diff --git a/.env.development b/.env.development index 0ae9885..600fadb 100644 --- a/.env.development +++ b/.env.development @@ -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' diff --git a/.eslintignore b/.eslintignore index a8bbb59..adde2d8 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,4 +1,3 @@ node_modules .eslintrc.cjs dist -/src/components/Main/Home/index.tsx diff --git a/package.json b/package.json index 62015ff..1f3497a 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 60d96fe..3a209ad 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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 diff --git a/src/api/oss/ali/index.ts b/src/api/oss/ali/index.ts index 0d1de92..c77cef6 100644 --- a/src/api/oss/ali/index.ts +++ b/src/api/oss/ali/index.ts @@ -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, + }, + }); +}; diff --git a/src/api/oss/index.ts b/src/api/oss/index.ts index 75f8f79..336c0e3 100644 --- a/src/api/oss/index.ts +++ b/src/api/oss/index.ts @@ -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, + }); +}; diff --git a/src/api/oss/minio/index.ts b/src/api/oss/minio/index.ts index 5a11d88..29a7611 100644 --- a/src/api/oss/minio/index.ts +++ b/src/api/oss/minio/index.ts @@ -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, + }, + }); +}; diff --git a/src/api/oss/qiniu/index.ts b/src/api/oss/qiniu/index.ts index ff88cb6..148f86b 100644 --- a/src/api/oss/qiniu/index.ts +++ b/src/api/oss/qiniu/index.ts @@ -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, + }, + }); +}; diff --git a/src/api/oss/tencent/index.ts b/src/api/oss/tencent/index.ts index 3060062..98dc1b1 100644 --- a/src/api/oss/tencent/index.ts +++ b/src/api/oss/tencent/index.ts @@ -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, + }, + }); +}; diff --git a/src/api/share/index.ts b/src/api/share/index.ts new file mode 100644 index 0000000..eb982ee --- /dev/null +++ b/src/api/share/index.ts @@ -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, + }, + }); +}; diff --git a/src/components/Main/Bucket/components/AliDrawer.tsx b/src/components/Main/Bucket/components/AliDrawer.tsx index bb6bb10..6582417 100644 --- a/src/components/Main/Bucket/components/AliDrawer.tsx +++ b/src/components/Main/Bucket/components/AliDrawer.tsx @@ -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>; -}>({} as any); const AliDrawer = () => { - const [drawerVisit, setDrawerVisit] = useState(false); - return ( - - - - ); -}; -const ProCardComponent = () => { - const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const [buckets, setBuckets] = useState([]); const [loading, setLoading] = useState(true); + const [bucketSize, setBucketSize] = useState(""); + const [form] = Form.useForm(); + const [open, setOpen] = useState(false); async function getAllBucket() { getAllAliOSsBucket("2").then((res: any) => { @@ -37,10 +28,11 @@ const ProCardComponent = () => { useEffect(() => { getAllBucket().then(); }, []); + const bucketList = () => { return ( @@ -53,7 +45,7 @@ const ProCardComponent = () => { getAllBucket().then(); }} icon={}> - @@ -63,33 +55,90 @@ const ProCardComponent = () => { {buckets && Array.from(buckets).map((item: any, index: number) => { return ( - <> -
- {item.name}} - style={{ - width: "180px", - height: 150, - borderWidth: "1px", - marginLeft: 10, - }} - actions={[ - , - , - , - ]}> - - {item.size} - -
- +
+ + { + getBucketSize( + 1, + item.name, + "minio", + ).then((res: any) => { + if ( + res && + res.success && + res.data + ) { + setBucketSize(res.data); + } else { + message + .open({ + content: "计算出错!", + type: "error", + }) + .then(); + } + }); + }} + /> + , + // eslint-disable-next-line react/jsx-key + { + 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"> + + , + ]}> + + {item.name} + +
); })} @@ -101,32 +150,49 @@ const ProCardComponent = () => { return ( <> {bucketList()} - { - console.log(values.name); - message.success("提交成功"); - return true; - }}> - - { + 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)}> +
+ - - - - + label="存储桶名称" + rules={[{ required: true, message: "请输入存储桶名称!" }]}> + + +
+ ); }; diff --git a/src/components/Main/Bucket/components/MinioDrawer.tsx b/src/components/Main/Bucket/components/MinioDrawer.tsx index 553aa9e..cfa29e5 100644 --- a/src/components/Main/Bucket/components/MinioDrawer.tsx +++ b/src/components/Main/Bucket/components/MinioDrawer.tsx @@ -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>; -}>({} as any); const MinioDrawer = () => { - const [drawerVisit, setDrawerVisit] = useState(false); - return ( - - - - ); -}; -const ProCardComponent = () => { - const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const [buckets, setBuckets] = useState([]); const [loading, setLoading] = useState(true); + const [bucketSize, setBucketSize] = useState(""); + const [form] = Form.useForm(); + const [open, setOpen] = useState(false); async function getAllBucket() { getAllMinioBucket("1").then((res: any) => { @@ -53,7 +44,7 @@ const ProCardComponent = () => { getAllBucket().then(); }} icon={}> - @@ -68,23 +59,83 @@ const ProCardComponent = () => { headStyle={{ backgroundColor: "#f0f2f5" }} hoverable bordered - title={{item.name}} + // title={} style={{ - width: "180px", - height: "150px", - marginLeft: 10, + width: "200px", + marginLeft: 20, }} actions={[ - , - , - , + // eslint-disable-next-line react/jsx-key + + { + getBucketSize( + 1, + item.name, + "minio", + ).then((res: any) => { + if ( + res && + res.success && + res.data + ) { + setBucketSize(res.data); + } else { + message + .open({ + content: "计算出错!", + type: "error", + }) + .then(); + } + }); + }} + /> + , + // eslint-disable-next-line react/jsx-key + { + 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"> + + , ]}> - {item.size} + {item.name}
); @@ -98,32 +149,49 @@ const ProCardComponent = () => { return ( <> {bucketList()} - { - console.log(values.name); - message.success("提交成功"); - return true; - }}> - - { + 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)}> +
+ - - - - + label="存储桶名称" + rules={[{ required: true, message: "请输入存储桶名称!" }]}> + + +
+ ); }; diff --git a/src/components/Main/Bucket/components/QingyunDrawer.tsx b/src/components/Main/Bucket/components/QingyunDrawer.tsx index eae71f3..a2c80e5 100644 --- a/src/components/Main/Bucket/components/QingyunDrawer.tsx +++ b/src/components/Main/Bucket/components/QingyunDrawer.tsx @@ -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<{ diff --git a/src/components/Main/Bucket/components/QiniuDrawer.tsx b/src/components/Main/Bucket/components/QiniuDrawer.tsx index b7ca6fb..5ef5f62 100644 --- a/src/components/Main/Bucket/components/QiniuDrawer.tsx +++ b/src/components/Main/Bucket/components/QiniuDrawer.tsx @@ -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>; -}>({} as any); const QiniuDrawer = () => { - const [drawerVisit, setDrawerVisit] = useState(false); - return ( - - - - ); -}; -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([]); + const [loading, setLoading] = useState(true); + const [bucketSize, setBucketSize] = useState(""); + const [form] = Form.useForm(); + const [open, setOpen] = useState(false); + + async function getAllBucket() { + getAllMinioBucket("1").then((res: any) => { + if (res && res.success) { + setBuckets(res.data); + setLoading(false); + } + }); + } + + useEffect(() => { + getAllBucket().then(); + }, []); const bucketList = () => { return ( setDrawerVisit(true)}> - 创建存储桶 - + <> + + + }>
- {list.map((item, index) => { - return ( - 名字:{item}} - style={{ - width: "180px", - borderWidth: "1px", - }} - actions={[ - , - , - , - ]}> - - size - - ); - })} + + {buckets && + Array.from(buckets).map((item: any, index: number) => { + return ( +
+ + { + getBucketSize( + 1, + item.name, + "minio", + ).then((res: any) => { + if ( + res && + res.success && + res.data + ) { + setBucketSize(res.data); + } else { + message + .open({ + content: "计算出错!", + type: "error", + }) + .then(); + } + }); + }} + /> + , + // eslint-disable-next-line react/jsx-key + { + 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"> + + , + ]}> + + {item.name} + +
+ ); + })} +
); @@ -86,32 +150,49 @@ const ProCardComponent = () => { return ( <> {bucketList()} - { - console.log(values.name); - message.success("提交成功"); - return true; - }}> - - { + 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)}> +
+ - - - - + label="存储桶名称" + rules={[{ required: true, message: "请输入存储桶名称!" }]}> + + +
+ ); }; diff --git a/src/components/Main/Bucket/components/TencentDrawer.tsx b/src/components/Main/Bucket/components/TencentDrawer.tsx index 18685eb..969e253 100644 --- a/src/components/Main/Bucket/components/TencentDrawer.tsx +++ b/src/components/Main/Bucket/components/TencentDrawer.tsx @@ -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>; -}>({} as any); const TencentDrawer = () => { - const [drawerVisit, setDrawerVisit] = useState(false); - return ( - - - - ); -}; -const ProCardComponent = () => { - const { drawerVisit, setDrawerVisit } = useContext(DrawerContext); const [buckets, setBuckets] = useState([]); const [loading, setLoading] = useState(true); + const [bucketSize, setBucketSize] = useState(""); + const [form] = Form.useForm(); + const [open, setOpen] = useState(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 ( setDrawerVisit(true)}> - 创建存储桶 - + <> + + + }>
@@ -58,23 +60,83 @@ const ProCardComponent = () => { headStyle={{ backgroundColor: "#f0f2f5" }} hoverable bordered - title={{item.name}} + // title={} style={{ width: "180px", - height: "150px", marginLeft: 10, }} actions={[ - , - , - , + // eslint-disable-next-line react/jsx-key + + { + getBucketSize( + 1, + item.name, + "minio", + ).then((res: any) => { + if ( + res && + res.success && + res.data + ) { + setBucketSize(res.data); + } else { + message + .open({ + content: "计算出错!", + type: "error", + }) + .then(); + } + }); + }} + /> + , + // eslint-disable-next-line react/jsx-key + { + 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"> + + , ]}> - {item.size} + {item.name}
); @@ -88,32 +150,49 @@ const ProCardComponent = () => { return ( <> {bucketList()} - { - console.log(values.name); - message.success("提交成功"); - return true; - }}> - - { + 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)}> +
+ - - - - + label="存储桶名称" + rules={[{ required: true, message: "请输入存储桶名称!" }]}> + + +
+ ); }; diff --git a/src/components/Main/File/components/FileUpload.tsx b/src/components/Main/File/components/FileUpload.tsx index f7cbb5f..3f20c18 100644 --- a/src/components/Main/File/components/FileUpload.tsx +++ b/src/components/Main/File/components/FileUpload.tsx @@ -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([]); + 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 ( <> @@ -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 ( - + <> { flexDirection: "row", }} size={"small"}> - {" "} + - {storage.name} + {label.label} - + ); - })} - + }} + options={props.userStorage} + notFoundContent={"未找到,请先配置存储商"} + optionRender={(item: any) => { + return ( + <> + + + + {item.label} + + + + ); + }} + placeholder={"请选择存储商"}> + - + }} + placeholder={"请选择存储桶"}> + { + store.setUploadFilePath(e.target.value); + }} + style={{ marginLeft: 10, width: "40%" }}>
- + uploadFile}>

+

单击或拖动文件到此区域进行上传

-

支持单次或批量上传。

+

只支持单次上传。

diff --git a/src/components/Main/File/index.tsx b/src/components/Main/File/index.tsx index 9fa328c..c07dbb0 100644 --- a/src/components/Main/File/index.tsx +++ b/src/components/Main/File/index.tsx @@ -1,5 +1,5 @@ /** @format */ -import React, { FunctionComponent, useEffect, useState } from "react"; +import { FunctionComponent, useEffect, useState } from "react"; import { CheckCard, ProCard } from "@ant-design/pro-components"; import styles from "./index.module.less"; import { @@ -14,23 +14,26 @@ import { Input, message, Modal, + Popover, + QRCode, Select, + Skeleton, Tooltip, } from "antd"; import bucket from "@/assets/icons/bucket.svg"; import { + CheckOutlined, CloudUploadOutlined, CopyOutlined, DeleteOutlined, DownloadOutlined, + EditOutlined, EllipsisOutlined, EyeOutlined, LeftOutlined, QrcodeOutlined, RedoOutlined, ReloadOutlined, - ScissorOutlined, - SearchOutlined, SnippetsOutlined, } from "@ant-design/icons"; import standard_dir from "@/assets/icons/standard_directory.svg"; @@ -39,34 +42,39 @@ import { observer } from "mobx-react"; import FileIcon from "@/constant/file-icon.ts"; import file_icon from "@/assets/icons/files/file.svg"; import FileUpload from "@/components/Main/File/components/FileUpload.tsx"; -import { getAllStorage, getBucketFiles, getStorageBuckets } from "@/api/oss"; +import logo from "@/assets/images/logo.png"; +import { + copyFile, + deleteFile, + downloadFiles, + getAllStorage, + getBucketFiles, + getStorageBuckets, + previewFile, + renameFile, +} from "@/api/oss"; import StorageIcon from "@/constant/stroage-icon.ts"; -const fileList: any = [ - { - name: "test1.png", - isDir: false, - path: "test1.png", - length: "1766511", - createTime: "2024-06-29T10:28:03.224Z", - }, - { - name: "schisandra", - isDir: true, - path: "schisandra/", - }, -]; - +import { useNavigate } from "react-router-dom"; +import Base64 from "base-64"; const File: FunctionComponent = () => { const store = useStore("file"); + const navigate = useNavigate(); const [files, setFiles] = useState([]); const [loading, setLoading] = useState(true); - const [bucketLoading, setBucketLoading] = useState(true); + const [loadingFile, setLoadingFile] = useState(true); const [open, setOpen] = useState(false); + const [openRename, setOpenRename] = useState(false); const [userStorage, setUserStorage] = useState([]); const [buckets, setBuckets] = useState([]); - const [currentStorage, setCurrentStorage] = useState(null); - const [currentBucket, setCurrentBucket] = useState(null); + const [newFileName, setNewFileName] = useState(null); + const [disable, setDisable] = useState(true); + const [previewUrl, setPreviewUrl] = useState(null); + function setLoadingTimeOut() { + setTimeout(() => { + setLoadingFile(false); + }, 500); + } async function getUserStorage() { getAllStorage("1").then((res: any) => { if (res && res.success) { @@ -79,6 +87,7 @@ const File: FunctionComponent = () => { return getBucketFiles("1", bucket, dirName, type).then((res: any) => { if (res && res.success) { setFiles(res.data); + setLoadingTimeOut(); } }); } @@ -90,7 +99,6 @@ const File: FunctionComponent = () => { getStorageBuckets("1", type).then((res: any) => { if (res && res.success) { setBuckets(res.data); - setBucketLoading(false); } }); } @@ -116,58 +124,84 @@ const File: FunctionComponent = () => { showSearch={true} allowClear={true} onSelect={(value: any) => { - setCurrentStorage(value); + store.setCurrentStorage(value); getBuckets(value).then(); }} onClear={() => { - setCurrentStorage(null); + store.setCurrentStorage(""); setBuckets([]); }} onChange={(value: any) => { - setCurrentStorage(value); - // getBuckets(value).then(); + store.setCurrentStorage(value); }} + fieldNames={{ + label: "name", + value: "ossType", + }} + labelRender={(label: any) => { + return ( + <> + + + + {label.label} + + + + ); + }} + options={userStorage} notFoundContent={"未找到,请先配置存储商"} - placeholder={"请选择存储商"}> - {userStorage && - userStorage.map((item: any, index: number) => { - return ( - <> - - - - - {item.name} - - - - - ); - })} - + optionRender={(item: any) => { + return ( + <> + + + + {item.label} + + + + ); + }} + placeholder={"请选择存储商"}> @@ -176,14 +210,14 @@ const File: FunctionComponent = () => {
{ + setFiles([]); store.clearAllFilePath(); store.setFilePath(`/${value}`); - setCurrentBucket(value); - console.log(value); + store.setCurrentBucket(value); if (value !== undefined) { - getFiles(value, "", currentStorage).then(); + setLoadingFile(true); + getFiles(value, "", store.getCurrentStorage()).then(); } }} style={{ width: "100%" }}> @@ -196,51 +230,46 @@ const File: FunctionComponent = () => { {buckets && Array.from(buckets).map((item: any, index: number) => { return ( - <> -
- { - domEvent.stopPropagation(); - message.info( - "menu click", +
+ { + if ( + value.key === "view" + ) { + navigate( + "/main/bucket", ); - }, - items: [ - { - label: "删除", - key: "1", - }, - { - label: "查看", - key: "2", - }, - ], - }}> - - e.stopPropagation() } - /> - - } - /> -
- + }, + items: [ + { + label: "查看", + key: "view", + }, + ], + }}> + + e.stopPropagation() + } + /> + + } + /> +
); })} @@ -258,18 +287,59 @@ const File: FunctionComponent = () => { shape="circle" icon={} onClick={() => { - getFiles( - currentBucket, - store.getMiddlePath(), - currentStorage, - ).then(() => { - store.clearFilePath(); - }); + if ( + store.getCurrentBucket() === null || + store.getCurrentStorage() === null + ) { + message.open({ + content: "请选择存储商和桶", + type: "warning", + }); + return; + } + if (store.getFilePath().length === 1) { + if (files.length !== 0) { + return; + } + setLoadingFile(true); + getFiles( + store.getCurrentBucket(), + "", + store.getCurrentStorage(), + ).then(); + } else { + setLoadingFile(true); + getFiles( + store.getCurrentBucket(), + store.getMiddlePath(), + store.getCurrentStorage(), + ).then(() => { + store.clearFilePath(); + }); + } }} /> + + } + title={"重命名:" + store.getCurrentFile()} + trigger="click"> +
- - {files.map((file: any, index: any) => { - if (file.isDir) { - return ( - -
{ - getFiles( - currentBucket, - `${file.name}/`, - currentStorage, - ).then(() => { - store.setFilePath(file.name); - }); - }}> - - - - - {file.name} - - -
- } - className={styles.file_card} - style={{ - width: 100, - height: 100, - display: "flex", - alignItems: "center", - justifyContent: "center", - }} - /> -
- - ); - } else { - return ( - -
- - + + {files.map((file: any, index: any) => { + if (file.isDir) { + return ( + +
{ + if ( + store.getCurrentBucket() === null || + store.getCurrentStorage() === null + ) { + message.open({ + content: "请选择存储商和桶", + type: "warning", + }); + return; + } + setLoadingTimeOut(); + getFiles( + store.getCurrentBucket(), + `${store.getFilePathExceptFirst()}/${file.name}`, + store.getCurrentStorage(), + ).then(() => { + store.setFilePath(file.name); + }); + }}> + + + + + {file.name} + + +
+ } + className={styles.file_card} + style={{ + width: 100, + height: 100, + display: "flex", + alignItems: "center", + justifyContent: "center", + }} + /> +
+
+ ); + } else { + return ( + { + if (key === "delete") { + deleteFile( + 1, + store.getCurrentBucket(), + store.getCurrentStorage(), + store.getFilePathExceptFirst() + + "/" + + file.name, + ).then((res: any) => { + if (res && res.success) { + message.open({ + content: "删除成功!", + type: "success", + }); + } else { + message.open({ + content: "删除失败!", + type: "error", + }); } - shape={"square"} - size={"large"} - /> - - - {file.name} - - - - } - className={styles.file_card} - style={{ - width: 100, - height: 100, - display: "flex", - alignItems: "center", - justifyContent: "center", - }} - /> - - - ); - } - })} - + }); + } else if (key === "view") { + previewFile( + 1, + store.getCurrentBucket(), + store.getCurrentStorage(), + store.getFilePathExceptFirst() + + "/" + + file.name, + ).then((res: any) => { + if ( + res && + res.success && + res.data + ) { + window.open( + "http://1.95.0.111:8012/onlinePreview?url=" + + encodeURIComponent( + Base64.encode( + res.data, + ) as any, + ), + ); + } + }); + } else if (key === "copy") { + if ( + store.getCurrentFile() !== "" && + store.getCurrentFile() !== null + ) { + message + .open({ + content: "复制成功 ", + type: "success", + }) + .then(); + store.setCopyFile( + store.getCurrentFile() as string, + ); + setDisable(false); + } else { + message + .open({ + content: + "请先选择文件!", + type: "warning", + }) + .then(); + } + } else if (key === "paste") { + if (disable) { + message + .open({ + content: "请先复制文件", + type: "warning", + }) + .then(); + } else { + copyFile( + 1, + store.getCurrentBucket(), + store.getCurrentStorage(), + store.getCopyFile(), + store.getFilePathExceptFirst() + + "/" + + store.getCopyFileName(), + ).then((res: any) => { + if (res && res.success) { + message + .open({ + content: + "粘贴成功 ", + type: "success", + }) + .then(); + setDisable(true); + } else { + message + .open({ + content: + "粘贴失败 ", + type: "error", + }) + .then(); + } + }); + } + } + }, + items: [ + { + label: "复制", + key: "copy", + icon: , + }, + { + label: "粘贴", + key: "paste", + icon: , + }, + { + label: "删除", + key: "delete", + icon: , + }, + { + label: "预览", + key: "view", + icon: , + }, + ], + }} + trigger={["contextMenu"]}> +
+ { + if (value) { + const pathExceptFirst = + store.getFilePathExceptFirst(); + const fileValue = + pathExceptFirst + + "/" + + file.name; + store.setCurrentFile(fileValue); + store.setCopyFileName( + file.name, + ); + } + if (value === false) { + store.setCopyFileName(""); + store.setCurrentFile(""); + } + }} + bodyStyle={{ overflow: "hidden" }} + avatar={ +
+ + + + {file.name} + + +
+ } + className={styles.file_card} + style={{ + width: 100, + height: 100, + display: "flex", + alignItems: "center", + justifyContent: "center", + }} + /> +
+ + ); + } + })} + + @@ -502,7 +1041,7 @@ const File: FunctionComponent = () => { open={open} width={"50%"} onCancel={() => setOpen(false)}> - + ); diff --git a/src/components/Main/Home/index.tsx b/src/components/Main/Home/index.tsx index b1d1794..72421c4 100644 --- a/src/components/Main/Home/index.tsx +++ b/src/components/Main/Home/index.tsx @@ -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([]); const [monthDownload, setMonthDownload] = useState([]); const [recentUploadFile, setRecentUploadFile] = useState([]); - const [recentDownloadFile, setRecentDownloadFile] = useState([]); + // const [recentDownloadFile, setRecentDownloadFile] = useState([]); const [recentPreviewFile, setRecentPreviewFile] = useState([]); - // 获取存储同和存储商的个数 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 = () => { - - - { - navigate("/main/setting") - }} className={styles.home_content_icon}/> + + + { + navigate("/main/setting"); + }} + className={styles.home_content_icon} + /> @@ -395,11 +404,20 @@ const MainHome: React.FC = () => { - - - { - navigate("/main/bucket") - }} className={styles.home_content_icon}/> + + + { + navigate("/main/bucket"); + }} + className={styles.home_content_icon} + /> @@ -567,25 +585,27 @@ const MainHome: React.FC = () => { showMonthLabels={true} horizontal={true} showWeekdayLabels={false} - onClick={(value:any)=>{ - if(value!==null) { - message.open({ - - content: (<> - - - 日期:{value.date} - - - 数量:{value.count} - - - ), - type:"success", - duration: 2, - }).then(); + onClick={(value: any) => { + if (value !== null) { + message + .open({ + content: ( + <> + + + 日期:{value.date} + + + 数量:{value.count} + + + + ), + 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 (<> - - ) - }else { - return (<> - - ) + render: (_: any, record: any) => { + if (record.fileName) { + return ( + <> + + + ); + } else { + return ( + <> + + + ); } - - } + }, }, description: { dataIndex: "size", - valueType: "text" + valueType: "text", }, content: { - dataIndex: "time" - } + dataIndex: "time", + }, }} /> @@ -682,36 +709,43 @@ const MainHome: React.FC = () => { dataIndex: "fileName", }, avatar: { - render: (text: any,record: any) => { - if(record.fileName) { - return (<> - - ) - }else { - return (<> - - ) + render: (_: any, record: any) => { + if (record.fileName) { + return ( + <> + + + ); + } else { + return ( + <> + + + ); } - - } + }, }, description: { dataIndex: "size", valueType: "text", }, content: { - dataIndex: "time" - } + dataIndex: "time", + }, }} /> diff --git a/src/components/Main/Settings/components/AliSettings.tsx b/src/components/Main/Settings/components/AliSettings.tsx index 93cc816..8a43fa5 100644 --- a/src/components/Main/Settings/components/AliSettings.tsx +++ b/src/components/Main/Settings/components/AliSettings.tsx @@ -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[] = [ - { - 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) => [ - { - action?.startEditable?.(record.id); - }}> - 编辑 - , - - 查看 - , - 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(); const [open, setOpen] = useState(false); - const [configs, setConfigs] = useState([]); - + const [openModal, setOpenModal] = useState(false); + const [configs, setConfigs] = useState([]); + const [loading, setLoading] = useState(true); + const [configDetail, setConfigDetail] = useState({}); + const columns: ProColumns[] = [ + { + 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) => [ + { + action?.startEditable?.(record.id); + }}> + 编辑 + , + { + getConfigDetail(record.id).then(() => { + setOpenModal(true); + setLoading(false); + }); + }}> + 查看 + , + { + 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={ - }> -
+ { }; return ( <> -
- +
+ { + 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 = () => { ]} /> + 配置详情

} + loading={loading} + footer={false} + open={openModal} + afterClose={() => { + setConfigDetail({}); + }} + onCancel={() => setOpenModal(false)}> + +

ID:

{configDetail.id} +
+ +

endpoint:

{" "} + {configDetail.endpoint} +
+ +

accessKeyId:

{" "} + {configDetail.accessKeyId} +
+ +

accessKeySecret:

{" "} + {configDetail.accessKeySecret} +
+ +

status:

{" "} + {configDetail.status} +
+ +

createdTime:

{" "} + {configDetail.createdTime} +
+ +

updateTime:

{" "} + {configDetail.updateTime} +
+
); diff --git a/src/components/Main/Settings/components/MinioSettings.tsx b/src/components/Main/Settings/components/MinioSettings.tsx index 44ba67c..13e9b1a 100644 --- a/src/components/Main/Settings/components/MinioSettings.tsx +++ b/src/components/Main/Settings/components/MinioSettings.tsx @@ -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[] = [ - { - 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) => [ - { - action?.startEditable?.(record.id); - }}> - 编辑 - , - - 查看 - , - action?.reload()} - menus={[ - { key: "copy", name: "复制" }, - { key: "delete", name: "删除" }, - ]} - />, - ], - }, -]; - const MinioSettings: React.FC = () => { + const [form] = Form.useForm(); const actionRef = useRef(); const [open, setOpen] = useState(false); const [configs, setConfigs] = useState([]); + const [openModal, setOpenModal] = useState(false); + const [loading, setLoading] = useState(true); + const [configDetail, setConfigDetail] = useState({}); + const columns: ProColumns[] = [ + { + 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) => [ + { + action?.startEditable?.(record.id); + }}> + 编辑 + , + { + getConfigDetail(record.id).then(() => { + setOpenModal(true); + setLoading(false); + }); + }}> + 查看 + , + { + 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 = () => { <> { extra={ - }> - + { }; return ( <> -
+
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 = () => { ]} /> + 配置详情

} + loading={loading} + footer={false} + afterClose={() => { + setConfigDetail({}); + }} + open={openModal} + onCancel={() => setOpenModal(false)}> + +

ID:

{configDetail.id} +
+ +

endpoint:

{" "} + {configDetail.endpoint} +
+ +

accessKey:

{" "} + {configDetail.accessKey} +
+ +

secretKey:

{" "} + {configDetail.secretKey} +
+ +

status:

{" "} + {configDetail.status} +
+ +

createdTime:

{" "} + {configDetail.createdTime} +
+ +

updateTime:

{" "} + {configDetail.updateTime} +
+
); diff --git a/src/components/Main/Settings/components/QiniuSettings.tsx b/src/components/Main/Settings/components/QiniuSettings.tsx index 9d18b17..68ba251 100644 --- a/src/components/Main/Settings/components/QiniuSettings.tsx +++ b/src/components/Main/Settings/components/QiniuSettings.tsx @@ -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[] = [ - { - 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) => [ - { - action?.startEditable?.(record.id); - }}> - 编辑 - , - - 查看 - , - action?.reload()} - menus={[ - { key: "copy", name: "复制" }, - { key: "delete", name: "删除" }, - ]} - />, - ], - }, -]; - const QiniuSettings: React.FC = () => { + const [form] = Form.useForm(); const actionRef = useRef(); const [open, setOpen] = useState(false); const [config, setConfig] = useState([]); + const [openModal, setOpenModal] = useState(false); + const [loading, setLoading] = useState(true); + const [configDetail, setConfigDetail] = useState({}); + const columns: ProColumns[] = [ + { + 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) => [ + { + action?.startEditable?.(record.id); + }}> + 编辑 + , + { + getConfigDetail(record.id).then(() => { + setOpenModal(true); + setLoading(false); + }); + }}> + 查看 + , + { + 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 ( <> { extra={ - }> - + { + + + + + @@ -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 = () => { ]} /> + 配置详情

} + loading={loading} + afterClose={() => { + setConfigDetail({}); + }} + footer={false} + open={openModal} + onCancel={() => setOpenModal(false)}> + +

ID:

{configDetail.id} +
+ +

endpoint:

{" "} + {configDetail.endpoint} +
+ +

accessKey:

{" "} + {configDetail.accessKey} +
+ +

secretKey:

{" "} + {configDetail.secretKey} +
+ +

status:

{" "} + {configDetail.status} +
+ +

createdTime:

{" "} + {configDetail.createdTime} +
+ +

updateTime:

{" "} + {configDetail.updateTime} +
+
); diff --git a/src/components/Main/Settings/components/TencentSettings.tsx b/src/components/Main/Settings/components/TencentSettings.tsx index 3807ba7..2d9f118 100644 --- a/src/components/Main/Settings/components/TencentSettings.tsx +++ b/src/components/Main/Settings/components/TencentSettings.tsx @@ -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[] = [ - { - 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) => [ - { - action?.startEditable?.(record.id); - }}> - 编辑 - , - - 查看 - , - action?.reload()} - menus={[ - { key: "copy", name: "复制" }, - { key: "delete", name: "删除" }, - ]} - />, - ], - }, -]; - const TencentSettings: React.FC = () => { + const [form] = Form.useForm(); const actionRef = useRef(); const [open, setOpen] = useState(false); const [configs, setConfigs] = useState([]); + const [openModal, setOpenModal] = useState(false); + const [loading, setLoading] = useState(true); + const [configDetail, setConfigDetail] = useState({}); + const columns: ProColumns[] = [ + { + 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) => [ + { + action?.startEditable?.(record.id); + }}> + 编辑 + , + { + getConfigDetail(record.id).then(() => { + setOpenModal(true); + setLoading(false); + }); + }}> + 查看 + , + { + 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={ - }> - + { + + + + + + + + + + + + @@ -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 = () => { ]} /> + 配置详情

} + loading={loading} + footer={false} + open={openModal} + afterClose={() => { + setConfigDetail({}); + }} + onCancel={() => setOpenModal(false)}> + +

ID:

{configDetail.id} +
+ +

endpoint:

{" "} + {configDetail.endpoint} +
+ +

secretId:

{" "} + {configDetail.secretId} +
+ +

secretKey:

{" "} + {configDetail.secretKey} +
+ +

appId:

{" "} + {configDetail.appId} +
+ +

region:

{" "} + {configDetail.region} +
+ +

status:

{" "} + {configDetail.status} +
+ +

createdTime:

{" "} + {configDetail.createdTime} +
+ +

updateTime:

{" "} + {configDetail.updateTime} +
+
); diff --git a/src/components/Main/Settings/index.tsx b/src/components/Main/Settings/index.tsx index 2e75613..5d0e800 100644 --- a/src/components/Main/Settings/index.tsx +++ b/src/components/Main/Settings/index.tsx @@ -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 ( - + <> { flexDirection: "row", }} size={"small"}> - {" "} + - {storage.name} + {label.label} - + ); - })} - + }} + options={selectOptions} + optionRender={(item: any) => { + return ( + <> + + + + {item.label} + + + + ); + }} + placeholder={"请选择存储商"}> diff --git a/src/components/Main/Share/components/ShareAdd/ShareAdd.tsx b/src/components/Main/Share/components/ShareAdd/ShareAdd.tsx index 6f36243..fddd996 100644 --- a/src/components/Main/Share/components/ShareAdd/ShareAdd.tsx +++ b/src/components/Main/Share/components/ShareAdd/ShareAdd.tsx @@ -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={} onClick={() => { - navigate("/main/share/list/1"); + navigate("/main/share/list/" + store.getCircleId()); }} /> {
-
+ @@ -111,6 +144,7 @@ const ShareAdd: React.FunctionComponent = () => {

介绍

} + rules={[{ required: true, message: "请输入介绍" }]} name="content" id={"content"}>
{ 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"}> { }} /> }> - + - + @@ -269,4 +307,4 @@ const ShareAdd: React.FunctionComponent = () => { ); }; -export default ShareAdd; +export default observer(ShareAdd); diff --git a/src/components/Main/Share/components/ShareDetail/ShareDetail.tsx b/src/components/Main/Share/components/ShareDetail/ShareDetail.tsx index fc082b0..6304c28 100644 --- a/src/components/Main/Share/components/ShareDetail/ShareDetail.tsx +++ b/src/components/Main/Share/components/ShareDetail/ShareDetail.tsx @@ -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({}); + 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 ( <> -
+ - - - - - }, - { label: "最热", value: "Kanban", icon: }, - ]} - /> - - - - + + { + setCommentData(e.target.value); + }} + showCount + placeholder={"平等表达,友善交流"}> + + + - - - - landaiqing - - } - color={"cyan"} - style={{ marginLeft: 5 }}> - 作者 - - - } - style={{ width: "100%" }}> - - i回复OIDHJHDCEHIceh车hi是事实上事实是事实hi是是是是是是是是是是 - - - - 1 小时前 - - - - - 10 - - - - - - 10 - - - - - - - - {isReply && ( - <> - - - 回复: - - {" "} - landaiqing - - - - - - - - - + + + + + + + , + }, + { + label: "最热", + value: "Kanban", + icon: , + }, + ]} + /> + {comment.length === 0 ? ( + + ) : ( + <> + {comment && + Array.from(comment).map((item: any, index: number) => { + return ( + + + + + + - - - - - - - - - - - - )} - - - - - - - - sjm 回复 landaiqing - - {/*}*/} - {/* color={"cyan"}*/} - {/* style={{ marginLeft: 5 }}>*/} - {/* 作者*/} - {/**/} - - } - style={{ width: "100%" }}> - - i回复OIDHJHDCEHIceh车hi是事实上事实是事实hi是是是是是是是是是是 - - - - 1 小时前 - - - - - 10 - - - - - - 10 - - - - - - - - {isReplyComment && ( - <> - - - - {" "} - 回复:{" "} - - - {" "} - landaiqing - - - - - - - - - + + fontSize: 16, + fontWeight: 500, + }}> + {item.nick} + + } + color={"cyan"} + style={{ marginLeft: 5 }}> + 作者 + + + } + style={{ width: "100%" }}> + {item.content} - - + }}> + {item.createdTime} + + + + + {item.likes} + + + + { + setReply([]); + if (item.id) { + replyComment( + item.id, + ).then(() => { + handleExpandReplyCommentClick( + index, + ); + }); + } + }} + className={ + styles.comment_icon + } + /> + + {item.replyCount} + + + + + - - + + {isReply === index && ( + + + + 回复: + + + {item.nick} + + + + + + + + + { + setReplyData( + e.target + .value, + ); + }} + placeholder={ + "平等表达,友善交流" + }> + + + + + + + + + - + )} + {isReplyComment === index && + reply && + Array.from(reply).map( + ( + replyItem: any, + replyIndex: number, + ) => { + return ( + + + + + + + + { + replyItem.nick + }{" "} + 回复 + { + replyItem.nickto + } + + {/*}*/} + {/* color={"cyan"}*/} + {/* style={{ marginLeft: 5 }}>*/} + {/* 作者*/} + {/**/} + + + } + style={{ + width: "100%", + }}> + + { + replyItem.content + } + + + + { + replyItem.createdTime + } + + + + + { + replyItem.likes + } + + + + + + + + {isReplyReply === + replyItem.id && ( + <> + + + + 回复: + + + { + replyItem.nick + } + + + + + + + + + { + setReplyReplyData( + e + .target + .value, + ); + }} + maxLength={ + 500 + } + showCount + placeholder={ + "平等表达,友善交流" + }> + + + + + + + + + + + + )} + + + ); + }, + )} - - )} - - - - - - - - - - sjm 回复 landaiqing - - {/*}*/} - {/* color={"cyan"}*/} - {/* style={{ marginLeft: 5 }}>*/} - {/* 作者*/} - {/**/} - - } - style={{ width: "100%" }}> - - i回复OIDHJHDCEHIceh车hi是事实上事实是事实hi是是是是是是是是是是 - - - - 1 小时前 - - - - - 10 - - - - - - 10 - - - - - - - {isReplyComment && ( - <> - - - - {" "} - 回复:{" "} - - - {" "} - landaiqing - - - - - - - - - - - - - - - - - - - - - )} - - - - + ); + })} + + )} - +
diff --git a/src/components/Main/Share/components/ShareList/ShareList.tsx b/src/components/Main/Share/components/ShareList/ShareList.tsx index 12456aa..d3713d7 100644 --- a/src/components/Main/Share/components/ShareList/ShareList.tsx +++ b/src/components/Main/Share/components/ShareList/ShareList.tsx @@ -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([]); - 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 () => {
- } - endMessage={It is all, nothing more 🤐} - scrollableTarget="scrollableDiv"> + {

分享列表

} - renderItem={(item) => ( - + renderItem={(item: any) => ( + } + avatar={} title={ - <> - { - navigate("/main/share/detail/1"); - }}> - {item.name.last} - - - IDM - - + + + {item.title} + + {item.tags && + Array.from(item.tags).map( + (tag: any, index: number) => { + return ( + + + {tag.tagName} + + + ); + }, + )} + } description={ <> @@ -123,7 +124,7 @@ export default () => { vertical={false} justify={"space-between"} align={"center"}> - {item.email} + {item.description} { style={{ width: "300px" }}> { color: "gray", overflow: "hidden", }}> - landaiqing + {item.nickname} @@ -150,7 +151,7 @@ export default () => { fontSize: 12, color: "gray", }}> - 1024 + {item.likesCount} @@ -160,7 +161,7 @@ export default () => { fontSize: 12, color: "gray", }}> - 1024 + {item.commentCount} @@ -172,7 +173,7 @@ export default () => { fontSize: 12, color: "gray", }}> - 1024 + {item.views} @@ -180,13 +181,12 @@ export default () => { } /> - {/*
Content
*/}
)} /> -
+
); -}; +}); diff --git a/src/components/Main/Share/index.tsx b/src/components/Main/Share/index.tsx index 9993dc6..650661a 100644 --- a/src/components/Main/Share/index.tsx +++ b/src/components/Main/Share/index.tsx @@ -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([]); + 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 ( <>
@@ -30,77 +56,108 @@ const MainShare: FunctionComponent = () => {
文件分享圈} bordered={false} boxShadow={false}> - - { - navigate("/main/share/list/1"); - }} - cover={ - example - }> - - {/**/} - - - {" "} - - landaiqing - - - - - {" "} - - 1024 - - - - {" "} - - 999 - - - - - + + + {circleList && + circleList.map((item: any, index: number) => { + return ( +
+ { + navigate("/main/share/list/" + item.id); + }} + cover={ + example + }> + + + {item.description} + + + } + /> + + + {" "} + + {item.nickName} + + + + + {" "} + + {item.views} + + + + {" "} + + {item.count} + + + + + +
+ ); + })} +
@@ -114,15 +171,44 @@ const MainShare: FunctionComponent = () => { paddingBottom: 80, }, }} - extra={ - - - - - }> - + // extra={ + // + // + // + // + // } + > + { + 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(); + } + }); + }}> { rules={[{ required: true, message: "请输入描述!" }]}>