feat: 评论接口对接
This commit is contained in:
@@ -17,7 +17,7 @@ VITE_TITLE_NAME='五味子云存储'
|
||||
VITE_APP_TOKEN_KEY='schisandra'
|
||||
|
||||
# the upload url
|
||||
VITE_UPLOAD_URL='http://127.0.0.1:3000'
|
||||
VITE_UPLOAD_URL='http://127.0.0.1:5050'
|
||||
|
||||
# the websocket url
|
||||
VITE_WEB_SOCKET_URL='ws://127.0.0.1:3010/wx/socket'
|
||||
|
@@ -1,4 +1,3 @@
|
||||
node_modules
|
||||
.eslintrc.cjs
|
||||
dist
|
||||
/src/components/Main/Home/index.tsx
|
||||
|
@@ -23,6 +23,7 @@
|
||||
"antd": "^5.19.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"axios": "^1.7.2",
|
||||
"base-64": "^1.0.0",
|
||||
"core-js": "^3.37.1",
|
||||
"crypto-js": "^4.2.0",
|
||||
"echarts-for-react": "^3.0.2",
|
||||
|
7
pnpm-lock.yaml
generated
7
pnpm-lock.yaml
generated
@@ -44,6 +44,9 @@ dependencies:
|
||||
axios:
|
||||
specifier: ^1.7.2
|
||||
version: 1.7.2
|
||||
base-64:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
core-js:
|
||||
specifier: ^3.37.1
|
||||
version: 3.37.1
|
||||
@@ -4647,6 +4650,10 @@ packages:
|
||||
resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==}
|
||||
dev: true
|
||||
|
||||
/base-64@1.0.0:
|
||||
resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==}
|
||||
dev: false
|
||||
|
||||
/base64-js@1.5.1:
|
||||
resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
|
||||
dev: true
|
||||
|
@@ -5,13 +5,15 @@ import web from "@/utils/axios/web.ts";
|
||||
/**
|
||||
* 初始化ali oss
|
||||
* @param data 用户id
|
||||
* @param Id id
|
||||
*/
|
||||
export const initAliOSS = (data: any) => {
|
||||
export const initAliOSS = (data: any, Id: any) => {
|
||||
return web.request({
|
||||
url: "/oss/oss/ali/init",
|
||||
method: "post",
|
||||
method: "get",
|
||||
params: {
|
||||
userId: data,
|
||||
Id: Id,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -59,3 +61,74 @@ export const getAllAliOSSConfig = (userId: any) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增阿里云oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const addAliOSSConfig = (data: API.AliOSSConfigRequest) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/ali/add`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 注销阿里云oss配置
|
||||
* @param userId
|
||||
* @param Id
|
||||
*/
|
||||
export const setAliShutdown = (userId: any, Id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/ali/shutdown`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
Id: Id,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 删除阿里云oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const deleteAliConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/ali/delete`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 修改阿里云oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const updateAliConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/ali/update`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取阿里云oss配置详情
|
||||
* @param id
|
||||
*/
|
||||
export const getAliConfigDetailById = (id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/ali/one`,
|
||||
method: "get",
|
||||
params: {
|
||||
id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@@ -167,3 +167,191 @@ export const getUserRecentPreviewFile = (userId: any) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取存储桶
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
*/
|
||||
export const deleteBucket = (userId: any, bucket: any, type: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/deleteBucket`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取存储桶大小
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
*/
|
||||
export const getBucketSize = (userId: any, bucket: any, type: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/getBucketSize`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 创建存储桶
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
*/
|
||||
export const creatBucket = (userId: any, bucket: any, type: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/createBucket`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 删除文件
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
* @param filePath
|
||||
*/
|
||||
export const deleteFile = (userId: any, bucket: any, type: any, filePath: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/deleteFile`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
filePath: filePath,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 下载文件
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
* @param listObjectsArgs
|
||||
*/
|
||||
export const downloadFiles = (userId: any, bucket: any, type: any, listObjectsArgs: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/downloadFile`,
|
||||
method: "get",
|
||||
responseType: "blob",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
listObjectsArgs: listObjectsArgs,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 预览文件
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
* @param filePath
|
||||
*/
|
||||
export const previewFile = (userId: any, bucket: any, type: any, filePath: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/previewFile`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
filePath: filePath,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 重命名文件
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
* @param oldFileName
|
||||
* @param newFileName
|
||||
*/
|
||||
export const renameFile = (
|
||||
userId: any,
|
||||
bucket: any,
|
||||
type: any,
|
||||
oldFileName: any,
|
||||
newFileName: any,
|
||||
) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/renameFile`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
oldFileName: oldFileName,
|
||||
newFileName: newFileName,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 拷贝文件
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
* @param oldFilePath
|
||||
* @param newFilePath
|
||||
*/
|
||||
export const copyFile = (
|
||||
userId: any,
|
||||
bucket: any,
|
||||
type: any,
|
||||
oldFilePath: any,
|
||||
newFilePath: any,
|
||||
) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/copyFile`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
oldFilePath: oldFilePath,
|
||||
newFilePath: newFilePath,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 创建存储桶
|
||||
* @param userId
|
||||
* @param bucket
|
||||
* @param type
|
||||
*/
|
||||
export const createBucket = (userId: any, bucket: any, type: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/createBucket`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
bucket: bucket,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 上传文件
|
||||
* @param type
|
||||
* @param data
|
||||
* @param peram
|
||||
*/
|
||||
export const uploadFiles = (type: any, data: any, peram: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/` + type + `/uploadFile`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
data: data,
|
||||
params: peram,
|
||||
});
|
||||
};
|
||||
|
@@ -5,13 +5,15 @@ import web from "@/utils/axios/web.ts";
|
||||
/**
|
||||
* 初始化minio
|
||||
* @param data 用户id
|
||||
* @param id
|
||||
*/
|
||||
export const initMinioOSS = (data: any) => {
|
||||
export const initMinioOSS = (data: any, id: any) => {
|
||||
return web.request({
|
||||
url: "/oss/oss/minio/init",
|
||||
method: "post",
|
||||
params: {
|
||||
userId: data,
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -58,3 +60,75 @@ export const getAllMinioConfig = (userId: any) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增阿里云oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const addMinioOSSConfig = (data: API.MinioOSSConfigRequest) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/minio/add`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 注销MinIo oss配置
|
||||
* @param userId
|
||||
* @param Id
|
||||
*/
|
||||
export const setMinioShutdown = (userId: any, Id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/minio/shutdown`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
Id: Id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除Minio oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const deleteMinioConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/minio/delete`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除Minio oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const updateMinioConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/minio/update`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取Minio oss配置详情
|
||||
* @param id
|
||||
*/
|
||||
export const getMinioConfigDetailById = (id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/minio/one`,
|
||||
method: "get",
|
||||
params: {
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@@ -5,13 +5,15 @@ import web from "@/utils/axios/web.ts";
|
||||
/**
|
||||
* 初始化qiniu
|
||||
* @param data 用户id
|
||||
* @param id
|
||||
*/
|
||||
export const initQiniuOSS = (data: any) => {
|
||||
export const initQiniuOSS = (data: any, id: any) => {
|
||||
return web.request({
|
||||
url: "/oss/oss/qiniu/init",
|
||||
method: "post",
|
||||
params: {
|
||||
userId: data,
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -55,3 +57,77 @@ export const getAllQiniuConfigs = (userId: any) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 新增七牛oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const addQiniuOSSConfig = (data: API.QiniuOSSConfigRequest) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/qiniu/add`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 注销 Qiniu oss配置
|
||||
* @param userId
|
||||
* @param Id
|
||||
*/
|
||||
export const setQiniuShutdown = (userId: any, Id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/qiniu/shutdown`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
Id: Id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除Qiniu oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const deleteQiniuConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/qiniu/delete`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新Qiniu oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const updateQiniuConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/qiniu/update`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取Qiniu oss配置
|
||||
* @param id
|
||||
*/
|
||||
export const getQiniuConfigDetailById = (id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/qiniu/one`,
|
||||
method: "get",
|
||||
params: {
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@@ -5,13 +5,15 @@ import web from "@/utils/axios/web.ts";
|
||||
/**
|
||||
* 初始化Tencent oss
|
||||
* @param data 用户id
|
||||
* @param id
|
||||
*/
|
||||
export const initTencentOSS = (data: any) => {
|
||||
export const initTencentOSS = (data: any, id: any) => {
|
||||
return web.request({
|
||||
url: "/oss/oss/ali/tencent",
|
||||
url: "/oss/oss/tencent/init",
|
||||
method: "post",
|
||||
params: {
|
||||
userId: data,
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
@@ -58,3 +60,76 @@ export const getAllTencentOSsConfig = (userId: any) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增腾讯云oss
|
||||
* @param data
|
||||
*/
|
||||
export const addTencentOSSConfig = (data: API.TencentOSSConfigRequest) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/tencent/add`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 注销 Tencent oss配置
|
||||
* @param userId
|
||||
* @param Id
|
||||
*/
|
||||
export const setTencentShutdown = (userId: any, Id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/tencent/shutdown`,
|
||||
method: "post",
|
||||
params: {
|
||||
userId: userId,
|
||||
Id: Id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 删除Tencent oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const deleteTencentConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/tencent/delete`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 更新Tencent oss配置
|
||||
* @param data
|
||||
*/
|
||||
export const updateTencentConfig = (data: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/tencent/update`,
|
||||
method: "post",
|
||||
headers: {
|
||||
"Content-Type": "application/json;charset=UTF-8",
|
||||
},
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 获取腾讯云oss配置详情
|
||||
* @param id
|
||||
*/
|
||||
export const getTencentConfigDetailById = (id: any) => {
|
||||
return web.request({
|
||||
url: `/oss/oss/tencent/one`,
|
||||
method: "get",
|
||||
params: {
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
123
src/api/share/index.ts
Normal file
123
src/api/share/index.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/** @format */
|
||||
|
||||
import web from "@/utils/axios/web.ts";
|
||||
|
||||
/**
|
||||
* 获取分享圈列表
|
||||
*/
|
||||
export const getShareCircleList = () => {
|
||||
return web.request({
|
||||
url: `/share/share/circle/sharelist`,
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增分享圈
|
||||
* @param data
|
||||
* @constructor
|
||||
*/
|
||||
export const addShareCircle = (data: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/circle/add`,
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 分享圈详情列表
|
||||
* @param circleId
|
||||
*/
|
||||
export const shareDetailList = (circleId: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/detail/list`,
|
||||
method: "post",
|
||||
params: {
|
||||
circleId: circleId,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 分享圈详情
|
||||
* @param id
|
||||
*/
|
||||
export const getShareDetail = (id: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/detail/get_detail`,
|
||||
method: "post",
|
||||
params: {
|
||||
Id: id,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增分享圈详情
|
||||
* @param data
|
||||
*/
|
||||
export const addShareDetail = (data: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/detail/add_detail`,
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 分享圈详情评论列表
|
||||
* @param detailId
|
||||
*/
|
||||
export const listComment = (detailId: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/comment/reply/listcomment`,
|
||||
method: "get",
|
||||
params: {
|
||||
detailId: detailId,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 分享圈详情回复列表
|
||||
* @param commentId
|
||||
*/
|
||||
export const listReply = (commentId: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/comment/reply/listreply`,
|
||||
method: "get",
|
||||
params: {
|
||||
commentId: commentId,
|
||||
},
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增评论
|
||||
* @param data
|
||||
*/
|
||||
export const addComment = (data: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/comment/reply/addcomment`,
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 新增回复
|
||||
* @param data
|
||||
*/
|
||||
export const addReply = (data: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/comment/reply/addreply`,
|
||||
method: "post",
|
||||
data: data,
|
||||
});
|
||||
};
|
||||
/**
|
||||
* 返回评论总数
|
||||
* @param detailId
|
||||
*/
|
||||
export const returnAllCommentAndReplyCount = (detailId: any) => {
|
||||
return web.request({
|
||||
url: `/share/share/comment/reply/returncount`,
|
||||
method: "post",
|
||||
params: {
|
||||
detailId: detailId,
|
||||
},
|
||||
});
|
||||
};
|
@@ -1,29 +1,20 @@
|
||||
/** @format */
|
||||
|
||||
import { Avatar, Button, message, Skeleton } from "antd";
|
||||
import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import styles from "./index.module.less";
|
||||
import { Avatar, Button, Form, Input, message, Modal, Popconfirm, Popover, Skeleton } from "antd";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ClusterOutlined, DeleteOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||
import bucket from "@/assets/icons/bucket.svg";
|
||||
import styles from "./index.module.less";
|
||||
import { creatBucket, deleteBucket, getBucketSize } from "@/api/oss";
|
||||
import { getAllAliOSsBucket } from "@/api/oss/ali";
|
||||
import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
|
||||
|
||||
const DrawerContext = createContext<{
|
||||
drawerVisit: boolean;
|
||||
setDrawerVisit: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}>({} as any);
|
||||
const AliDrawer = () => {
|
||||
const [drawerVisit, setDrawerVisit] = useState(false);
|
||||
return (
|
||||
<DrawerContext.Provider value={{ drawerVisit, setDrawerVisit }}>
|
||||
<ProCardComponent />
|
||||
</DrawerContext.Provider>
|
||||
);
|
||||
};
|
||||
const ProCardComponent = () => {
|
||||
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
|
||||
const [buckets, setBuckets] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [bucketSize, setBucketSize] = useState<string>("");
|
||||
const [form] = Form.useForm();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
|
||||
async function getAllBucket() {
|
||||
getAllAliOSsBucket("2").then((res: any) => {
|
||||
@@ -37,10 +28,11 @@ const ProCardComponent = () => {
|
||||
useEffect(() => {
|
||||
getAllBucket().then();
|
||||
}, []);
|
||||
|
||||
const bucketList = () => {
|
||||
return (
|
||||
<ProCard
|
||||
title={"阿里云OSS存储桶列表"}
|
||||
title={"MinIO存储桶列表"}
|
||||
headerBordered
|
||||
extra={
|
||||
<>
|
||||
@@ -53,7 +45,7 @@ const ProCardComponent = () => {
|
||||
getAllBucket().then();
|
||||
}}
|
||||
icon={<ReloadOutlined />}></Button>
|
||||
<Button type="primary" onClick={() => setDrawerVisit(true)}>
|
||||
<Button type="primary" onClick={() => setOpen(true)}>
|
||||
创建存储桶
|
||||
</Button>
|
||||
</>
|
||||
@@ -63,33 +55,90 @@ const ProCardComponent = () => {
|
||||
{buckets &&
|
||||
Array.from(buckets).map((item: any, index: number) => {
|
||||
return (
|
||||
<>
|
||||
<div key={index}>
|
||||
<ProCard
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
title={<b>{item.name}</b>}
|
||||
style={{
|
||||
width: "180px",
|
||||
height: 150,
|
||||
borderWidth: "1px",
|
||||
marginLeft: 10,
|
||||
}}
|
||||
actions={[
|
||||
<SettingOutlined key="setting" />,
|
||||
<EditOutlined key="edit" />,
|
||||
<EllipsisOutlined key="ellipsis" />,
|
||||
]}>
|
||||
<Avatar
|
||||
shape={"square"}
|
||||
src={bucket as any}
|
||||
size={"large"}
|
||||
/>
|
||||
<b style={{ marginLeft: 10 }}>{item.size}</b>
|
||||
</ProCard>
|
||||
</div>
|
||||
</>
|
||||
<div key={index}>
|
||||
<ProCard
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
// title={}
|
||||
style={{
|
||||
width: "180px",
|
||||
marginLeft: 10,
|
||||
}}
|
||||
actions={[
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popover
|
||||
content={bucketSize}
|
||||
title={`size:`}
|
||||
trigger="click">
|
||||
<ClusterOutlined
|
||||
key={"calculate"}
|
||||
onClick={() => {
|
||||
getBucketSize(
|
||||
1,
|
||||
item.name,
|
||||
"minio",
|
||||
).then((res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.success &&
|
||||
res.data
|
||||
) {
|
||||
setBucketSize(res.data);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: "计算出错!",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Popover>,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popconfirm
|
||||
title={`删除存储桶:${item.name}`}
|
||||
description="你知道你要做什么吗?"
|
||||
onConfirm={() => {
|
||||
deleteBucket(1, item.name, "minio").then(
|
||||
(res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.data &&
|
||||
res.data === "success"
|
||||
) {
|
||||
message
|
||||
.open({
|
||||
content: "删除成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No">
|
||||
<DeleteOutlined key="delete" />
|
||||
</Popconfirm>,
|
||||
]}>
|
||||
<Avatar
|
||||
shape={"square"}
|
||||
src={bucket as any}
|
||||
size={"large"}
|
||||
/>
|
||||
<b style={{ marginLeft: 5 }}>{item.name}</b>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Skeleton>
|
||||
@@ -101,32 +150,49 @@ const ProCardComponent = () => {
|
||||
return (
|
||||
<>
|
||||
{bucketList()}
|
||||
<DrawerForm
|
||||
<Modal
|
||||
title="创建存储桶"
|
||||
open={drawerVisit}
|
||||
onOpenChange={setDrawerVisit}
|
||||
onFinish={async (values) => {
|
||||
console.log(values.name);
|
||||
message.success("提交成功");
|
||||
return true;
|
||||
}}>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
width="md"
|
||||
width={"30%"}
|
||||
open={open}
|
||||
closable={true}
|
||||
onOk={() => {
|
||||
const bucketName = form.getFieldValue("name" as any);
|
||||
if (bucketName === "" || bucketName === null) {
|
||||
message.open({
|
||||
content: " 请输入存储桶名称!",
|
||||
type: "warning",
|
||||
});
|
||||
} else {
|
||||
creatBucket(1, bucketName, "ali").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message
|
||||
.open({
|
||||
content: "创建成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
setOpen(false);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
onCancel={() => setOpen(false)}>
|
||||
<Form layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="存储桶名字"
|
||||
tooltip="最长为 24 位"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="capacity"
|
||||
label="我方公司名称"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</DrawerForm>
|
||||
label="存储桶名称"
|
||||
rules={[{ required: true, message: "请输入存储桶名称!" }]}>
|
||||
<Input placeholder="请输入存储桶名称!" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -1,29 +1,20 @@
|
||||
/** @format */
|
||||
|
||||
import { Avatar, Button, message, Skeleton } from "antd";
|
||||
import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
|
||||
import { Avatar, Button, Form, Input, message, Modal, Popconfirm, Popover, Skeleton } from "antd";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ClusterOutlined, DeleteOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||
import bucket from "@/assets/icons/bucket.svg";
|
||||
import styles from "./index.module.less";
|
||||
import { getAllMinioBucket } from "@/api/oss/minio";
|
||||
import { creatBucket, deleteBucket, getBucketSize } from "@/api/oss";
|
||||
|
||||
const DrawerContext = createContext<{
|
||||
drawerVisit: boolean;
|
||||
setDrawerVisit: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}>({} as any);
|
||||
const MinioDrawer = () => {
|
||||
const [drawerVisit, setDrawerVisit] = useState(false);
|
||||
return (
|
||||
<DrawerContext.Provider value={{ drawerVisit, setDrawerVisit }}>
|
||||
<ProCardComponent />
|
||||
</DrawerContext.Provider>
|
||||
);
|
||||
};
|
||||
const ProCardComponent = () => {
|
||||
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
|
||||
const [buckets, setBuckets] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [bucketSize, setBucketSize] = useState<string>("");
|
||||
const [form] = Form.useForm();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
|
||||
async function getAllBucket() {
|
||||
getAllMinioBucket("1").then((res: any) => {
|
||||
@@ -53,7 +44,7 @@ const ProCardComponent = () => {
|
||||
getAllBucket().then();
|
||||
}}
|
||||
icon={<ReloadOutlined />}></Button>
|
||||
<Button type="primary" onClick={() => setDrawerVisit(true)}>
|
||||
<Button type="primary" onClick={() => setOpen(true)}>
|
||||
创建存储桶
|
||||
</Button>
|
||||
</>
|
||||
@@ -68,23 +59,83 @@ const ProCardComponent = () => {
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
title={<b>{item.name}</b>}
|
||||
// title={}
|
||||
style={{
|
||||
width: "180px",
|
||||
height: "150px",
|
||||
marginLeft: 10,
|
||||
width: "200px",
|
||||
marginLeft: 20,
|
||||
}}
|
||||
actions={[
|
||||
<SettingOutlined key="setting" />,
|
||||
<EditOutlined key="edit" />,
|
||||
<EllipsisOutlined key="ellipsis" />,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popover
|
||||
content={bucketSize}
|
||||
title={`size:`}
|
||||
trigger="click">
|
||||
<ClusterOutlined
|
||||
key={"calculate"}
|
||||
onClick={() => {
|
||||
getBucketSize(
|
||||
1,
|
||||
item.name,
|
||||
"minio",
|
||||
).then((res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.success &&
|
||||
res.data
|
||||
) {
|
||||
setBucketSize(res.data);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: "计算出错!",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Popover>,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popconfirm
|
||||
title={`删除存储桶:${item.name}`}
|
||||
description="你知道你要做什么吗?"
|
||||
onConfirm={() => {
|
||||
deleteBucket(1, item.name, "minio").then(
|
||||
(res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.data &&
|
||||
res.data === "success"
|
||||
) {
|
||||
message
|
||||
.open({
|
||||
content: "删除成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No">
|
||||
<DeleteOutlined key="delete" />
|
||||
</Popconfirm>,
|
||||
]}>
|
||||
<Avatar
|
||||
shape={"square"}
|
||||
src={bucket as any}
|
||||
size={"large"}
|
||||
/>
|
||||
<b style={{ marginLeft: 10 }}>{item.size}</b>
|
||||
<b style={{ marginLeft: 5 }}>{item.name}</b>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
@@ -98,32 +149,49 @@ const ProCardComponent = () => {
|
||||
return (
|
||||
<>
|
||||
{bucketList()}
|
||||
<DrawerForm
|
||||
<Modal
|
||||
title="创建存储桶"
|
||||
open={drawerVisit}
|
||||
onOpenChange={setDrawerVisit}
|
||||
onFinish={async (values) => {
|
||||
console.log(values.name);
|
||||
message.success("提交成功");
|
||||
return true;
|
||||
}}>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
width="md"
|
||||
width={"30%"}
|
||||
open={open}
|
||||
closable={true}
|
||||
onOk={() => {
|
||||
const bucketName = form.getFieldValue("name" as any);
|
||||
if (bucketName === "" || bucketName === null) {
|
||||
message.open({
|
||||
content: " 请输入存储桶名称!",
|
||||
type: "warning",
|
||||
});
|
||||
} else {
|
||||
creatBucket(1, bucketName, "minio").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message
|
||||
.open({
|
||||
content: "创建成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
setOpen(false);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
onCancel={() => setOpen(false)}>
|
||||
<Form layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="存储桶名字"
|
||||
tooltip="最长为 24 位"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="capacity"
|
||||
label="我方公司名称"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</DrawerForm>
|
||||
label="存储桶名称"
|
||||
rules={[{ required: true, message: "请输入存储桶名称!" }]}>
|
||||
<Input placeholder="请输入存储桶名称!" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -6,7 +6,6 @@ import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { EditOutlined, EllipsisOutlined, ReloadOutlined, SettingOutlined } from "@ant-design/icons";
|
||||
import bucket from "@/assets/icons/bucket.svg";
|
||||
import styles from "./index.module.less";
|
||||
import { getAllMinioBucket } from "@/api/oss/minio";
|
||||
import { getAllQiniuBucket } from "@/api/oss/qiniu";
|
||||
|
||||
const DrawerContext = createContext<{
|
||||
|
@@ -1,83 +1,147 @@
|
||||
/** @format */
|
||||
|
||||
import { Avatar, Button, message } from "antd";
|
||||
import {
|
||||
DrawerForm,
|
||||
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 { Avatar, Button, Form, Input, message, Modal, Popconfirm, Popover, Skeleton } from "antd";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ClusterOutlined, DeleteOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||
import bucket from "@/assets/icons/bucket.svg";
|
||||
import styles from "./index.module.less";
|
||||
import { getAllMinioBucket } from "@/api/oss/minio";
|
||||
import { creatBucket, deleteBucket, getBucketSize } from "@/api/oss";
|
||||
|
||||
const DrawerContext = createContext<{
|
||||
drawerVisit: boolean;
|
||||
setDrawerVisit: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}>({} as any);
|
||||
const QiniuDrawer = () => {
|
||||
const [drawerVisit, setDrawerVisit] = useState(false);
|
||||
return (
|
||||
<DrawerContext.Provider value={{ drawerVisit, setDrawerVisit }}>
|
||||
<ProCardComponent />
|
||||
</DrawerContext.Provider>
|
||||
);
|
||||
};
|
||||
const ProCardComponent = () => {
|
||||
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
|
||||
const list = [
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test3",
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
];
|
||||
const [buckets, setBuckets] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [bucketSize, setBucketSize] = useState<string>("");
|
||||
const [form] = Form.useForm();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
|
||||
async function getAllBucket() {
|
||||
getAllMinioBucket("1").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
setBuckets(res.data);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getAllBucket().then();
|
||||
}, []);
|
||||
|
||||
const bucketList = () => {
|
||||
return (
|
||||
<ProCard
|
||||
title={"存储桶列表"}
|
||||
title={"MinIO存储桶列表"}
|
||||
headerBordered
|
||||
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={() => setOpen(true)}>
|
||||
创建存储桶
|
||||
</Button>
|
||||
</>
|
||||
}>
|
||||
<div className={styles.div_proCard}>
|
||||
{list.map((item, index) => {
|
||||
return (
|
||||
<ProCard
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
key={index}
|
||||
title={<b>名字:{item}</b>}
|
||||
style={{
|
||||
width: "180px",
|
||||
borderWidth: "1px",
|
||||
}}
|
||||
actions={[
|
||||
<SettingOutlined key="setting" />,
|
||||
<EditOutlined key="edit" />,
|
||||
<EllipsisOutlined key="ellipsis" />,
|
||||
]}>
|
||||
<Avatar shape={"square"} src={bucket} size={"large"} />
|
||||
<b style={{ marginLeft: 10 }}> size</b>
|
||||
</ProCard>
|
||||
);
|
||||
})}
|
||||
<Skeleton loading={loading} paragraph={{ rows: 13 }} active>
|
||||
{buckets &&
|
||||
Array.from(buckets).map((item: any, index: number) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<ProCard
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
// title={}
|
||||
style={{
|
||||
width: "180px",
|
||||
marginLeft: 10,
|
||||
}}
|
||||
actions={[
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popover
|
||||
content={bucketSize}
|
||||
title={`size:`}
|
||||
trigger="click">
|
||||
<ClusterOutlined
|
||||
key={"calculate"}
|
||||
onClick={() => {
|
||||
getBucketSize(
|
||||
1,
|
||||
item.name,
|
||||
"minio",
|
||||
).then((res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.success &&
|
||||
res.data
|
||||
) {
|
||||
setBucketSize(res.data);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: "计算出错!",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Popover>,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popconfirm
|
||||
title={`删除存储桶:${item.name}`}
|
||||
description="你知道你要做什么吗?"
|
||||
onConfirm={() => {
|
||||
deleteBucket(1, item.name, "minio").then(
|
||||
(res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.data &&
|
||||
res.data === "success"
|
||||
) {
|
||||
message
|
||||
.open({
|
||||
content: "删除成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No">
|
||||
<DeleteOutlined key="delete" />
|
||||
</Popconfirm>,
|
||||
]}>
|
||||
<Avatar
|
||||
shape={"square"}
|
||||
src={bucket as any}
|
||||
size={"large"}
|
||||
/>
|
||||
<b style={{ marginLeft: 5 }}>{item.name}</b>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Skeleton>
|
||||
</div>
|
||||
</ProCard>
|
||||
);
|
||||
@@ -86,32 +150,49 @@ const ProCardComponent = () => {
|
||||
return (
|
||||
<>
|
||||
{bucketList()}
|
||||
<DrawerForm
|
||||
<Modal
|
||||
title="创建存储桶"
|
||||
open={drawerVisit}
|
||||
onOpenChange={setDrawerVisit}
|
||||
onFinish={async (values) => {
|
||||
console.log(values.name);
|
||||
message.success("提交成功");
|
||||
return true;
|
||||
}}>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
width="md"
|
||||
width={"30%"}
|
||||
open={open}
|
||||
closable={true}
|
||||
onOk={() => {
|
||||
const bucketName = form.getFieldValue("name" as any);
|
||||
if (bucketName === "" || bucketName === null) {
|
||||
message.open({
|
||||
content: " 请输入存储桶名称!",
|
||||
type: "warning",
|
||||
});
|
||||
} else {
|
||||
creatBucket(1, bucketName, "qiniu").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message
|
||||
.open({
|
||||
content: "创建成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
setOpen(false);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
onCancel={() => setOpen(false)}>
|
||||
<Form layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="存储桶名字"
|
||||
tooltip="最长为 24 位"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="capacity"
|
||||
label="我方公司名称"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</DrawerForm>
|
||||
label="存储桶名称"
|
||||
rules={[{ required: true, message: "请输入存储桶名称!" }]}>
|
||||
<Input placeholder="请输入存储桶名称!" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -1,32 +1,23 @@
|
||||
/** @format */
|
||||
|
||||
import { Avatar, Button, message, Skeleton } from "antd";
|
||||
import { DrawerForm, ProCard, ProForm, ProFormText } from "@ant-design/pro-components";
|
||||
import React, { createContext, useContext, useEffect, useState } from "react";
|
||||
import { EditOutlined, EllipsisOutlined, SettingOutlined } from "@ant-design/icons";
|
||||
import bucket from "../../../../assets/icons/bucket.svg";
|
||||
import { Avatar, Button, Form, Input, message, Modal, Popconfirm, Popover, Skeleton } from "antd";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { ClusterOutlined, DeleteOutlined, ReloadOutlined } from "@ant-design/icons";
|
||||
import bucket from "@/assets/icons/bucket.svg";
|
||||
import styles from "./index.module.less";
|
||||
import { getAllTencentOSsBucket } from "@/api/oss/tencent";
|
||||
import { getAllMinioBucket } from "@/api/oss/minio";
|
||||
import { creatBucket, deleteBucket, getBucketSize } from "@/api/oss";
|
||||
|
||||
const DrawerContext = createContext<{
|
||||
drawerVisit: boolean;
|
||||
setDrawerVisit: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
}>({} as any);
|
||||
const TencentDrawer = () => {
|
||||
const [drawerVisit, setDrawerVisit] = useState(false);
|
||||
return (
|
||||
<DrawerContext.Provider value={{ drawerVisit, setDrawerVisit }}>
|
||||
<ProCardComponent />
|
||||
</DrawerContext.Provider>
|
||||
);
|
||||
};
|
||||
const ProCardComponent = () => {
|
||||
const { drawerVisit, setDrawerVisit } = useContext(DrawerContext);
|
||||
const [buckets, setBuckets] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [bucketSize, setBucketSize] = useState<string>("");
|
||||
const [form] = Form.useForm();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
|
||||
async function getAllBucket() {
|
||||
getAllTencentOSsBucket("1").then((res: any) => {
|
||||
getAllMinioBucket("1").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
setBuckets(res.data);
|
||||
setLoading(false);
|
||||
@@ -41,12 +32,23 @@ const ProCardComponent = () => {
|
||||
const bucketList = () => {
|
||||
return (
|
||||
<ProCard
|
||||
title={"腾讯云COS存储桶列表"}
|
||||
title={"MinIO存储桶列表"}
|
||||
headerBordered
|
||||
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={() => setOpen(true)}>
|
||||
创建存储桶
|
||||
</Button>
|
||||
</>
|
||||
}>
|
||||
<div className={styles.div_proCard}>
|
||||
<Skeleton loading={loading} paragraph={{ rows: 13 }} active>
|
||||
@@ -58,23 +60,83 @@ const ProCardComponent = () => {
|
||||
headStyle={{ backgroundColor: "#f0f2f5" }}
|
||||
hoverable
|
||||
bordered
|
||||
title={<b>{item.name}</b>}
|
||||
// title={}
|
||||
style={{
|
||||
width: "180px",
|
||||
height: "150px",
|
||||
marginLeft: 10,
|
||||
}}
|
||||
actions={[
|
||||
<SettingOutlined key="setting" />,
|
||||
<EditOutlined key="edit" />,
|
||||
<EllipsisOutlined key="ellipsis" />,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popover
|
||||
content={bucketSize}
|
||||
title={`size:`}
|
||||
trigger="click">
|
||||
<ClusterOutlined
|
||||
key={"calculate"}
|
||||
onClick={() => {
|
||||
getBucketSize(
|
||||
1,
|
||||
item.name,
|
||||
"minio",
|
||||
).then((res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.success &&
|
||||
res.data
|
||||
) {
|
||||
setBucketSize(res.data);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: "计算出错!",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</Popover>,
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<Popconfirm
|
||||
title={`删除存储桶:${item.name}`}
|
||||
description="你知道你要做什么吗?"
|
||||
onConfirm={() => {
|
||||
deleteBucket(1, item.name, "minio").then(
|
||||
(res: any) => {
|
||||
if (
|
||||
res &&
|
||||
res.data &&
|
||||
res.data === "success"
|
||||
) {
|
||||
message
|
||||
.open({
|
||||
content: "删除成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
},
|
||||
);
|
||||
}}
|
||||
okText="Yes"
|
||||
cancelText="No">
|
||||
<DeleteOutlined key="delete" />
|
||||
</Popconfirm>,
|
||||
]}>
|
||||
<Avatar
|
||||
shape={"square"}
|
||||
src={bucket as any}
|
||||
size={"large"}
|
||||
/>
|
||||
<b style={{ marginLeft: 10 }}>{item.size}</b>
|
||||
<b style={{ marginLeft: 5 }}>{item.name}</b>
|
||||
</ProCard>
|
||||
</div>
|
||||
);
|
||||
@@ -88,32 +150,49 @@ const ProCardComponent = () => {
|
||||
return (
|
||||
<>
|
||||
{bucketList()}
|
||||
<DrawerForm
|
||||
<Modal
|
||||
title="创建存储桶"
|
||||
open={drawerVisit}
|
||||
onOpenChange={setDrawerVisit}
|
||||
onFinish={async (values) => {
|
||||
console.log(values.name);
|
||||
message.success("提交成功");
|
||||
return true;
|
||||
}}>
|
||||
<ProForm.Group>
|
||||
<ProFormText
|
||||
width="md"
|
||||
width={"30%"}
|
||||
open={open}
|
||||
closable={true}
|
||||
onOk={() => {
|
||||
const bucketName = form.getFieldValue("name" as any);
|
||||
if (bucketName === "" || bucketName === null) {
|
||||
message.open({
|
||||
content: " 请输入存储桶名称!",
|
||||
type: "warning",
|
||||
});
|
||||
} else {
|
||||
creatBucket(1, bucketName, "tencent").then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message
|
||||
.open({
|
||||
content: "创建成功!",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
setOpen(false);
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
onCancel={() => setOpen(false)}>
|
||||
<Form layout="vertical" form={form}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="存储桶名字"
|
||||
tooltip="最长为 24 位"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
|
||||
<ProFormText
|
||||
width="md"
|
||||
name="capacity"
|
||||
label="我方公司名称"
|
||||
placeholder="请输入名称"
|
||||
/>
|
||||
</ProForm.Group>
|
||||
</DrawerForm>
|
||||
label="存储桶名称"
|
||||
rules={[{ required: true, message: "请输入存储桶名称!" }]}>
|
||||
<Input placeholder="请输入存储桶名称!" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -1,34 +1,68 @@
|
||||
/** @format */
|
||||
|
||||
import React from "react";
|
||||
import { Avatar, Card, Flex, Input, message, Select, Upload } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Avatar, Card, Flex, Input, message, Progress, Select, Upload } from "antd";
|
||||
import { CloudUploadOutlined } from "@ant-design/icons";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import selectOptions from "@/components/Main/Settings/settings.ts";
|
||||
import StorageIcon from "@/constant/stroage-icon.ts";
|
||||
import { getStorageBuckets, uploadFiles } from "@/api/oss";
|
||||
import useStore from "@/utils/store/useStore.tsx";
|
||||
import axios from "axios";
|
||||
|
||||
const { Dragger } = Upload;
|
||||
const props: any = {
|
||||
name: "file",
|
||||
multiple: true,
|
||||
directory: true,
|
||||
action: "https://660d2bd96ddfa2943b33731c.mockapi.io/api/upload",
|
||||
onChange(info: any) {
|
||||
const { status } = info.file;
|
||||
if (status !== "uploading") {
|
||||
console.log(info.file, info.fileList);
|
||||
|
||||
const FileUpload: React.FC = (props: any) => {
|
||||
const [buckets, setBuckets] = useState<any[]>([]);
|
||||
const store = useStore("file");
|
||||
const [defaultFileList, setDefaultFileList] = useState([]);
|
||||
async function getBuckets(type: any) {
|
||||
getStorageBuckets("1", type).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
setBuckets(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
const handleOnChange = ({ fileList }) => {
|
||||
setDefaultFileList(fileList);
|
||||
};
|
||||
|
||||
const uploadFile = async (options) => {
|
||||
const { onSuccess, onError, file, onProgress } = options;
|
||||
if (
|
||||
store.getUploadFilePath() === null ||
|
||||
(store.getUploadFileBucket() === null && store.getUploadFileStorage() === null)
|
||||
) {
|
||||
message.open({
|
||||
content: "请选择存储桶和存储路径",
|
||||
type: "error",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (status === "done") {
|
||||
message.success(`${info.file.name} file uploaded successfully.`);
|
||||
} else if (status === "error") {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
},
|
||||
onDrop(e: any) {
|
||||
console.log("Dropped files", e.dataTransfer.files);
|
||||
},
|
||||
};
|
||||
const FileUpload: React.FC = () => {
|
||||
const fileData = new FormData();
|
||||
fileData.append("file", file);
|
||||
const formData: any = {
|
||||
userId: "1",
|
||||
bucketName: store.getUploadFileBucket(),
|
||||
path: store.getUploadFilePath(),
|
||||
};
|
||||
console.log(formData);
|
||||
uploadFiles(store.getUploadFileStorage(), fileData, formData).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "上传成功",
|
||||
type: "success",
|
||||
});
|
||||
onSuccess(res.success);
|
||||
} else {
|
||||
message.open({
|
||||
content: "上传失败",
|
||||
type: "error",
|
||||
});
|
||||
setDefaultFileList([]);
|
||||
onError(res.success);
|
||||
}
|
||||
});
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -45,11 +79,24 @@ const FileUpload: React.FC = () => {
|
||||
}}
|
||||
showSearch={true}
|
||||
allowClear={true}
|
||||
notFoundContent={"未找到,请先配置存储商"}
|
||||
placeholder={"请选择存储商"}>
|
||||
{selectOptions.map((storage: any, index: any) => {
|
||||
onSelect={(value: any) => {
|
||||
store.setUploadFileStorage(value);
|
||||
getBuckets(value).then();
|
||||
}}
|
||||
onClear={() => {
|
||||
store.setUploadFileStorage("");
|
||||
setBuckets([]);
|
||||
}}
|
||||
onChange={(value: any) => {
|
||||
store.setUploadFileStorage(value);
|
||||
}}
|
||||
fieldNames={{
|
||||
label: "name",
|
||||
value: "ossType",
|
||||
}}
|
||||
labelRender={(label: any) => {
|
||||
return (
|
||||
<Select.Option value={storage.value} key={index}>
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
@@ -59,22 +106,46 @@ const FileUpload: React.FC = () => {
|
||||
flexDirection: "row",
|
||||
}}
|
||||
size={"small"}>
|
||||
<Avatar
|
||||
src={StorageIcon[storage.value]}
|
||||
size={"small"}
|
||||
/>{" "}
|
||||
<Avatar src={StorageIcon[label.value]} size={"small"} />
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{storage.name}
|
||||
{label.label}
|
||||
</span>
|
||||
</Card>
|
||||
</Select.Option>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
}}
|
||||
options={props.userStorage}
|
||||
notFoundContent={"未找到,请先配置存储商"}
|
||||
optionRender={(item: any) => {
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
height: 35,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
size={"small"}>
|
||||
<Avatar src={StorageIcon[item.value]} size={"small"} />
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{item.label}
|
||||
</span>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
placeholder={"请选择存储商"}></Select>
|
||||
|
||||
<Select
|
||||
size="large"
|
||||
status="warning"
|
||||
@@ -85,13 +156,55 @@ const FileUpload: React.FC = () => {
|
||||
alignItems: "center",
|
||||
marginLeft: "10px",
|
||||
}}
|
||||
onSelect={(value: any) => {
|
||||
store.setUploadFileBucket(value);
|
||||
}}
|
||||
onClear={() => {
|
||||
store.setUploadFileBucket("");
|
||||
setBuckets([]);
|
||||
}}
|
||||
onChange={(value: any) => {
|
||||
store.setUploadFileBucket(value);
|
||||
}}
|
||||
showSearch={true}
|
||||
allowClear={true}
|
||||
notFoundContent={"未找到,请先配置存储商"}
|
||||
placeholder={"请选择存储桶"}>
|
||||
{selectOptions.map((storage: any, index: any) => {
|
||||
fieldNames={{
|
||||
label: "name",
|
||||
value: "name",
|
||||
}}
|
||||
labelRender={(label: any) => {
|
||||
return (
|
||||
<Select.Option value={storage.value} key={index}>
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
height: 35,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
size={"small"}>
|
||||
<Avatar
|
||||
src={StorageIcon["bucket"]}
|
||||
shape={"square"}
|
||||
size={"small"}
|
||||
/>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{label.label}
|
||||
</span>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
options={buckets}
|
||||
optionRender={(item: any) => {
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
@@ -111,24 +224,41 @@ const FileUpload: React.FC = () => {
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{storage.name}
|
||||
{item.label}
|
||||
</span>
|
||||
</Card>
|
||||
</Select.Option>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
<Input placeholder={"请输入路径/默认当前打开的路径"} style={{ marginLeft: 10,width: "40%" }}></Input>
|
||||
}}
|
||||
placeholder={"请选择存储桶"}></Select>
|
||||
<Input
|
||||
placeholder={"请输入路径/默认当前打开的路径"}
|
||||
onChange={(e: any) => {
|
||||
store.setUploadFilePath(e.target.value);
|
||||
}}
|
||||
style={{ marginLeft: 10, width: "40%" }}></Input>
|
||||
</Flex>
|
||||
</ProCard>
|
||||
</Flex>
|
||||
<ProCard>
|
||||
<Dragger {...props}>
|
||||
<Dragger
|
||||
name={"file"}
|
||||
multiple={false}
|
||||
directory={false}
|
||||
maxCount={1}
|
||||
defaultFileList={defaultFileList}
|
||||
headers={{
|
||||
ContentType: "multipart/form-data",
|
||||
}}
|
||||
onChange={handleOnChange}
|
||||
customRequest={uploadFile}
|
||||
onDrop={() => uploadFile}>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<CloudUploadOutlined />
|
||||
</p>
|
||||
|
||||
<p className="ant-upload-text">单击或拖动文件到此区域进行上传</p>
|
||||
<p className="ant-upload-hint">支持单次或批量上传。</p>
|
||||
<p className="ant-upload-hint">只支持单次上传。</p>
|
||||
</Dragger>
|
||||
</ProCard>
|
||||
</>
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/** @format */
|
||||
import React, { memo, useEffect, useState } from "react";
|
||||
import { Avatar, Card, Flex, message, Skeleton, Space, Tag, Tooltip } from "antd";
|
||||
import { Avatar, Card, Flex, message, Skeleton, Tooltip } from "antd";
|
||||
import styles from "./index.module.less";
|
||||
import ReactECharts from "echarts-for-react";
|
||||
import { ProCard, ProList } from "@ant-design/pro-components";
|
||||
@@ -17,11 +17,13 @@ import {
|
||||
getUserDownloadFileDiagramPerMonth,
|
||||
getUserFileCount,
|
||||
getUserFileFlow,
|
||||
getUserFileHeatMap, getUserRecentDownloadFile, getUserRecentPreviewFile, getUserRecentUploadFile,
|
||||
getUserUploadFileDiagramPerMonth
|
||||
getUserFileHeatMap,
|
||||
getUserRecentPreviewFile,
|
||||
getUserRecentUploadFile,
|
||||
getUserUploadFileDiagramPerMonth,
|
||||
} from "@/api/oss";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { EyeOutlined, InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { InfoCircleOutlined } from "@ant-design/icons";
|
||||
import FileIcon from "@/constant/file-icon.ts";
|
||||
import file_icon from "@/assets/icons/files/file.svg";
|
||||
|
||||
@@ -42,10 +44,9 @@ const MainHome: React.FC = () => {
|
||||
const [monthUpload, setMonthUpload] = useState<any>([]);
|
||||
const [monthDownload, setMonthDownload] = useState<any>([]);
|
||||
const [recentUploadFile, setRecentUploadFile] = useState<any>([]);
|
||||
const [recentDownloadFile, setRecentDownloadFile] = useState<any>([]);
|
||||
// const [recentDownloadFile, setRecentDownloadFile] = useState<any>([]);
|
||||
const [recentPreviewFile, setRecentPreviewFile] = useState<any>([]);
|
||||
|
||||
|
||||
// 获取存储同和存储商的个数
|
||||
async function getStorageAndBucketsCount() {
|
||||
return getStorageAndBuckets("1").then((res: any) => {
|
||||
@@ -101,7 +102,7 @@ const MainHome: React.FC = () => {
|
||||
if (res && res.success && res.data) {
|
||||
setMonthUpload(res.data);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
// 获取用户最近上传文件
|
||||
async function getRecentUploadFile() {
|
||||
@@ -109,23 +110,23 @@ const MainHome: React.FC = () => {
|
||||
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 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){
|
||||
getUserRecentPreviewFile(1).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setRecentPreviewFile(res.data);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
const option = {
|
||||
tooltip: {
|
||||
@@ -145,15 +146,17 @@ const MainHome: React.FC = () => {
|
||||
height: "80%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: [{
|
||||
type: "time",
|
||||
// data: month,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#999",
|
||||
xAxis: [
|
||||
{
|
||||
type: "time",
|
||||
// data: month,
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: "#999",
|
||||
},
|
||||
},
|
||||
},
|
||||
}],
|
||||
],
|
||||
yAxis: {
|
||||
type: "value",
|
||||
|
||||
@@ -257,9 +260,8 @@ const MainHome: React.FC = () => {
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getStorageAndBucketsCount().then(()=>{
|
||||
getStorageAndBucketsCount().then(() => {
|
||||
getUploadDownloadFlux().then(() => {
|
||||
getUploadDownloadCount().then(() => {
|
||||
setLoading(false);
|
||||
@@ -268,27 +270,25 @@ const MainHome: React.FC = () => {
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
getFileHeatMap().then(()=>{
|
||||
getFileHeatMap().then(() => {
|
||||
setLoadingHeatmap(false);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getDownloadCountByMonth().then(()=>{
|
||||
getUploadCountByMonth().then(()=>{
|
||||
getDownloadCountByMonth().then(() => {
|
||||
getUploadCountByMonth().then(() => {
|
||||
setLoadingEChart(false);
|
||||
});
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
getRecentUploadFile().then(()=>{
|
||||
getRecentUploadFile().then(() => {
|
||||
setLoadingRecentFile(false);
|
||||
});
|
||||
getRecentPreviewFile().then(()=>{
|
||||
getRecentPreviewFile().then(() => {
|
||||
setLoadingPreviewFile(false);
|
||||
});
|
||||
}, []);
|
||||
@@ -343,11 +343,20 @@ const MainHome: React.FC = () => {
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"} justify={"flex-end"} style={{marginTop: 50}}>
|
||||
<Tooltip title={"存储商个数,点击查看详情"} color={"#47D8BE"}>
|
||||
<InfoCircleOutlined onClick={()=>{
|
||||
navigate("/main/setting")
|
||||
}} className={styles.home_content_icon}/>
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
justify={"flex-end"}
|
||||
style={{ marginTop: 50 }}>
|
||||
<Tooltip
|
||||
title={"存储商个数,点击查看详情"}
|
||||
color={"#47D8BE"}>
|
||||
<InfoCircleOutlined
|
||||
onClick={() => {
|
||||
navigate("/main/setting");
|
||||
}}
|
||||
className={styles.home_content_icon}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -395,11 +404,20 @@ const MainHome: React.FC = () => {
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"} justify={"flex-end"} style={{marginTop: 50}}>
|
||||
<Tooltip title={"存储桶个数,点击查看详情"} color={"#47D8BE"}>
|
||||
<InfoCircleOutlined onClick={()=>{
|
||||
navigate("/main/bucket")
|
||||
}} className={styles.home_content_icon}/>
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
justify={"flex-end"}
|
||||
style={{ marginTop: 50 }}>
|
||||
<Tooltip
|
||||
title={"存储桶个数,点击查看详情"}
|
||||
color={"#47D8BE"}>
|
||||
<InfoCircleOutlined
|
||||
onClick={() => {
|
||||
navigate("/main/bucket");
|
||||
}}
|
||||
className={styles.home_content_icon}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -567,25 +585,27 @@ const MainHome: React.FC = () => {
|
||||
showMonthLabels={true}
|
||||
horizontal={true}
|
||||
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();
|
||||
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={[
|
||||
"一月",
|
||||
@@ -632,36 +652,43 @@ const MainHome: React.FC = () => {
|
||||
dataIndex: "fileName",
|
||||
},
|
||||
avatar: {
|
||||
render: (text: any,record: any) => {
|
||||
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"}
|
||||
/>
|
||||
</>)
|
||||
render: (_: any, record: any) => {
|
||||
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: {
|
||||
dataIndex: "size",
|
||||
valueType: "text"
|
||||
valueType: "text",
|
||||
},
|
||||
content: {
|
||||
dataIndex: "time"
|
||||
}
|
||||
dataIndex: "time",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Skeleton>
|
||||
@@ -682,36 +709,43 @@ const MainHome: React.FC = () => {
|
||||
dataIndex: "fileName",
|
||||
},
|
||||
avatar: {
|
||||
render: (text: any,record: any) => {
|
||||
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"}
|
||||
/>
|
||||
</>)
|
||||
render: (_: any, record: any) => {
|
||||
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: {
|
||||
dataIndex: "size",
|
||||
valueType: "text",
|
||||
},
|
||||
content: {
|
||||
dataIndex: "time"
|
||||
}
|
||||
dataIndex: "time",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Skeleton>
|
||||
|
@@ -2,118 +2,235 @@
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import type { ActionType, ProColumns } 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,
|
||||
Flex,
|
||||
Form,
|
||||
Input,
|
||||
message,
|
||||
Modal,
|
||||
Row,
|
||||
Space,
|
||||
} from "antd";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import { getAllAliOSSConfig } from "@/api/oss/ali";
|
||||
|
||||
type AliOssConfigItem = {
|
||||
id: number;
|
||||
userId: number;
|
||||
endpoint: string;
|
||||
accessKeyId: string;
|
||||
accessKeySecret: string;
|
||||
createdTime: string;
|
||||
updateTime: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
const columns: ProColumns<AliOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKeyId",
|
||||
tooltip: "access key id",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "accessKeySecret",
|
||||
tooltip: "access key secret",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: any, record: any, _, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a target="_blank" rel="noopener noreferrer" key="view">
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={() => action?.reload()}
|
||||
menus={[
|
||||
{ key: "copy", name: "复制" },
|
||||
{ key: "delete", name: "删除" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
import {
|
||||
addAliOSSConfig,
|
||||
deleteAliConfig,
|
||||
getAliConfigDetailById,
|
||||
getAllAliOSSConfig,
|
||||
initAliOSS,
|
||||
setAliShutdown,
|
||||
updateAliConfig,
|
||||
} from "@/api/oss/ali";
|
||||
|
||||
const AliSettings: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const actionRef = useRef<ActionType>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [configs, setConfigs] = useState<AliOssConfigItem[]>([]);
|
||||
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [configs, setConfigs] = useState<any>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [configDetail, setConfigDetail] = useState<object>({});
|
||||
const columns: ProColumns<any[]>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
valueType: "text",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKeyId",
|
||||
tooltip: "access key id",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "accessKeySecret",
|
||||
tooltip: "access key secret",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
valueEnum: {
|
||||
true: { text: "开启", status: "Success" },
|
||||
false: { text: "关闭", status: "Error" },
|
||||
},
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: any, record: any, _, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="view"
|
||||
onClick={() => {
|
||||
getConfigDetail(record.id).then(() => {
|
||||
setOpenModal(true);
|
||||
setLoading(false);
|
||||
});
|
||||
}}>
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={(key: string) => {
|
||||
if (key === "open") {
|
||||
init(record.id).then();
|
||||
} else if (key === "close") {
|
||||
shutdown(record.id).then();
|
||||
}
|
||||
}}
|
||||
menus={[
|
||||
{ key: "open", name: "开启" },
|
||||
{ key: "close", name: "关闭" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
async function getAllConfig() {
|
||||
getAllAliOSSConfig(1).then((res) => {
|
||||
console.log(res);
|
||||
getAllAliOSSConfig("1").then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigs(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function getConfigDetail(id: any) {
|
||||
getAliConfigDetailById(id).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigDetail(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function init(id: any) {
|
||||
initAliOSS("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "开启成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
async function shutdown(id: any) {
|
||||
setAliShutdown("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
async function deleteConfig(id: any) {
|
||||
const form: any = {
|
||||
id: id,
|
||||
isDeleted: 1,
|
||||
};
|
||||
deleteAliConfig(form).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
async function addConfigs() {
|
||||
const fieldsValue = form.getFieldsValue();
|
||||
const AliOssConfig = {
|
||||
userId: "1",
|
||||
...fieldsValue,
|
||||
};
|
||||
addAliOSSConfig(AliOssConfig).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
onClose();
|
||||
getAllConfig().then(() => {
|
||||
message
|
||||
.open({
|
||||
content: "新增成功",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
});
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
const showDrawer = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
@@ -121,7 +238,7 @@ const AliSettings: React.FC = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
useEffect(() => {
|
||||
getAllConfig();
|
||||
getAllConfig().then();
|
||||
}, []);
|
||||
const AddAliOssConfigDrawer = () => {
|
||||
return (
|
||||
@@ -139,12 +256,12 @@ const AliSettings: React.FC = () => {
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button onClick={onClose} type="primary">
|
||||
<Button onClick={addConfigs} type="primary">
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
}>
|
||||
<Form layout="vertical">
|
||||
<Form layout="vertical" form={form}>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
@@ -180,14 +297,52 @@ const AliSettings: React.FC = () => {
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div style={{ height: "65vh" }}>
|
||||
<ProTable<AliOssConfigItem>
|
||||
<div style={{ minHeight: "65vh" }}>
|
||||
<ProTable
|
||||
columns={columns}
|
||||
dataSource={configs}
|
||||
actionRef={actionRef}
|
||||
cardBordered={true}
|
||||
editable={{
|
||||
type: "multiple",
|
||||
onSave: async (__: any, originRow: any, _: any) => {
|
||||
const updateForm: any = {
|
||||
id: originRow.id,
|
||||
endpoint: originRow.endpoint,
|
||||
accessKeyId: originRow.accessKeyId,
|
||||
accessKeySecret: originRow.accessKeySecret,
|
||||
};
|
||||
updateAliConfig(updateForm).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "修改成功!",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete: async (row: any) => {
|
||||
deleteConfig(row).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: "pro-table-singe-demos",
|
||||
@@ -224,6 +379,43 @@ const AliSettings: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
<AddAliOssConfigDrawer />
|
||||
<Modal
|
||||
title={<p>配置详情</p>}
|
||||
loading={loading}
|
||||
footer={false}
|
||||
open={openModal}
|
||||
afterClose={() => {
|
||||
setConfigDetail({});
|
||||
}}
|
||||
onCancel={() => setOpenModal(false)}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>ID:</h4> <span style={{ marginLeft: 10 }}>{configDetail.id}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>endpoint: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.endpoint}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>accessKeyId: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.accessKeyId} </span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>accessKeySecret: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.accessKeySecret}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>status: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.status}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>createdTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.createdTime}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>updateTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.updateTime}</span>
|
||||
</Flex>
|
||||
</Modal>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@@ -2,9 +2,17 @@
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import type { ActionType, ProColumns } 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, Flex, Form, Input, message, Modal, Row, Space } from "antd";
|
||||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { getAllMinioConfig } from "@/api/oss/minio";
|
||||
import {
|
||||
addMinioOSSConfig,
|
||||
deleteMinioConfig,
|
||||
getAllMinioConfig,
|
||||
getMinioConfigDetailById,
|
||||
initMinioOSS,
|
||||
setMinioShutdown,
|
||||
updateMinioConfig,
|
||||
} from "@/api/oss/minio";
|
||||
|
||||
type MinioOssConfigItem = {
|
||||
id: number;
|
||||
@@ -17,95 +25,123 @@ type MinioOssConfigItem = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
const columns: ProColumns<MinioOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKey",
|
||||
tooltip: "access key",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "secret key",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: MinioOssConfigItem, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a target="_blank" rel="noopener noreferrer" key="view">
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={() => action?.reload()}
|
||||
menus={[
|
||||
{ key: "copy", name: "复制" },
|
||||
{ key: "delete", name: "删除" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const MinioSettings: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const actionRef = useRef<ActionType>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [configs, setConfigs] = useState<MinioOssConfigItem[]>([]);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [configDetail, setConfigDetail] = useState<object>({});
|
||||
const columns: ProColumns<MinioOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKey",
|
||||
tooltip: "access key",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "secret key",
|
||||
ellipsis: true,
|
||||
copyable: true,
|
||||
},
|
||||
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
valueEnum: {
|
||||
true: { text: "开启", status: "Success" },
|
||||
false: { text: "关闭", status: "Error" },
|
||||
},
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: any, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="view"
|
||||
onClick={() => {
|
||||
getConfigDetail(record.id).then(() => {
|
||||
setOpenModal(true);
|
||||
setLoading(false);
|
||||
});
|
||||
}}>
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={(key: string) => {
|
||||
if (key === "open") {
|
||||
init(record.id).then();
|
||||
} else if (key === "close") {
|
||||
shutdown(record.id).then();
|
||||
}
|
||||
}}
|
||||
menus={[
|
||||
{ key: "open", name: "开启" },
|
||||
{ key: "close", name: "关闭" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
const showDrawer = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
@@ -114,14 +150,101 @@ const MinioSettings: React.FC = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
async function getConfigDetail(id: any) {
|
||||
getMinioConfigDetailById(id).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigDetail(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function init(id: any) {
|
||||
initMinioOSS("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "开启成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function shutdown(id: any) {
|
||||
setMinioShutdown("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteConfig(id: any) {
|
||||
const form: any = {
|
||||
id: id,
|
||||
isDeleted: 1,
|
||||
};
|
||||
deleteMinioConfig(form).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getAllConfig() {
|
||||
getAllMinioConfig(1).then((res: any) => {
|
||||
getAllMinioConfig("1").then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigs(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function addMinioConfig() {
|
||||
const fieldsValue = form.getFieldsValue();
|
||||
const MinioOssConfig = {
|
||||
userId: "1",
|
||||
...fieldsValue,
|
||||
};
|
||||
addMinioOSSConfig(MinioOssConfig).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "新增成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then(() => {
|
||||
onClose();
|
||||
});
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getAllConfig().then();
|
||||
}, []);
|
||||
@@ -130,7 +253,7 @@ const MinioSettings: React.FC = () => {
|
||||
<>
|
||||
<Drawer
|
||||
title="创建连接配置"
|
||||
width={720}
|
||||
width={"45%"}
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
styles={{
|
||||
@@ -141,12 +264,12 @@ const MinioSettings: React.FC = () => {
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button onClick={onClose} type="primary">
|
||||
<Button onClick={addMinioConfig} type="primary">
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
}>
|
||||
<Form layout="vertical">
|
||||
<Form layout="vertical" form={form}>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
@@ -182,7 +305,7 @@ const MinioSettings: React.FC = () => {
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<div style={{ height: "65vh" }}>
|
||||
<div style={{ minHeight: "65vh" }}>
|
||||
<ProTable<MinioOssConfigItem>
|
||||
columns={columns}
|
||||
dataSource={configs}
|
||||
@@ -190,6 +313,44 @@ const MinioSettings: React.FC = () => {
|
||||
cardBordered={true}
|
||||
editable={{
|
||||
type: "multiple",
|
||||
onSave: async (__: any, originRow: any, _: any) => {
|
||||
const updateForm: any = {
|
||||
id: originRow.id,
|
||||
endpoint: originRow.endpoint,
|
||||
accessKey: originRow.accessKey,
|
||||
secretKey: originRow.secretKey,
|
||||
};
|
||||
updateMinioConfig(updateForm).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "修改成功!",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete: async (row: any) => {
|
||||
deleteConfig(row).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfig().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: "pro-table-singe-demos",
|
||||
@@ -226,6 +387,43 @@ const MinioSettings: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
<AddMinioOssConfigDrawer />
|
||||
<Modal
|
||||
title={<p>配置详情</p>}
|
||||
loading={loading}
|
||||
footer={false}
|
||||
afterClose={() => {
|
||||
setConfigDetail({});
|
||||
}}
|
||||
open={openModal}
|
||||
onCancel={() => setOpenModal(false)}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>ID:</h4> <span style={{ marginLeft: 10 }}>{configDetail.id}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>endpoint: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.endpoint}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>accessKey: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.accessKey} </span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>secretKey: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.secretKey}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>status: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.status}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>createdTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.createdTime}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>updateTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.updateTime}</span>
|
||||
</Flex>
|
||||
</Modal>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@@ -2,9 +2,17 @@
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import type { ActionType, ProColumns } 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, Flex, Form, Input, message, Modal, Row, Space } from "antd";
|
||||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { getAllQiniuConfigs } from "@/api/oss/qiniu";
|
||||
import {
|
||||
addQiniuOSSConfig,
|
||||
deleteQiniuConfig,
|
||||
getAllQiniuConfigs,
|
||||
getQiniuConfigDetailById,
|
||||
initQiniuOSS,
|
||||
setQiniuShutdown,
|
||||
updateQiniuConfig,
|
||||
} from "@/api/oss/qiniu";
|
||||
|
||||
type QiniuOssConfigItem = {
|
||||
id: number;
|
||||
@@ -17,95 +25,187 @@ type QiniuOssConfigItem = {
|
||||
status: string;
|
||||
};
|
||||
|
||||
const columns: ProColumns<QiniuOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKey",
|
||||
tooltip: "access key id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "access key secret",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: QiniuOssConfigItem, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a target="_blank" rel="noopener noreferrer" key="view">
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={() => action?.reload()}
|
||||
menus={[
|
||||
{ key: "copy", name: "复制" },
|
||||
{ key: "delete", name: "删除" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const QiniuSettings: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const actionRef = useRef<ActionType>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [config, setConfig] = useState<QiniuOssConfigItem[]>([]);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [configDetail, setConfigDetail] = useState<object>({});
|
||||
const columns: ProColumns<QiniuOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
tooltip: "endpoint",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "accessKey",
|
||||
tooltip: "access key id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "access key secret",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
valueEnum: {
|
||||
true: { text: "开启", status: "Success" },
|
||||
false: { text: "关闭", status: "Error" },
|
||||
},
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: QiniuOssConfigItem, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="view"
|
||||
onClick={() => {
|
||||
getConfigDetail(record.id).then(() => {
|
||||
setOpenModal(true);
|
||||
setLoading(false);
|
||||
});
|
||||
}}>
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={(key: string) => {
|
||||
if (key === "open") {
|
||||
init(record.id).then();
|
||||
} else if (key === "close") {
|
||||
shutdown(record.id).then();
|
||||
}
|
||||
}}
|
||||
menus={[
|
||||
{ key: "open", name: "开启" },
|
||||
{ key: "close", name: "关闭" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
async function init(id: any) {
|
||||
initQiniuOSS("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "开启成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function getConfigDetail(id: any) {
|
||||
getQiniuConfigDetailById(id).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigDetail(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function shutdown(id: any) {
|
||||
setQiniuShutdown("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteConfig(id: any) {
|
||||
const form: any = {
|
||||
id: id,
|
||||
isDeleted: 1,
|
||||
};
|
||||
deleteQiniuConfig(form).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const showDrawer = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
@@ -113,7 +213,8 @@ const QiniuSettings: React.FC = () => {
|
||||
const onClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
async function getAllCOnfigs() {
|
||||
|
||||
async function getAllConfigs() {
|
||||
getAllQiniuConfigs(1).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfig(res.data);
|
||||
@@ -121,15 +222,39 @@ const QiniuSettings: React.FC = () => {
|
||||
});
|
||||
}
|
||||
|
||||
async function addQiniuoConfig() {
|
||||
const fieldsValue = form.getFieldsValue();
|
||||
const QiniuOssConfig = {
|
||||
userId: 1,
|
||||
...fieldsValue,
|
||||
};
|
||||
addQiniuOSSConfig(QiniuOssConfig).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "新增成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then(() => {
|
||||
onClose();
|
||||
});
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getAllCOnfigs().then();
|
||||
getAllConfigs().then();
|
||||
}, []);
|
||||
const AddQiniuOssConfigDrawer = () => {
|
||||
return (
|
||||
<>
|
||||
<Drawer
|
||||
title="创建连接配置"
|
||||
width={720}
|
||||
width={"45%"}
|
||||
onClose={onClose}
|
||||
open={open}
|
||||
styles={{
|
||||
@@ -140,12 +265,12 @@ const QiniuSettings: React.FC = () => {
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button onClick={onClose} type="primary">
|
||||
<Button onClick={addQiniuoConfig} type="primary">
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
}>
|
||||
<Form layout="vertical">
|
||||
<Form layout="vertical" form={form}>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
@@ -155,6 +280,14 @@ const QiniuSettings: React.FC = () => {
|
||||
<Input placeholder="请输入存储桶!" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="endpoint"
|
||||
label="服务地址"
|
||||
rules={[{ required: true, message: "请输入服务地址!" }]}>
|
||||
<Input placeholder="请输入服务地址!" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
@@ -189,6 +322,44 @@ const QiniuSettings: React.FC = () => {
|
||||
cardBordered={true}
|
||||
editable={{
|
||||
type: "multiple",
|
||||
onSave: async (__: any, originRow: any, _: any) => {
|
||||
const updateForm: any = {
|
||||
id: originRow.id,
|
||||
endpoint: originRow.endpoint,
|
||||
accessKey: originRow.accessKey,
|
||||
secretKey: originRow.secretKey,
|
||||
};
|
||||
updateQiniuConfig(updateForm).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "修改成功!",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete: async (row: any) => {
|
||||
deleteConfig(row).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: "pro-table-singe-demos",
|
||||
@@ -225,6 +396,43 @@ const QiniuSettings: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
<AddQiniuOssConfigDrawer />
|
||||
<Modal
|
||||
title={<p>配置详情</p>}
|
||||
loading={loading}
|
||||
afterClose={() => {
|
||||
setConfigDetail({});
|
||||
}}
|
||||
footer={false}
|
||||
open={openModal}
|
||||
onCancel={() => setOpenModal(false)}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>ID:</h4> <span style={{ marginLeft: 10 }}>{configDetail.id}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>endpoint: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.endpoint}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>accessKey: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.accessKey} </span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>secretKey: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.secretKey}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>status: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.status}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>createdTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.createdTime}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>updateTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.updateTime}</span>
|
||||
</Flex>
|
||||
</Modal>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@@ -2,101 +2,225 @@
|
||||
import { PlusOutlined } from "@ant-design/icons";
|
||||
import type { ActionType, ProColumns } 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, Flex, Form, Input, message, Modal, Row, Space } from "antd";
|
||||
import React, { ReactNode, useEffect, useRef, useState } from "react";
|
||||
import { getAllTencentOSsConfig } from "@/api/oss/tencent";
|
||||
import {
|
||||
addTencentOSSConfig,
|
||||
deleteTencentConfig,
|
||||
getAllTencentOSsConfig,
|
||||
getTencentConfigDetailById,
|
||||
initTencentOSS,
|
||||
setTencentShutdown,
|
||||
updateTencentConfig,
|
||||
} from "@/api/oss/tencent";
|
||||
|
||||
type TencentOssConfigItem = {
|
||||
id: number;
|
||||
userId: number;
|
||||
endpoint: number;
|
||||
secretId: string;
|
||||
secretKey: string;
|
||||
appId: string;
|
||||
region: string;
|
||||
createdTime: string;
|
||||
updateTime: string;
|
||||
status: string;
|
||||
};
|
||||
|
||||
const columns: ProColumns<TencentOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "secretId",
|
||||
copyable: true,
|
||||
tooltip: "secret Id",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "secret Key",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: TencentOssConfigItem, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a target="_blank" rel="noopener noreferrer" key="view">
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={() => action?.reload()}
|
||||
menus={[
|
||||
{ key: "copy", name: "复制" },
|
||||
{ key: "delete", name: "删除" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const TencentSettings: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const actionRef = useRef<ActionType>();
|
||||
const [open, setOpen] = useState(false);
|
||||
const [configs, setConfigs] = useState<TencentOssConfigItem[]>([]);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [configDetail, setConfigDetail] = useState<object>({});
|
||||
const columns: ProColumns<TencentOssConfigItem>[] = [
|
||||
{
|
||||
dataIndex: "index",
|
||||
valueType: "indexBorder",
|
||||
width: 48,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "ID",
|
||||
dataIndex: "id",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
tooltip: "Id",
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "服务地址",
|
||||
dataIndex: "endpoint",
|
||||
copyable: true,
|
||||
tooltip: "endpoint",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥ID",
|
||||
dataIndex: "secretId",
|
||||
copyable: true,
|
||||
tooltip: "secret Id",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "密钥值",
|
||||
dataIndex: "secretKey",
|
||||
tooltip: "secret Key",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "appId",
|
||||
dataIndex: "appId",
|
||||
tooltip: "appId",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "地域",
|
||||
dataIndex: "region",
|
||||
tooltip: "region",
|
||||
copyable: true,
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
hideInSearch: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "更新时间",
|
||||
dataIndex: "updateTime",
|
||||
valueType: "dateTime",
|
||||
sorter: true,
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
disable: true,
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
search: true,
|
||||
valueEnum: {
|
||||
true: { text: "开启", status: "Success" },
|
||||
false: { text: "关闭", status: "Error" },
|
||||
},
|
||||
editable: false,
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
valueType: "option",
|
||||
key: "option",
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
render: (text: ReactNode, record: TencentOssConfigItem, _: number, action: any) => [
|
||||
<a
|
||||
key="editable"
|
||||
onClick={() => {
|
||||
action?.startEditable?.(record.id);
|
||||
}}>
|
||||
编辑
|
||||
</a>,
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="view"
|
||||
onClick={() => {
|
||||
getConfigDetail(record.id).then(() => {
|
||||
setOpenModal(true);
|
||||
setLoading(false);
|
||||
});
|
||||
}}>
|
||||
查看
|
||||
</a>,
|
||||
<TableDropdown
|
||||
key="actionGroup"
|
||||
onSelect={(key: string) => {
|
||||
if (key === "open") {
|
||||
init(record.id).then();
|
||||
} else if (key === "close") {
|
||||
shutdown(record.id).then();
|
||||
}
|
||||
}}
|
||||
menus={[
|
||||
{ key: "open", name: "开启" },
|
||||
{ key: "close", name: "关闭" },
|
||||
]}
|
||||
/>,
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
async function init(id: any) {
|
||||
initTencentOSS("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "开启成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
async function getConfigDetail(id: any) {
|
||||
getTencentConfigDetailById(id).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigDetail(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
async function shutdown(id: any) {
|
||||
setTencentShutdown("1", id).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function deleteConfig(id: any) {
|
||||
const form: any = {
|
||||
id: id,
|
||||
isDeleted: 1,
|
||||
};
|
||||
deleteTencentConfig(form).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const showDrawer = () => {
|
||||
setOpen(true);
|
||||
};
|
||||
@@ -104,14 +228,39 @@ const TencentSettings: React.FC = () => {
|
||||
const onClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
async function getAllConfigs() {
|
||||
getAllTencentOSsConfig(5).then((res: any) => {
|
||||
getAllTencentOSsConfig("1").then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setConfigs(res.data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async function addTencentConfig() {
|
||||
const fieldsValue = form.getFieldsValue();
|
||||
const TencentOssConfig = {
|
||||
userId: "1",
|
||||
...fieldsValue,
|
||||
};
|
||||
addTencentOSSConfig(TencentOssConfig).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "新增成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then(() => {
|
||||
onClose();
|
||||
});
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getAllConfigs().then();
|
||||
}, []);
|
||||
@@ -131,12 +280,12 @@ const TencentSettings: React.FC = () => {
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button onClick={onClose} type="primary">
|
||||
<Button onClick={addTencentConfig} type="primary">
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
}>
|
||||
<Form layout="vertical">
|
||||
<Form layout="vertical" form={form}>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
@@ -155,6 +304,24 @@ const TencentSettings: React.FC = () => {
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={16}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="appId"
|
||||
label="appId"
|
||||
rules={[{ required: true, message: "请输入appID!" }]}>
|
||||
<Input placeholder="请输入appID!" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
name="region"
|
||||
label="地区"
|
||||
rules={[{ required: true, message: "请输入地区!" }]}>
|
||||
<Input placeholder="请输入地区!" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
</Drawer>
|
||||
</>
|
||||
@@ -170,6 +337,46 @@ const TencentSettings: React.FC = () => {
|
||||
cardBordered={true}
|
||||
editable={{
|
||||
type: "multiple",
|
||||
onSave: async (__: any, originRow: any, _: any) => {
|
||||
const updateForm: any = {
|
||||
id: originRow.id,
|
||||
endpoint: originRow.endpoint,
|
||||
secretId: originRow.secretId,
|
||||
secretKey: originRow.secretKey,
|
||||
appId: originRow.appId,
|
||||
region: originRow.region,
|
||||
};
|
||||
updateTencentConfig(updateForm).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "修改成功!",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
onDelete: async (row: any) => {
|
||||
deleteConfig(row).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message.open({
|
||||
content: "删除成功",
|
||||
type: "success",
|
||||
});
|
||||
getAllConfigs().then();
|
||||
} else {
|
||||
message.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
}}
|
||||
columnsState={{
|
||||
persistenceKey: "pro-table-singe-demos",
|
||||
@@ -206,6 +413,51 @@ const TencentSettings: React.FC = () => {
|
||||
]}
|
||||
/>
|
||||
<AddTencentOssConfigDrawer />
|
||||
<Modal
|
||||
title={<p>配置详情</p>}
|
||||
loading={loading}
|
||||
footer={false}
|
||||
open={openModal}
|
||||
afterClose={() => {
|
||||
setConfigDetail({});
|
||||
}}
|
||||
onCancel={() => setOpenModal(false)}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>ID:</h4> <span style={{ marginLeft: 10 }}>{configDetail.id}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>endpoint: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.endpoint}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>secretId: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.secretId} </span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>secretKey: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.secretKey}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>appId: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.appId}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>region: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.region}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>status: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.status}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>createdTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.createdTime}</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h4>updateTime: </h4>{" "}
|
||||
<span style={{ marginLeft: 10 }}>{configDetail.updateTime}</span>
|
||||
</Flex>
|
||||
</Modal>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@@ -27,10 +27,13 @@ export default () => {
|
||||
onSelect={(value: any) => {
|
||||
navigate("/main/setting/" + value);
|
||||
}}
|
||||
placeholder={"请选择存储商"}>
|
||||
{selectOptions.map((storage: any, index: any) => {
|
||||
fieldNames={{
|
||||
label: "name",
|
||||
value: "value",
|
||||
}}
|
||||
labelRender={(label: any) => {
|
||||
return (
|
||||
<Select.Option value={storage.value} key={index}>
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
@@ -40,19 +43,44 @@ export default () => {
|
||||
flexDirection: "row",
|
||||
}}
|
||||
size={"small"}>
|
||||
<Avatar src={StorageIcon[storage.value]} size={"small"} />{" "}
|
||||
<Avatar src={StorageIcon[label.value]} size={"small"} />
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{storage.name}
|
||||
{label.label}
|
||||
</span>
|
||||
</Card>
|
||||
</Select.Option>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
}}
|
||||
options={selectOptions}
|
||||
optionRender={(item: any) => {
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
bordered={false}
|
||||
style={{
|
||||
height: 35,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
}}
|
||||
size={"small"}>
|
||||
<Avatar src={StorageIcon[item.value]} size={"small"} />
|
||||
<span
|
||||
style={{
|
||||
marginLeft: "10px",
|
||||
fontWeight: "bolder",
|
||||
}}>
|
||||
{item.label}
|
||||
</span>
|
||||
</Card>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
placeholder={"请选择存储商"}></Select>
|
||||
</div>
|
||||
</ProCard>
|
||||
<ProCard style={{ marginTop: 20, height: "100%" }} bordered boxShadow>
|
||||
|
@@ -6,18 +6,53 @@ import { useNavigate } from "react-router-dom";
|
||||
import "aieditor/dist/style.css";
|
||||
import styles from "./index.module.less";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { Button, Card, Flex, Form, FormListFieldData, FormProps, Input, Select } from "antd";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Flex,
|
||||
Form,
|
||||
FormListFieldData,
|
||||
FormProps,
|
||||
Input,
|
||||
message,
|
||||
Select,
|
||||
} from "antd";
|
||||
import { CloseOutlined, LeftOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import selectOptions from "@/components/Main/Settings/settings.ts";
|
||||
import { addShareDetail } from "@/api/share";
|
||||
import useStore from "@/utils/store/useStore.tsx";
|
||||
import { observer } from "mobx-react";
|
||||
|
||||
const ShareAdd: React.FunctionComponent = () => {
|
||||
const navigate = useNavigate();
|
||||
const divRef = useRef(null);
|
||||
const fromRef: any = useRef();
|
||||
const [form] = Form.useForm();
|
||||
const [isDisabled, setIsDisabled] = React.useState(false);
|
||||
const store = useStore("share");
|
||||
|
||||
const onFinish: FormProps["onFinish"] = (values) => {
|
||||
console.log("Success:", values);
|
||||
const formData: any = {
|
||||
circleId: store.getCircleId(),
|
||||
userId: 32,
|
||||
...values,
|
||||
};
|
||||
addShareDetail(formData).then((res: any) => {
|
||||
if (res && res.success) {
|
||||
message
|
||||
.open({
|
||||
content: "新增成功",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: "新增失败",
|
||||
type: "warning",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
};
|
||||
useEffect(() => {
|
||||
if (divRef.current) {
|
||||
@@ -39,9 +74,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
},
|
||||
},
|
||||
onChange: async (value: any) => {
|
||||
fromRef.current.setFieldsValue({
|
||||
content: value.getHtml(),
|
||||
});
|
||||
form.setFieldValue("content" as any, value.getHtml());
|
||||
},
|
||||
} as any);
|
||||
return () => {
|
||||
@@ -58,7 +91,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
shape="circle"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={() => {
|
||||
navigate("/main/share/list/1");
|
||||
navigate("/main/share/list/" + store.getCircleId());
|
||||
}}
|
||||
/>
|
||||
<Flex
|
||||
@@ -71,7 +104,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
</Flex>
|
||||
</ProCard>
|
||||
<div className={styles.share_add_content}>
|
||||
<Form onFinish={onFinish} autoComplete="off" ref={fromRef}>
|
||||
<Form onFinish={onFinish} autoComplete="off" form={form}>
|
||||
<Form.Item
|
||||
label={
|
||||
<>
|
||||
@@ -111,6 +144,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
<h4>介绍</h4>
|
||||
</>
|
||||
}
|
||||
rules={[{ required: true, message: "请输入介绍" }]}
|
||||
name="content"
|
||||
id={"content"}>
|
||||
<div
|
||||
@@ -126,7 +160,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
if (!tags) {
|
||||
return Promise.reject(new Error("请至少填写一个标签"));
|
||||
}
|
||||
if (tags.length >= 3) {
|
||||
if (tags.length > 3) {
|
||||
setIsDisabled(true);
|
||||
return Promise.reject(
|
||||
new Error("最多只能添加三个标签"),
|
||||
@@ -148,7 +182,7 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
id={"tags"}>
|
||||
<Form.Item
|
||||
validateTrigger={["onChange", "onBlur"]}
|
||||
name={[field.name, "tag"]}
|
||||
name={[field.name, "tagName"] as any}
|
||||
noStyle>
|
||||
<Input
|
||||
placeholder="请输入标签"
|
||||
@@ -209,7 +243,9 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
}}
|
||||
/>
|
||||
}>
|
||||
<Form.Item name={[field.name, "type"]} label="分享类型">
|
||||
<Form.Item
|
||||
name={[field.name, "type"] as any}
|
||||
label="分享类型">
|
||||
<Select
|
||||
size="middle"
|
||||
style={{ width: "20%" }}
|
||||
@@ -231,15 +267,17 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={[field.name, "description"]}
|
||||
name={[field.name, "description"] as any}
|
||||
label="资源描述">
|
||||
<Input name={"description"} />
|
||||
</Form.Item>
|
||||
<Form.Item name={[field.name, "url"]} label="资源链接">
|
||||
<Form.Item
|
||||
name={[field.name, "url"] as any}
|
||||
label="资源链接">
|
||||
<Input name={"url"} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={[field.name, "password"]}
|
||||
name={[field.name, "password"] as any}
|
||||
label={"提取密码"}>
|
||||
<Input name={"password"} />
|
||||
</Form.Item>
|
||||
@@ -269,4 +307,4 @@ const ShareAdd: React.FunctionComponent = () => {
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default ShareAdd;
|
||||
export default observer(ShareAdd);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/** @format */
|
||||
import React from "react";
|
||||
import { Avatar, Button, Card, Divider, Flex, Tag, Tooltip } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Avatar, Button, Card, Divider, Flex, Skeleton, Tag, Tooltip } from "antd";
|
||||
import {
|
||||
CommentOutlined,
|
||||
ExportOutlined,
|
||||
@@ -11,33 +11,54 @@ import {
|
||||
TagsOutlined,
|
||||
WarningOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import "aieditor/dist/style.css";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import styles from "./index.module.less";
|
||||
import logo from "@/assets/icons/baiduyun.svg";
|
||||
import { Typography } from "antd";
|
||||
import Comment from "@/components/Main/Share/components/ShareDetail/components/Comment";
|
||||
import getRandomColor from "@/constant/random-color.ts";
|
||||
const { Paragraph } = Typography;
|
||||
import like from "@/assets/icons/like.svg";
|
||||
import favorite from "@/assets/icons/favorite.svg";
|
||||
import useStore from "@/utils/store/useStore.tsx";
|
||||
import { getShareDetail } from "@/api/share";
|
||||
import StorageIcon from "@/constant/stroage-icon.ts";
|
||||
import { observer } from "mobx-react";
|
||||
const ShareDetail: React.FunctionComponent = () => {
|
||||
const navigate = useNavigate();
|
||||
const store = useStore("share");
|
||||
const params = useParams();
|
||||
const [detail, setDetail] = useState<any>({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
async function getDetail() {
|
||||
getShareDetail(params.id).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setDetail(res.data);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getDetail().then();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
<Skeleton loading={loading} active={true} paragraph={{ rows: 16 }}>
|
||||
<ProCard bordered={true}>
|
||||
<Flex vertical={false} align={"center"} justify={"space-between"}>
|
||||
<Button
|
||||
shape="circle"
|
||||
icon={<LeftOutlined />}
|
||||
onClick={() => {
|
||||
navigate("/main/share/list/1");
|
||||
const circleId = store.getCircleId();
|
||||
navigate("/main/share/list/" + circleId);
|
||||
}}
|
||||
/>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<h3>办公软件分享</h3>
|
||||
<h3>{detail.title as string}</h3>
|
||||
</Flex>
|
||||
<Flex
|
||||
vertical={false}
|
||||
@@ -45,14 +66,14 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
justify={"space-between"}
|
||||
style={{ width: "20%" }}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Avatar src={logo as any} size={"small"} />
|
||||
<Avatar src={detail.avatar as any} size={"small"} />
|
||||
<span
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
landaiqing
|
||||
{detail.nickname}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -62,7 +83,7 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{detail.likesCount}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -72,7 +93,7 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{detail.commentCount}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -82,7 +103,7 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{detail.views}
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -90,7 +111,9 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
</ProCard>
|
||||
<div className={styles.share_detail_container}>
|
||||
<ProCard bordered={true}>
|
||||
<div style={{ height: 500 }}>资源描述</div>
|
||||
<div
|
||||
style={{ height: 500 }}
|
||||
dangerouslySetInnerHTML={{ __html: detail.content }}></div>
|
||||
|
||||
<Card style={{ borderRadius: "10px", borderColor: "#1677FF" }}>
|
||||
<Flex vertical={false} align={"center"} justify={"space-between"}>
|
||||
@@ -111,7 +134,7 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
align={"center"}
|
||||
style={{ marginTop: 10 }}
|
||||
justify={"space-between"}>
|
||||
<span style={{ fontSize: 16 }}>Windows DefenderRemover</span>
|
||||
<span style={{ fontSize: 16 }}>{detail.title}</span>
|
||||
</Flex>
|
||||
<Flex
|
||||
vertical={false}
|
||||
@@ -131,48 +154,77 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
style={{ marginTop: 10 }}
|
||||
justify={"space-between"}>
|
||||
<Card hoverable={true} style={{ width: 280, height: 140 }}>
|
||||
<Flex vertical={true}>
|
||||
<Flex
|
||||
vertical={false}
|
||||
justify={"space-between"}
|
||||
align={"center"}>
|
||||
<div>
|
||||
<Avatar src={logo as any}></Avatar>
|
||||
<span
|
||||
justify={"flex-start"}>
|
||||
{detail.urls &&
|
||||
Array.from(detail.urls).map((url: any, index: number) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Card
|
||||
hoverable={true}
|
||||
style={{
|
||||
width: 280,
|
||||
height: 140,
|
||||
marginLeft: 10,
|
||||
color: "#1677FF",
|
||||
fontSize: 16,
|
||||
}}>
|
||||
百度云
|
||||
</span>
|
||||
<Flex vertical={true}>
|
||||
<Flex
|
||||
vertical={false}
|
||||
justify={"space-between"}
|
||||
align={"center"}>
|
||||
<div>
|
||||
<Avatar
|
||||
src={
|
||||
StorageIcon[url.type] as any
|
||||
}></Avatar>
|
||||
<span
|
||||
style={{
|
||||
marginLeft: 10,
|
||||
color: "#1677FF",
|
||||
fontSize: 16,
|
||||
}}>
|
||||
百度云
|
||||
</span>
|
||||
</div>
|
||||
<ExportOutlined
|
||||
className={styles.link_btn}
|
||||
onClick={() => {
|
||||
window.open(url.url, "_blank");
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
<Divider></Divider>
|
||||
<Flex vertical={false}>
|
||||
<Tooltip
|
||||
title={url.description}
|
||||
placement={"bottom"}>
|
||||
<span
|
||||
style={{
|
||||
width: 150,
|
||||
overflowX: "hidden",
|
||||
}}>
|
||||
{url.description}
|
||||
</span>
|
||||
</Tooltip>
|
||||
<span
|
||||
style={{
|
||||
width: 130,
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
}}>
|
||||
<span style={{ color: "#1677FF" }}>
|
||||
密码:
|
||||
</span>{" "}
|
||||
<Paragraph copyable>
|
||||
{url.password}
|
||||
</Paragraph>
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
</div>
|
||||
<ExportOutlined className={styles.link_btn} />
|
||||
</Flex>
|
||||
<Divider></Divider>
|
||||
<Flex vertical={false}>
|
||||
<Tooltip
|
||||
title="DefenderRemove111111111"
|
||||
placement={"bottom"}>
|
||||
<span style={{ width: 150, overflowX: "hidden" }}>
|
||||
DefenderRemove111111111
|
||||
</span>
|
||||
</Tooltip>
|
||||
<span
|
||||
style={{
|
||||
width: 130,
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
}}>
|
||||
<span style={{ color: "#1677FF" }}>密码:</span>{" "}
|
||||
<Paragraph copyable>12345</Paragraph>
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
<Flex vertical={false} style={{ marginTop: 10 }}>
|
||||
<span style={{ color: "grey" }}>
|
||||
@@ -185,19 +237,27 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
<Flex vertical={false} align={"center"} style={{ marginTop: 20 }}>
|
||||
<TagsOutlined style={{ fontSize: 30, color: "#1677FF" }} />
|
||||
<Flex vertical={false} align={"center"} style={{ marginLeft: 10 }}>
|
||||
<Tag bordered={false} color={getRandomColor()}>
|
||||
测试标签
|
||||
</Tag>
|
||||
<Tag bordered={false} color={getRandomColor()}>
|
||||
测试标签
|
||||
</Tag>
|
||||
<Tag bordered={false} color={getRandomColor()}>
|
||||
测试标签
|
||||
</Tag>
|
||||
{detail.tags &&
|
||||
Array.from(detail.tags).map((tag: any, index: number) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Tag bordered={false} color={getRandomColor()}>
|
||||
{tag.tagName}
|
||||
</Tag>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"} justify={"center"} style={{height: 50}}>
|
||||
<Avatar className={styles.like_icon} src={like as any} size={"large"}></Avatar>
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
justify={"center"}
|
||||
style={{ height: 50 }}>
|
||||
<Avatar
|
||||
className={styles.like_icon}
|
||||
src={like as any}
|
||||
size={"large"}></Avatar>
|
||||
<Avatar
|
||||
className={styles.favtorie_icon}
|
||||
src={favorite as any}
|
||||
@@ -206,8 +266,8 @@ const ShareDetail: React.FunctionComponent = () => {
|
||||
</ProCard>
|
||||
</div>
|
||||
<Comment />
|
||||
</div>
|
||||
</Skeleton>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default ShareDetail;
|
||||
export default observer(ShareDetail);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,10 @@
|
||||
/** @format */
|
||||
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import { Avatar, Button, Divider, Flex, Input, List, Skeleton, Tag } from "antd";
|
||||
import { Avatar, Button, Flex, Input, List, Skeleton, Tag } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import styles from "./index.module.less";
|
||||
import InfiniteScroll from "react-infinite-scroll-component";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
CommentOutlined,
|
||||
EyeOutlined,
|
||||
@@ -13,7 +12,10 @@ import {
|
||||
LeftOutlined,
|
||||
ShareAltOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import logo from "@/assets/icons/aliyun.svg";
|
||||
import { shareDetailList } from "@/api/share";
|
||||
import getRandomColor from "@/constant/random-color.ts";
|
||||
import useStore from "@/utils/store/useStore.tsx";
|
||||
import { observer } from "mobx-react";
|
||||
interface DataType {
|
||||
gender: string;
|
||||
name: {
|
||||
@@ -30,28 +32,24 @@ interface DataType {
|
||||
nat: string;
|
||||
}
|
||||
|
||||
export default () => {
|
||||
export default observer(() => {
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const params = useParams();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [data, setData] = useState<DataType[]>([]);
|
||||
const loadMoreData = () => {
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
setLoading(true);
|
||||
fetch("https://randomuser.me/api/?results=10&inc=name,gender,email,nat,picture&noinfo")
|
||||
.then((res) => res.json())
|
||||
.then((body) => {
|
||||
setData([...data, ...body.results]);
|
||||
const store = useStore("share");
|
||||
async function getShareDetailList() {
|
||||
store.setCircleId(params.id as string);
|
||||
shareDetailList(params.id).then((res: any) => {
|
||||
if (res && res.data && res.data) {
|
||||
setData(res.data);
|
||||
setLoading(false);
|
||||
})
|
||||
.catch(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadMoreData();
|
||||
getShareDetailList().then();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
@@ -83,13 +81,7 @@ export default () => {
|
||||
</div>
|
||||
</ProCard>
|
||||
<ProCard bordered={false} boxShadow={false}>
|
||||
<InfiniteScroll
|
||||
dataLength={data.length}
|
||||
next={loadMoreData}
|
||||
hasMore={data.length < 50}
|
||||
loader={<Skeleton avatar paragraph={{ rows: 1 }} active />}
|
||||
endMessage={<Divider plain>It is all, nothing more 🤐</Divider>}
|
||||
scrollableTarget="scrollableDiv">
|
||||
<Skeleton loading={loading} active={true} paragraph={{ rows: 14 }}>
|
||||
<List
|
||||
dataSource={data}
|
||||
header={
|
||||
@@ -97,25 +89,34 @@ export default () => {
|
||||
<h4>分享列表</h4>
|
||||
</>
|
||||
}
|
||||
renderItem={(item) => (
|
||||
<List.Item key={item.email}>
|
||||
renderItem={(item: any) => (
|
||||
<List.Item key={item.id}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src={item.picture.large} />}
|
||||
avatar={<Avatar src={item.icon} />}
|
||||
title={
|
||||
<>
|
||||
<a
|
||||
onClick={() => {
|
||||
navigate("/main/share/detail/1");
|
||||
}}>
|
||||
{item.name.last}
|
||||
</a>
|
||||
<Tag
|
||||
bordered={false}
|
||||
color="processing"
|
||||
style={{ marginLeft: 10 }}>
|
||||
IDM
|
||||
</Tag>
|
||||
</>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Link to={"/main/share/detail/" + item.id}>
|
||||
{item.title}
|
||||
</Link>
|
||||
{item.tags &&
|
||||
Array.from(item.tags).map(
|
||||
(tag: any, index: number) => {
|
||||
return (
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
key={index}>
|
||||
<Tag
|
||||
bordered={false}
|
||||
color={getRandomColor()}
|
||||
style={{ marginLeft: 10 }}>
|
||||
{tag.tagName}
|
||||
</Tag>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
)}
|
||||
</Flex>
|
||||
}
|
||||
description={
|
||||
<>
|
||||
@@ -123,7 +124,7 @@ export default () => {
|
||||
vertical={false}
|
||||
justify={"space-between"}
|
||||
align={"center"}>
|
||||
{item.email}
|
||||
{item.description}
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
@@ -131,7 +132,7 @@ export default () => {
|
||||
style={{ width: "300px" }}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Avatar
|
||||
src={logo as any}
|
||||
src={item.avatar as any}
|
||||
size={"small"}
|
||||
/>
|
||||
<span
|
||||
@@ -140,7 +141,7 @@ export default () => {
|
||||
color: "gray",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
landaiqing
|
||||
{item.nickname}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -150,7 +151,7 @@ export default () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{item.likesCount}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -160,7 +161,7 @@ export default () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{item.commentCount}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
@@ -172,7 +173,7 @@ export default () => {
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
}}>
|
||||
1024
|
||||
{item.views}
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
@@ -180,13 +181,12 @@ export default () => {
|
||||
</>
|
||||
}
|
||||
/>
|
||||
{/*<div>Content</div>*/}
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
</InfiniteScroll>
|
||||
</Skeleton>
|
||||
</ProCard>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
@@ -1,22 +1,48 @@
|
||||
/** @format */
|
||||
import { FunctionComponent, useState } from "react";
|
||||
import { FunctionComponent, useEffect, useState } from "react";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import styles from "./index.module.less";
|
||||
import { Avatar, Button, Card, Drawer, Flex, FloatButton, Form, Image, Input, Space } from "antd";
|
||||
import {
|
||||
Avatar,
|
||||
Button,
|
||||
Card,
|
||||
Drawer,
|
||||
Flex,
|
||||
FloatButton,
|
||||
Form,
|
||||
Image,
|
||||
Input,
|
||||
message,
|
||||
Skeleton,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import TextArea from "antd/es/input/TextArea";
|
||||
import { EyeOutlined, PlusOutlined, UnorderedListOutlined } from "@ant-design/icons";
|
||||
import pic from "@/assets/images/background.png";
|
||||
|
||||
import Meta from "antd/es/card/Meta";
|
||||
import { addShareCircle, getShareCircleList } from "@/api/share";
|
||||
const MainShare: FunctionComponent = () => {
|
||||
const navigate = useNavigate();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [circleList, setCircleList] = useState<any[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
const onClose = () => {
|
||||
setOpen(false);
|
||||
};
|
||||
async function getShareCircles() {
|
||||
getShareCircleList().then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
setCircleList(res.data);
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getShareCircles().then();
|
||||
}, []);
|
||||
return (
|
||||
<>
|
||||
<div className={styles.share_main}>
|
||||
@@ -30,77 +56,108 @@ const MainShare: FunctionComponent = () => {
|
||||
</div>
|
||||
</ProCard>
|
||||
<ProCard title={<h3>文件分享圈</h3>} bordered={false} boxShadow={false}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Card
|
||||
hoverable
|
||||
style={{
|
||||
width: "250px",
|
||||
boxShadow: " 0 0 10px rgba(0, 0, 0, 0.1)",
|
||||
borderRadius: 20,
|
||||
// backgroundColor: "rgba(79,68,68,0.11)",
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate("/main/share/list/1");
|
||||
}}
|
||||
cover={
|
||||
<Image
|
||||
alt="example"
|
||||
src={pic as any}
|
||||
style={{
|
||||
height: 180,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
}}
|
||||
preview={false}
|
||||
width={"100%"}
|
||||
fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
|
||||
/>
|
||||
}>
|
||||
<Meta title="工具软件分享" description="分享一些常用的办公软件" />
|
||||
{/*<Avatar*/}
|
||||
{/* src={pic2 as any}*/}
|
||||
{/* shape={"circle"}*/}
|
||||
{/* style={{*/}
|
||||
{/* position: "absolute",*/}
|
||||
{/* top: 160,*/}
|
||||
{/* left: 10,*/}
|
||||
{/* width: 60,*/}
|
||||
{/* height: 60,*/}
|
||||
{/* zIndex: 9999,*/}
|
||||
{/* }}></Avatar>*/}
|
||||
<Flex
|
||||
vertical={false}
|
||||
style={{ marginTop: 10 }}
|
||||
align={"center"}
|
||||
justify={"space-between"}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Avatar src={pic as any} size={"small"} />{" "}
|
||||
<span style={{ fontSize: 12, color: "gray", marginLeft: 5 }}>
|
||||
landaiqing
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
style={{ width: 100 }}
|
||||
justify={"space-between"}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<EyeOutlined style={{ color: "gray" }} />{" "}
|
||||
<span
|
||||
style={{ fontSize: 12, color: "gray", marginLeft: 5 }}>
|
||||
1024
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<UnorderedListOutlined style={{ color: "gray" }} />{" "}
|
||||
<span
|
||||
style={{ fontSize: 12, color: "gray", marginLeft: 5 }}>
|
||||
999
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
<Flex vertical={false} align={"center"} wrap={true} justify={"flex-start"}>
|
||||
<Skeleton active={true} loading={loading} paragraph={{ rows: 10 }}>
|
||||
{circleList &&
|
||||
circleList.map((item: any, index: number) => {
|
||||
return (
|
||||
<div key={index}>
|
||||
<Card
|
||||
hoverable
|
||||
style={{
|
||||
width: "250px",
|
||||
boxShadow: " 0 0 10px rgba(0, 0, 0, 0.1)",
|
||||
borderRadius: 20,
|
||||
marginLeft: 30,
|
||||
marginTop: 20,
|
||||
// backgroundColor: "rgba(79,68,68,0.11)",
|
||||
}}
|
||||
onClick={() => {
|
||||
navigate("/main/share/list/" + item.id);
|
||||
}}
|
||||
cover={
|
||||
<Image
|
||||
alt="example"
|
||||
src={item.icon}
|
||||
style={{
|
||||
height: 180,
|
||||
borderTopLeftRadius: 20,
|
||||
borderTopRightRadius: 20,
|
||||
backgroundSize: "cover",
|
||||
}}
|
||||
preview={false}
|
||||
width={"100%"}
|
||||
height={"100%"}
|
||||
fallback="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg=="
|
||||
/>
|
||||
}>
|
||||
<Meta
|
||||
title={item.name}
|
||||
description={
|
||||
<>
|
||||
<Tooltip title={item.description}>
|
||||
<span>{item.description}</span>
|
||||
</Tooltip>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<Flex
|
||||
vertical={false}
|
||||
style={{ marginTop: 10 }}
|
||||
align={"center"}
|
||||
justify={"space-between"}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<Avatar
|
||||
src={item.avatar as any}
|
||||
size={"small"}
|
||||
/>{" "}
|
||||
<span
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
marginLeft: 5,
|
||||
}}>
|
||||
{item.nickName}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex
|
||||
vertical={false}
|
||||
align={"center"}
|
||||
style={{ width: 100 }}
|
||||
justify={"space-between"}>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<EyeOutlined
|
||||
style={{ color: "gray" }}
|
||||
/>{" "}
|
||||
<span
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
marginLeft: 5,
|
||||
}}>
|
||||
{item.views}
|
||||
</span>
|
||||
</Flex>
|
||||
<Flex vertical={false} align={"center"}>
|
||||
<UnorderedListOutlined
|
||||
style={{ color: "gray" }}
|
||||
/>{" "}
|
||||
<span
|
||||
style={{
|
||||
fontSize: 12,
|
||||
color: "gray",
|
||||
marginLeft: 5,
|
||||
}}>
|
||||
{item.count}
|
||||
</span>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Flex>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</Skeleton>
|
||||
</Flex>
|
||||
</ProCard>
|
||||
</div>
|
||||
@@ -114,15 +171,44 @@ const MainShare: FunctionComponent = () => {
|
||||
paddingBottom: 80,
|
||||
},
|
||||
}}
|
||||
extra={
|
||||
<Space>
|
||||
<Button onClick={onClose}>取消</Button>
|
||||
<Button onClick={onClose} type="primary">
|
||||
提交
|
||||
</Button>
|
||||
</Space>
|
||||
}>
|
||||
<Form layout="vertical">
|
||||
// extra={
|
||||
// <Space>
|
||||
// <Button onClick={onClose}>取消</Button>
|
||||
// <Button onClick={onClose} type="primary">
|
||||
// 提交
|
||||
// </Button>
|
||||
// </Space>
|
||||
// }
|
||||
>
|
||||
<Form
|
||||
layout="vertical"
|
||||
form={form}
|
||||
onFinish={(values: any) => {
|
||||
const formData = {
|
||||
userId: 17,
|
||||
...values,
|
||||
};
|
||||
addShareCircle(formData).then((res: any) => {
|
||||
if (res && res.success && res.data) {
|
||||
message
|
||||
.open({
|
||||
content: "创建成功",
|
||||
type: "success",
|
||||
})
|
||||
.then();
|
||||
setOpen(false);
|
||||
getShareCircles().then();
|
||||
form.resetFields();
|
||||
} else {
|
||||
message
|
||||
.open({
|
||||
content: res.data,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
}
|
||||
});
|
||||
}}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
label="名称"
|
||||
@@ -143,6 +229,16 @@ const MainShare: FunctionComponent = () => {
|
||||
rules={[{ required: true, message: "请输入描述!" }]}>
|
||||
<TextArea rows={4} maxLength={50} showCount placeholder="请输入描述!" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
justifyContent: "flex-end",
|
||||
}}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
提交
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Drawer>
|
||||
<FloatButton
|
||||
|
@@ -10,17 +10,15 @@ import {
|
||||
import styles from "./index.module.less";
|
||||
import { ProCard } from "@ant-design/pro-components";
|
||||
import Meta from "antd/es/card/Meta";
|
||||
import gitee from "@/assets/icons/gitee.svg";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { getAllStorage } from "@/api/oss";
|
||||
import StorageIcon from "@/constant/stroage-icon.ts";
|
||||
import { getUserInfoApi } from "@/api/user";
|
||||
|
||||
const UserInfo: FunctionComponent = () => {
|
||||
const navigate = useNavigate();
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [userStorage, setUserStorage] = useState([]);
|
||||
const [userInfo, setUserInfo] = useState<any>({} as any);
|
||||
// const [userInfo, setUserInfo] = useState<any>({} as any);
|
||||
const data = [
|
||||
{
|
||||
title: "Ant Design Title 1",
|
||||
@@ -36,20 +34,20 @@ const UserInfo: FunctionComponent = () => {
|
||||
},
|
||||
];
|
||||
async function getUserStorage() {
|
||||
const res = await getAllStorage("1");
|
||||
if (res.success) {
|
||||
const res: any = await getAllStorage("1");
|
||||
if (res && res.success && res.data) {
|
||||
setUserStorage(res.data);
|
||||
setLoading(false);
|
||||
}
|
||||
}
|
||||
const getUserInfo = async () => {
|
||||
const res = await getUserInfoApi("9");
|
||||
if (res.success) {
|
||||
setUserInfo(res.data);
|
||||
}
|
||||
};
|
||||
// const getUserInfo = async () => {
|
||||
// const res = await getUserInfoApi("9");
|
||||
// if (res && res.success && res.data) {
|
||||
// setUserInfo(res.data);
|
||||
// }
|
||||
// };
|
||||
useEffect(() => {
|
||||
getUserInfo().then();
|
||||
// getUserInfo().then();
|
||||
getUserStorage().then();
|
||||
}, []);
|
||||
return (
|
||||
|
@@ -2,9 +2,11 @@
|
||||
|
||||
import { useUserStore } from "./modules/user.ts";
|
||||
import { useFileStore } from "@/store/modules/file.ts";
|
||||
import { useShareStore } from "@/store/modules/share.ts";
|
||||
|
||||
/** 将每个Store实例化 */
|
||||
export const RootStore = {
|
||||
user: new useUserStore(),
|
||||
file: new useFileStore(),
|
||||
share: new useShareStore(),
|
||||
};
|
||||
|
@@ -5,34 +5,78 @@ import { isHydrated, makePersistable } from "mobx-persist-store";
|
||||
import { handleLocalforage } from "@/utils/localforage";
|
||||
|
||||
export class useFileStore {
|
||||
filePath: [any] = [];
|
||||
|
||||
filePath: any[] = []; // 文件路径
|
||||
currentStorage: string = ""; // 当前存储商
|
||||
currentBucket: string = ""; // 当前存储桶
|
||||
currentFile: string = ""; // 当前文件
|
||||
copyFile: string = ""; // 复制的文件地址
|
||||
pasteFile: string = ""; //粘贴的地址
|
||||
copyFileName: string = ""; // 复制的文件名
|
||||
uploadFileStorage: string = ""; // 上传文件的存储商
|
||||
uploadFileBucket: string = ""; // 上传文件的存储桶
|
||||
uploadFilePath: string = ""; // 上传文件的路径
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
filePath: observable,
|
||||
currentStorage: observable,
|
||||
currentFile: observable,
|
||||
currentBucket: observable,
|
||||
copyFile: observable,
|
||||
pasteFile: observable,
|
||||
copyFileName: observable,
|
||||
uploadFileStorage: observable,
|
||||
uploadFileBucket: observable,
|
||||
uploadFilePath: observable,
|
||||
setFilePath: action,
|
||||
getFilePath: action,
|
||||
clearFilePath: action,
|
||||
getFilePathSecondLast: action,
|
||||
getMiddlePath: action,
|
||||
clearAllFilePath: action,
|
||||
getFilePathExceptFirst: action,
|
||||
setCurrentBucket: action,
|
||||
setCurrentStorage: action,
|
||||
getCurrentBucket: action,
|
||||
getCurrentStorage: action,
|
||||
getCurrentFile: action,
|
||||
setCurrentFile: action,
|
||||
isHydrated: action,
|
||||
setCopyFile: action,
|
||||
getCopyFile: action,
|
||||
setPasteFile: action,
|
||||
getPasteFile: action,
|
||||
getCopyFileName: action,
|
||||
setCopyFileName: action,
|
||||
setUploadFileStorage: action,
|
||||
getUploadFileStorage: action,
|
||||
setUploadFileBucket: action,
|
||||
getUploadFileBucket: action,
|
||||
setUploadFilePath: action,
|
||||
getUploadFilePath: action,
|
||||
});
|
||||
makePersistable(
|
||||
this,
|
||||
{
|
||||
// 在构造函数内使用 makePersistable
|
||||
name: "file", // 保存的name,用于在storage中的名称标识,只要不和storage中其他名称重复就可以
|
||||
properties: ["filePath"], // 要保存的字段,这些字段会被保存在name对应的storage中,注意:不写在这里面的字段将不会被保存,刷新页面也将丢失:get字段例外。get数据会在数据返回后再自动计算
|
||||
properties: [
|
||||
"filePath",
|
||||
"currentStorage",
|
||||
"currentBucket",
|
||||
"currentFile",
|
||||
"copyFile",
|
||||
"pasteFile",
|
||||
"copyFileName",
|
||||
], // 要保存的字段,这些字段会被保存在name对应的storage中,注意:不写在这里面的字段将不会被保存,刷新页面也将丢失:get字段例外。get数据会在数据返回后再自动计算
|
||||
storage: handleLocalforage, // 保存的位置:可以是localStorage,sessionstorage
|
||||
removeOnExpiration: true, //如果 expireIn 具有值且已过期,则在调用 getItem 时将自动删除存储中的数据。默认值为 true。
|
||||
stringify: false, //如果为 true,则数据在传递给 setItem 之前将是 JSON.stringify。默认值为 true。
|
||||
expireIn: 2592000000, // 一个以毫秒为单位的值,用于确定 getItem 何时不应检索存储中的数据。默认情况下永不过期。
|
||||
debugMode: false, // 如果为 true,将为多个 mobx-persist-store 项调用 console.info。默认值为 false。
|
||||
// removeOnExpiration: true, //如果 expireIn 具有值且已过期,则在调用 getItem 时将自动删除存储中的数据。默认值为 true。
|
||||
// stringify: false, //如果为 true,则数据在传递给 setItem 之前将是 JSON.stringify。默认值为 true。
|
||||
// expireIn: 2592000000, // 一个以毫秒为单位的值,用于确定 getItem 何时不应检索存储中的数据。默认情况下永不过期。
|
||||
// debugMode: false, // 如果为 true,将为多个 mobx-persist-store 项调用 console.info。默认值为 false。
|
||||
},
|
||||
{
|
||||
delay: 0, // 允许您设置一个 delay 选项来限制 write 函数的调用次数。默认情况下没有延迟。
|
||||
fireImmediately: false, // 确定是应立即保留存储数据,还是等到存储中的属性发生更改。 false 默认情况下。
|
||||
// delay: 0, // 允许您设置一个 delay 选项来限制 write 函数的调用次数。默认情况下没有延迟。
|
||||
// fireImmediately: false, // 确定是应立即保留存储数据,还是等到存储中的属性发生更改。 false 默认情况下。
|
||||
},
|
||||
).then(
|
||||
action(() => {
|
||||
@@ -64,6 +108,15 @@ export class useFileStore {
|
||||
getFilePathSecondLast() {
|
||||
return this.filePath.slice(0, -1).pop();
|
||||
}
|
||||
// 获取文件路径除了第一个
|
||||
getFilePathExceptFirst() {
|
||||
if (this.filePath.length === 1) {
|
||||
return "";
|
||||
} else {
|
||||
return this.filePath.slice(1).join("/");
|
||||
}
|
||||
}
|
||||
|
||||
// 获取文件路径中间路径
|
||||
getMiddlePath() {
|
||||
if (this.filePath.length <= 2) {
|
||||
@@ -75,4 +128,72 @@ export class useFileStore {
|
||||
isHydrated() {
|
||||
return isHydrated(this);
|
||||
}
|
||||
|
||||
// 设置当前存储桶
|
||||
setCurrentBucket(currentBucket: string) {
|
||||
this.currentBucket = currentBucket;
|
||||
}
|
||||
// 设置当前存储商
|
||||
setCurrentStorage(currentStorage: string) {
|
||||
this.currentStorage = currentStorage;
|
||||
}
|
||||
// 获取当前存储商
|
||||
getCurrentStorage() {
|
||||
return this.currentStorage ? this.currentStorage : null;
|
||||
}
|
||||
// 获取当前存储桶
|
||||
getCurrentBucket() {
|
||||
return this.currentBucket ? this.currentBucket : null;
|
||||
}
|
||||
// 获取当前文件
|
||||
getCurrentFile() {
|
||||
return this.currentFile ? this.currentFile : null;
|
||||
}
|
||||
// 设置当前文件
|
||||
setCurrentFile(currentFile: string) {
|
||||
return (this.currentFile = currentFile);
|
||||
}
|
||||
//设置复制文件
|
||||
setCopyFile(copyFile: string) {
|
||||
this.copyFile = copyFile;
|
||||
}
|
||||
// 设置粘贴文件
|
||||
setPasteFile(pasteFile: string) {
|
||||
this.pasteFile = pasteFile;
|
||||
}
|
||||
// 获取复制文件
|
||||
getCopyFile() {
|
||||
return this.copyFile ? this.copyFile : null;
|
||||
}
|
||||
// 获取粘贴文件
|
||||
getPasteFile() {
|
||||
return this.pasteFile ? this.pasteFile : null;
|
||||
}
|
||||
// 设置文件名称
|
||||
setCopyFileName(copyFileName: string) {
|
||||
this.copyFileName = copyFileName;
|
||||
}
|
||||
// 获取文件名称
|
||||
getCopyFileName() {
|
||||
return this.copyFileName ? this.copyFileName : null;
|
||||
}
|
||||
setUploadFileStorage(uploadFileStorage: string) {
|
||||
this.uploadFileStorage = uploadFileStorage;
|
||||
}
|
||||
getUploadFileStorage() {
|
||||
return this.uploadFileStorage ? this.uploadFileStorage : null;
|
||||
}
|
||||
|
||||
setUploadFileBucket(uploadFileBucket: string) {
|
||||
this.uploadFileBucket = uploadFileBucket;
|
||||
}
|
||||
getUploadFileBucket() {
|
||||
return this.uploadFileBucket ? this.uploadFileBucket : null;
|
||||
}
|
||||
setUploadFilePath(uploadFilePath: string) {
|
||||
this.uploadFilePath = uploadFilePath;
|
||||
}
|
||||
getUploadFilePath() {
|
||||
return this.uploadFilePath ? this.uploadFilePath : null;
|
||||
}
|
||||
}
|
||||
|
52
src/store/modules/share.ts
Normal file
52
src/store/modules/share.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
/** @format */
|
||||
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import { isHydrated, makePersistable } from "mobx-persist-store";
|
||||
import { handleLocalforage } from "@/utils/localforage";
|
||||
|
||||
export class useShareStore {
|
||||
circleId: string = "";
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
circleId: observable,
|
||||
setCircleId: action,
|
||||
getCircleId: action,
|
||||
isHydrated: action,
|
||||
});
|
||||
makePersistable(
|
||||
this,
|
||||
{
|
||||
// 在构造函数内使用 makePersistable
|
||||
name: "shareInfo", // 保存的name,用于在storage中的名称标识,只要不和storage中其他名称重复就可以
|
||||
properties: ["circleId"], // 要保存的字段,这些字段会被保存在name对应的storage中,注意:不写在这里面的字段将不会被保存,刷新页面也将丢失:get字段例外。get数据会在数据返回后再自动计算
|
||||
storage: handleLocalforage, // 保存的位置:可以是localStorage,sessionstorage
|
||||
// removeOnExpiration: true, //如果 expireIn 具有值且已过期,则在调用 getItem 时将自动删除存储中的数据。默认值为 true。
|
||||
// stringify: false, //如果为 true,则数据在传递给 setItem 之前将是 JSON.stringify。默认值为 true。
|
||||
// expireIn: 2592000000, // 一个以毫秒为单位的值,用于确定 getItem 何时不应检索存储中的数据。默认情况下永不过期。
|
||||
// debugMode: false, // 如果为 true,将为多个 mobx-persist-store 项调用 console.info。默认值为 false。
|
||||
} as any,
|
||||
{
|
||||
// delay: 0, // 允许您设置一个 delay 选项来限制 write 函数的调用次数。默认情况下没有延迟。
|
||||
// fireImmediately: false, // 确定是应立即保留存储数据,还是等到存储中的属性发生更改。 false 默认情况下。
|
||||
},
|
||||
).then(
|
||||
action(() => {
|
||||
// persist 完成的回调,在这里可以执行一些拿到数据后需要执行的操作,如果在页面上要判断是否完成persist,使用 isHydrated
|
||||
// console.log(persistStore)
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
getCircleId() {
|
||||
return this.circleId ? this.circleId : null;
|
||||
}
|
||||
|
||||
isHydrated() {
|
||||
return isHydrated(this);
|
||||
}
|
||||
|
||||
setCircleId(circleId: string) {
|
||||
this.circleId = circleId;
|
||||
}
|
||||
}
|
@@ -1,64 +1,64 @@
|
||||
/** @format */
|
||||
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import { isHydrated, makePersistable } from "mobx-persist-store";
|
||||
import { handleLocalforage } from "@/utils/localforage";
|
||||
|
||||
export class useUserStore {
|
||||
token: string = "";
|
||||
userId: string = "";
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
token: observable,
|
||||
userId: observable,
|
||||
setToken: action,
|
||||
setUserId: action,
|
||||
getToken: action,
|
||||
getUserId: action,
|
||||
isHydrated: action,
|
||||
});
|
||||
makePersistable(
|
||||
this,
|
||||
{
|
||||
// 在构造函数内使用 makePersistable
|
||||
name: "userInfo", // 保存的name,用于在storage中的名称标识,只要不和storage中其他名称重复就可以
|
||||
properties: ["token", "userId"], // 要保存的字段,这些字段会被保存在name对应的storage中,注意:不写在这里面的字段将不会被保存,刷新页面也将丢失:get字段例外。get数据会在数据返回后再自动计算
|
||||
storage: handleLocalforage, // 保存的位置:可以是localStorage,sessionstorage
|
||||
removeOnExpiration: true, //如果 expireIn 具有值且已过期,则在调用 getItem 时将自动删除存储中的数据。默认值为 true。
|
||||
stringify: false, //如果为 true,则数据在传递给 setItem 之前将是 JSON.stringify。默认值为 true。
|
||||
expireIn: 2592000000, // 一个以毫秒为单位的值,用于确定 getItem 何时不应检索存储中的数据。默认情况下永不过期。
|
||||
debugMode: false, // 如果为 true,将为多个 mobx-persist-store 项调用 console.info。默认值为 false。
|
||||
},
|
||||
{
|
||||
delay: 0, // 允许您设置一个 delay 选项来限制 write 函数的调用次数。默认情况下没有延迟。
|
||||
fireImmediately: false, // 确定是应立即保留存储数据,还是等到存储中的属性发生更改。 false 默认情况下。
|
||||
},
|
||||
).then(
|
||||
action(() => {
|
||||
// persist 完成的回调,在这里可以执行一些拿到数据后需要执行的操作,如果在页面上要判断是否完成persist,使用 isHydrated
|
||||
// console.log(persistStore)
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this.token ? this.token : null;
|
||||
}
|
||||
|
||||
getUserId() {
|
||||
return this.userId ? this.userId : null;
|
||||
}
|
||||
|
||||
isHydrated() {
|
||||
return isHydrated(this);
|
||||
}
|
||||
|
||||
setToken(token: string) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
setUserId(userId: string) {
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
/** @format */
|
||||
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import { isHydrated, makePersistable } from "mobx-persist-store";
|
||||
import { handleLocalforage } from "@/utils/localforage";
|
||||
|
||||
export class useUserStore {
|
||||
token: string = "";
|
||||
userId: string = "";
|
||||
|
||||
constructor() {
|
||||
makeObservable(this, {
|
||||
token: observable,
|
||||
userId: observable,
|
||||
setToken: action,
|
||||
setUserId: action,
|
||||
getToken: action,
|
||||
getUserId: action,
|
||||
isHydrated: action,
|
||||
});
|
||||
makePersistable(
|
||||
this,
|
||||
{
|
||||
// 在构造函数内使用 makePersistable
|
||||
name: "userInfo", // 保存的name,用于在storage中的名称标识,只要不和storage中其他名称重复就可以
|
||||
properties: ["token", "userId"], // 要保存的字段,这些字段会被保存在name对应的storage中,注意:不写在这里面的字段将不会被保存,刷新页面也将丢失:get字段例外。get数据会在数据返回后再自动计算
|
||||
storage: handleLocalforage, // 保存的位置:可以是localStorage,sessionstorage
|
||||
// removeOnExpiration: true, //如果 expireIn 具有值且已过期,则在调用 getItem 时将自动删除存储中的数据。默认值为 true。
|
||||
// stringify: false, //如果为 true,则数据在传递给 setItem 之前将是 JSON.stringify。默认值为 true。
|
||||
// expireIn: 2592000000, // 一个以毫秒为单位的值,用于确定 getItem 何时不应检索存储中的数据。默认情况下永不过期。
|
||||
// debugMode: false, // 如果为 true,将为多个 mobx-persist-store 项调用 console.info。默认值为 false。
|
||||
},
|
||||
{
|
||||
// delay: 0, // 允许您设置一个 delay 选项来限制 write 函数的调用次数。默认情况下没有延迟。
|
||||
// fireImmediately: false, // 确定是应立即保留存储数据,还是等到存储中的属性发生更改。 false 默认情况下。
|
||||
},
|
||||
).then(
|
||||
action(() => {
|
||||
// persist 完成的回调,在这里可以执行一些拿到数据后需要执行的操作,如果在页面上要判断是否完成persist,使用 isHydrated
|
||||
// console.log(persistStore)
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return this.token ? this.token : null;
|
||||
}
|
||||
|
||||
getUserId() {
|
||||
return this.userId ? this.userId : null;
|
||||
}
|
||||
|
||||
isHydrated() {
|
||||
return isHydrated(this);
|
||||
}
|
||||
|
||||
setToken(token: string) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
setUserId(userId: string) {
|
||||
this.userId = userId;
|
||||
}
|
||||
}
|
||||
|
25
src/types/user.d.ts
vendored
25
src/types/user.d.ts
vendored
@@ -29,4 +29,29 @@ declare namespace API {
|
||||
token: string;
|
||||
deg: number;
|
||||
};
|
||||
type AliOSSConfigRequest = {
|
||||
userId?:number;
|
||||
endpoint?:string;
|
||||
accessKeyId?:string;
|
||||
accessKeySecret?:string;
|
||||
}
|
||||
type MinioOSSConfigRequest = {
|
||||
userId?:number;
|
||||
endpoint?:string;
|
||||
accessKey?:string;
|
||||
secretKey?:string;
|
||||
}
|
||||
type QiniuOSSConfigRequest = {
|
||||
userId?:number;
|
||||
endpoint?:string;
|
||||
accessKey?:string;
|
||||
secretKey?:string;
|
||||
region?:string;
|
||||
}
|
||||
type TencentOSSConfigRequest = {
|
||||
userId?:number;
|
||||
appId?:string;
|
||||
secretKey?:string;
|
||||
region?:string;
|
||||
}
|
||||
}
|
||||
|
@@ -1,174 +1,163 @@
|
||||
/** @format */
|
||||
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import { message } from "antd";
|
||||
import { getStorageFromKey } from "@/utils/localStorage/config.ts";
|
||||
|
||||
class Request {
|
||||
private instance: AxiosInstance | undefined;
|
||||
|
||||
constructor(config: AxiosRequestConfig) {
|
||||
this.instance = axios.create(config);
|
||||
// 全局请求拦截
|
||||
this.instance.interceptors.request.use(
|
||||
(config) => {
|
||||
const token: string | null = getStorageFromKey("token");
|
||||
if (token) {
|
||||
config.headers.Authorization = `${import.meta.env.VITE_APP_TOKEN_KEY} ${token}`;
|
||||
}
|
||||
|
||||
// if (config.method == "post") {
|
||||
// config.data = EncryptData(JSON.stringify(config.data));
|
||||
// }
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// 全局响应拦截
|
||||
this.instance.interceptors.response.use(
|
||||
(response) => {
|
||||
// 后端返回字符串表示需要解密操作
|
||||
// if (typeof response.data == "string") {
|
||||
// response.data = DecryptData(response.data);
|
||||
// if (response.status !== 200) {
|
||||
// message.error(response.statusText).then();
|
||||
// return Promise.reject(response.data);
|
||||
// }
|
||||
// }
|
||||
return response.data;
|
||||
},
|
||||
(error) => {
|
||||
const { response } = error;
|
||||
if (response) {
|
||||
this.handleCode(response.status);
|
||||
}
|
||||
if (!window.navigator.onLine) {
|
||||
message.error("网络连接失败");
|
||||
// return router.push({
|
||||
// path: '/404',
|
||||
// })
|
||||
return Promise.reject(error);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
handleCode(code: number): void {
|
||||
switch (code) {
|
||||
case 400:
|
||||
message
|
||||
.open({
|
||||
content: "请求错误(400)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 401:
|
||||
message
|
||||
.open({
|
||||
content: "未授权,请重新登录(401)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 403:
|
||||
message
|
||||
.open({
|
||||
content: "拒绝访问(403)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 404:
|
||||
message
|
||||
.open({
|
||||
content: "请求出错(404)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 408:
|
||||
message
|
||||
.open({
|
||||
content: "请求超时(408)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 500:
|
||||
message
|
||||
.open({
|
||||
content: "服务器错误(500)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 501:
|
||||
message
|
||||
.open({
|
||||
content: "服务未实现(501)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 502:
|
||||
message
|
||||
.open({
|
||||
content: "网络错误(502)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 503:
|
||||
message
|
||||
.open({
|
||||
content: "服务不可用(503)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 504:
|
||||
message
|
||||
.open({
|
||||
content: "网络超时(504)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 505:
|
||||
message
|
||||
.open({
|
||||
content: "HTTP版本不受支持(505)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
default:
|
||||
message
|
||||
.open({
|
||||
content: `连接出错(${code})!`,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.instance
|
||||
?.request<any, T>(config)
|
||||
.then((res) => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Request;
|
||||
/** @format */
|
||||
|
||||
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import { message } from "antd";
|
||||
import { getStorageFromKey } from "@/utils/localStorage/config.ts";
|
||||
|
||||
class Request {
|
||||
private instance: AxiosInstance | undefined;
|
||||
|
||||
constructor(config: AxiosRequestConfig) {
|
||||
this.instance = axios.create(config);
|
||||
// 全局请求拦截
|
||||
this.instance.interceptors.request.use(
|
||||
(config) => {
|
||||
const token: string | null = getStorageFromKey("token");
|
||||
if (token) {
|
||||
config.headers.Authorization = `${import.meta.env.VITE_APP_TOKEN_KEY} ${token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
},
|
||||
);
|
||||
|
||||
// 全局响应拦截
|
||||
this.instance.interceptors.response.use(
|
||||
(response) => {
|
||||
if (response.data instanceof Blob) {
|
||||
return response;
|
||||
} else {
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
const { response } = error;
|
||||
if (response) {
|
||||
this.handleCode(response.status);
|
||||
}
|
||||
if (!window.navigator.onLine) {
|
||||
message.error("网络连接失败");
|
||||
return Promise.reject(error);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
handleCode(code: number): void {
|
||||
switch (code) {
|
||||
case 400:
|
||||
message
|
||||
.open({
|
||||
content: "请求错误(400)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 401:
|
||||
message
|
||||
.open({
|
||||
content: "未授权,请重新登录(401)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 403:
|
||||
message
|
||||
.open({
|
||||
content: "拒绝访问(403)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 404:
|
||||
message
|
||||
.open({
|
||||
content: "请求出错(404)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 408:
|
||||
message
|
||||
.open({
|
||||
content: "请求超时(408)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 500:
|
||||
message
|
||||
.open({
|
||||
content: "服务器错误(500)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 501:
|
||||
message
|
||||
.open({
|
||||
content: "服务未实现(501)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 502:
|
||||
message
|
||||
.open({
|
||||
content: "网络错误(502)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 503:
|
||||
message
|
||||
.open({
|
||||
content: "服务不可用(503)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 504:
|
||||
message
|
||||
.open({
|
||||
content: "网络超时(504)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
case 505:
|
||||
message
|
||||
.open({
|
||||
content: "HTTP版本不受支持(505)",
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
default:
|
||||
message
|
||||
.open({
|
||||
content: `连接出错(${code})!`,
|
||||
type: "error",
|
||||
})
|
||||
.then();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
request<T>(config: AxiosRequestConfig<T>): Promise<T> {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
this.instance
|
||||
?.request<any, T>(config)
|
||||
.then((res) => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default Request;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/** @format */
|
||||
|
||||
import Request from "./request";
|
||||
|
||||
const web: Request = new Request({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
export default web;
|
||||
/** @format */
|
||||
|
||||
import Request from "./request";
|
||||
|
||||
const web: Request = new Request({
|
||||
baseURL: import.meta.env.VITE_APP_BASE_API,
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
export default web;
|
||||
|
@@ -11,7 +11,6 @@ import {
|
||||
PageContainer,
|
||||
ProCard,
|
||||
ProLayout,
|
||||
SettingDrawer,
|
||||
} from "@ant-design/pro-components";
|
||||
import { Link, Outlet, useLocation } from "react-router-dom";
|
||||
import logo from "@/assets/images/logo.png";
|
||||
|
77
src/vite-env.d.ts
vendored
77
src/vite-env.d.ts
vendored
@@ -1,38 +1,39 @@
|
||||
/** @format */
|
||||
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare interface ImportMetaEnv {
|
||||
readonly VITE_APP_BASE_API: string;
|
||||
readonly VITE_APP_TITLE: string;
|
||||
readonly VITE_API_BASE_URL: string;
|
||||
readonly VITE_NODE_ENV: string;
|
||||
readonly VITE_TITLE_NAME: string;
|
||||
readonly VITE_APP_TOKEN_KEY?: string;
|
||||
readonly VITE_UPLOAD_URL?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
declare module "*.svg" {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module "*.js" {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module ".*" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.tsx";
|
||||
declare module "*.svg";
|
||||
declare module "*.png";
|
||||
declare module "*.jpg";
|
||||
declare module "*.jpeg";
|
||||
declare module "*.gif";
|
||||
declare module "*.bmp";
|
||||
declare module "*.tiff";
|
||||
/** @format */
|
||||
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
declare interface ImportMetaEnv {
|
||||
readonly VITE_APP_BASE_API: string;
|
||||
readonly VITE_APP_TITLE: string;
|
||||
readonly VITE_API_BASE_URL: string;
|
||||
readonly VITE_NODE_ENV: string;
|
||||
readonly VITE_TITLE_NAME: string;
|
||||
readonly VITE_APP_TOKEN_KEY?: string;
|
||||
readonly VITE_UPLOAD_URL?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
|
||||
declare module "*.svg" {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module "*.js" {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
declare module ".*" {
|
||||
const value: any;
|
||||
export default value;
|
||||
}
|
||||
declare module "*.tsx";
|
||||
declare module "*.svg";
|
||||
declare module "*.png";
|
||||
declare module "*.jpg";
|
||||
declare module "*.jpeg";
|
||||
declare module "*.gif";
|
||||
declare module "*.bmp";
|
||||
declare module "*.tiff";
|
||||
declare module "base-64";
|
||||
|
Reference in New Issue
Block a user