feat: 文件分享update

This commit is contained in:
landaiqing
2024-07-11 14:56:57 +08:00
parent 32dff4adbb
commit b7a16c3c59
13 changed files with 972 additions and 456 deletions

View File

@@ -1,9 +1,10 @@
.settings_container{ .settings_container{
height: 75vh; width: 100%;
} height: 100%;
.settings_header{ }
display: flex; .settings_header{
flex-direction: row; display: flex;
justify-content: space-between; flex-direction: row;
} justify-content: space-between;
}

View File

@@ -55,7 +55,7 @@ export default () => {
</Select> </Select>
</div> </div>
</ProCard> </ProCard>
<ProCard style={{ marginTop: 20, height: "60vh" }} bordered boxShadow> <ProCard style={{ marginTop: 20, height: "100%" }} bordered boxShadow>
{location.pathname === "/main/setting" || location.pathname === "/main/setting/" ? ( {location.pathname === "/main/setting" || location.pathname === "/main/setting/" ? (
<> <>
<Empty description={"请选择存储商"} /> <Empty description={"请选择存储商"} />

View File

@@ -0,0 +1,225 @@
/** @format */
import React, { useEffect, useRef } from "react";
import { AiEditor } from "aieditor";
import "aieditor/dist/style.css";
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, Form, FormListFieldData, FormProps, Input, Select } from "antd";
import { CloseOutlined, LeftOutlined, MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
import selectOptions from "@/components/Main/Settings/settings.ts";
const ShareAdd: React.FunctionComponent = () => {
const navigate = useNavigate();
const divRef = useRef(null);
const fromRef: any = useRef();
const [isDisabled, setIsDisabled] = React.useState(false);
const onFinish: FormProps["onFinish"] = (values) => {
console.log("Success:", values);
};
useEffect(() => {
if (divRef.current) {
const aiEditor = new AiEditor({
element: divRef.current,
placeholder: "点击输入描述...",
contentRetention: true,
textSelectionBubbleMenu: {
enable: true,
items: ["ai", "Bold", "Italic", "Underline", "Strike", "code", "comment"],
},
onChange: async (value) => {
fromRef.current.setFieldsValue({
content: value.getHtml(),
});
},
});
return () => {
aiEditor.destroy();
};
}
}, []);
return (
<>
<div className={styles.share_add_main}>
<ProCard bordered={true}>
<Button
shape="circle"
icon={<LeftOutlined />}
onClick={() => {
navigate("/main/share/list/1");
}}
/>
</ProCard>
<div className={styles.share_add_content}>
<Form onFinish={onFinish} autoComplete="off" ref={fromRef}>
<Form.Item
label={"标题"}
name="title"
id={"title"}
rules={[{ required: true, message: "请输入标题" }]}>
<Input name="title" maxLength={50} showCount></Input>
</Form.Item>
<Form.Item
label={"图标"}
id={"icon"}
name="icon"
rules={[{ required: true, message: "请输入图标" }]}>
<Input name="icon"></Input>
</Form.Item>
<Form.Item
label={"摘要"}
id={"description"}
name="description"
rules={[{ required: true, message: "请输入摘要" }]}>
<Input name="description" maxLength={100} showCount></Input>
</Form.Item>
<Form.Item label={"介绍"} name={"content"} id={"content"}>
<div
ref={divRef}
style={{ height: "300px", maxWidth: "100%", minWidth: "100%" }}
/>
</Form.Item>
<Form.List
name="tags"
rules={[
{
validator: async (_, tags) => {
if (!tags) {
return Promise.reject(new Error("请至少填写一个标签"));
}
if (tags.length >= 3) {
setIsDisabled(true);
return Promise.reject(
new Error("最多只能添加五个标签"),
);
}
},
},
]}>
{(fields: FormListFieldData[], { add, remove }, { errors }) => (
<>
{fields.map((field: FormListFieldData, index: number) => (
<Form.Item
label={"标签" + (index + 1)}
key={index}
id={"tags"}>
<Form.Item
validateTrigger={["onChange", "onBlur"]}
name={[field.name, "tag"]}
noStyle>
<Input
placeholder="请输入标签"
maxLength={10}
showCount
style={{ width: "20%" }}
/>
</Form.Item>
{fields.length > 0 ? (
<MinusCircleOutlined
className="dynamic-delete-button"
onClick={() => {
setIsDisabled(false);
remove(field.name);
}}
/>
) : null}
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
disabled={isDisabled}
onClick={() => add()}
style={{ width: "100%" }}
icon={<PlusOutlined />}>
</Button>
<Form.ErrorList errors={errors} />
</Form.Item>
</>
)}
</Form.List>
<Form.List name="urls">
{(fields: FormListFieldData[], { add, remove }) => (
<div
style={{
display: "flex",
rowGap: 16,
flexDirection: "column",
}}>
{fields.map((field: FormListFieldData, index: number) => (
<Card
size="small"
title={`链接 ${index + 1}`}
key={index}
extra={
<CloseOutlined
onClick={() => {
remove(field.name);
}}
/>
}>
<Form.Item name={[field.name, "type"]} label="分享类型">
<Select
size="middle"
style={{ width: "20%" }}
showSearch={true}
allowClear={true}
notFoundContent={"未找到哦"}
placeholder={"请选择分享类型"}>
{selectOptions.map(
(storage: any, index: any) => {
return (
<Select.Option
value={storage.value}
key={index}>
{storage.name}
</Select.Option>
);
},
)}
</Select>
</Form.Item>
<Form.Item
name={[field.name, "description"]}
label="资源描述">
<Input name={"description"} />
</Form.Item>
<Form.Item name={[field.name, "url"]} label="资源链接">
<Input name={"url"} />
</Form.Item>
<Form.Item
name={[field.name, "password"]}
label={"提取密码"}>
<Input name={"password"} />
</Form.Item>
</Card>
))}
<Button type="dashed" onClick={() => add()} block>
+
</Button>
</div>
)}
</Form.List>
<Form.Item
style={{
display: "flex",
flexDirection: "row",
justifyContent: "flex-end",
marginTop: "2%",
}}>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Form>
</div>
</div>
</>
);
};
export default ShareAdd;

View File

@@ -0,0 +1,7 @@
.share_add_main{
display: flex;
flex-direction: column;
.share_add_content{
margin-top: 2%;
}
}

View File

@@ -1,43 +1,130 @@
/** @format */ /** @format */
import React, { useEffect, useRef } from "react"; import React from "react";
import { Button } from "antd"; import { Avatar, Button, Card, Divider, Flex, Tooltip } from "antd";
import { LeftOutlined } from "@ant-design/icons"; import {
ExportOutlined,
InfoCircleOutlined,
LeftOutlined,
WarningOutlined,
} from "@ant-design/icons";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import {AiEditor} from "aieditor"; import "aieditor/dist/style.css";
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";
const { Paragraph } = Typography;
const ShareDetail: React.FunctionComponent = () => { const ShareDetail: React.FunctionComponent = () => {
const navigate = useNavigate(); const navigate = useNavigate();
//定义 ref
const divRef = useRef(null);
//初始化 AiEditor
useEffect(() => {
if (divRef.current) {
const aiEditor = new AiEditor({
editable:false,
element: divRef.current,
placeholder: "点击输入内容...",
content: 'AiEditor 是一个面向 AI 的开源富文本编辑器。 ',
})
return ()=>{
aiEditor.destroy();
}
}
}, [])
return ( return (
<> <>
<Button
shape="circle"
icon={<LeftOutlined />}
onClick={() => {
navigate("/main/share/list/1");
}}
/>
<div> <div>
<div ref={divRef} style={{ height: 550}}> <ProCard bordered={true}>
</div> <Button
<div> shape="circle"
555 icon={<LeftOutlined />}
onClick={() => {
navigate("/main/share/list/1");
}}
/>
</ProCard>
<div className={styles.share_detail_container}>
<ProCard bordered={true}>
<div style={{ height: 500 }}>
</div>
<Card style={{ borderRadius: "10px", borderColor: "#1677FF" }}>
<Flex vertical={false} align={"center"} justify={"space-between"}>
<span
style={{
fontSize: 18,
color: "#1677FF",
fontWeight: "bolder",
}}>
</span>
<Button icon={<WarningOutlined />} type={"primary"}>
</Button>
</Flex>
<Flex
vertical={false}
align={"center"}
style={{ marginTop: 10 }}
justify={"space-between"}>
<span style={{ fontSize: 16 }}>Windows DefenderRemover</span>
</Flex>
<Flex
vertical={false}
align={"center"}
style={{ marginTop: 10 }}
justify={"space-between"}>
<span
style={{
fontSize: 18,
color: "#1677FF",
fontWeight: "bolder",
}}>
</span>
</Flex>
<Flex
vertical={false}
align={"center"}
style={{ marginTop: 10 }}
justify={"space-between"}>
<Card hoverable={true} style={{ width: 280, height: 140 }}>
<Flex vertical={true}>
<Flex
vertical={false}
justify={"space-between"}
align={"center"}>
<div>
<Avatar src={logo}></Avatar>
<span
style={{
marginLeft: 10,
color: "#1677FF",
fontSize: 16,
}}>
</span>
</div>
<ExportOutlined className={styles.link_btn} />
</Flex>
<Divider></Divider>
<Flex vertical={false}>
<Tooltip
title="DefenderRemove111111111"
placement={"bottom"}>
<span style={{ width: 150, overflowX: "hidden" }}>
DefenderRemove111111111
</span>
</Tooltip>
<span
style={{
width: 130,
marginLeft: 10,
display: "flex",
flexDirection: "row",
}}>
<span style={{ color: "#1677FF" }}></span>{" "}
<Paragraph copyable>12345</Paragraph>
</span>
</Flex>
</Flex>
</Card>
</Flex>
<Flex vertical={false} style={{ marginTop: 10 }}>
<span style={{ color: "grey" }}>
<InfoCircleOutlined />
使24
</span>
</Flex>
</Card>
</ProCard>
</div> </div>
</div> </div>
</> </>

View File

@@ -0,0 +1,10 @@
.share_detail_container{
margin-top: 10px;
}
.link_btn{
font-size: 20px;
color: grey;
}
.link_btn:hover{
color: #1890ff;
}

View File

@@ -1,13 +1,14 @@
/** @format */ /** @format */
import { ProCard } from "@ant-design/pro-components"; import { ProCard } from "@ant-design/pro-components";
import { Avatar, Button, Divider, List, Skeleton } from "antd"; import { Avatar, Button, Divider, Flex, List, Skeleton, Tag } from "antd";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import styles from "./index.module.less"; import styles from "./index.module.less";
import Search from "antd/es/input/Search"; import Search from "antd/es/input/Search";
import InfiniteScroll from "react-infinite-scroll-component"; import InfiniteScroll from "react-infinite-scroll-component";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { LeftOutlined } from "@ant-design/icons"; import { CommentOutlined, EyeOutlined, HeartOutlined, LeftOutlined } from "@ant-design/icons";
import logo from "@/assets/icons/aliyun.svg";
interface DataType { interface DataType {
gender: string; gender: string;
name: { name: {
@@ -23,11 +24,11 @@ interface DataType {
}; };
nat: string; nat: string;
} }
export default () => { export default () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [data, setData] = useState<DataType[]>([]); const [data, setData] = useState<DataType[]>([]);
const loadMoreData = () => { const loadMoreData = () => {
if (loading) { if (loading) {
return; return;
@@ -63,7 +64,12 @@ export default () => {
<Search placeholder="搜索" style={{ width: 500, marginLeft: 20 }} /> <Search placeholder="搜索" style={{ width: 500, marginLeft: 20 }} />
</div> </div>
<Button></Button> <Button
onClick={() => {
navigate("/main/share/add");
}}>
</Button>
</div> </div>
</ProCard> </ProCard>
<ProCard bordered={true} boxShadow={true} style={{ marginTop: 20 }}> <ProCard bordered={true} boxShadow={true} style={{ marginTop: 20 }}>
@@ -81,16 +87,62 @@ export default () => {
<List.Item.Meta <List.Item.Meta
avatar={<Avatar src={item.picture.large} />} avatar={<Avatar src={item.picture.large} />}
title={ title={
<a <>
onClick={() => { <a
navigate("/main/share/detail/1"); onClick={() => {
}}> navigate("/main/share/detail/1");
{item.name.last} }}>
</a> {item.name.last}
</a>
<Tag
bordered={false}
color="processing"
style={{ marginLeft: 10 }}>
IDM
</Tag>
</>
}
description={
<>
<Flex
vertical={false}
justify={"space-between"}
align={"center"}>
{item.email}
<Flex
vertical={false}
align={"center"}
justify={"space-between"}
style={{ width: "250px" }}>
<Avatar src={logo} size={"small"} />
<span
style={{
fontSize: 12,
color: "gray",
}}>
landaiqing
</span>
<HeartOutlined />
<span
style={{ fontSize: 12, color: "gray" }}>
1024
</span>
<CommentOutlined />
<span
style={{ fontSize: 12, color: "gray" }}>
1024
</span>
<EyeOutlined style={{ color: "gray" }} />{" "}
<span
style={{ fontSize: 12, color: "gray" }}>
1024
</span>
</Flex>
</Flex>
</>
} }
description={item.email}
/> />
<div>Content</div> {/*<div>Content</div>*/}
</List.Item> </List.Item>
)} )}
/> />

View File

@@ -1,45 +1,154 @@
/** @format */ /** @format */
import { FunctionComponent } from "react"; import { FunctionComponent, useState } from "react";
import { ProCard } from "@ant-design/pro-components"; import { ProCard } from "@ant-design/pro-components";
import styles from "./index.module.less"; import styles from "./index.module.less";
import { Button, Card, Image } from "antd"; import { Avatar, Button, Card, Drawer, Flex, Form, Image, Input, Space } from "antd";
import Search from "antd/es/input/Search"; import Search from "antd/es/input/Search";
import Meta from "antd/es/card/Meta"; import Meta from "antd/es/card/Meta";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import background from "@/assets/images/background.png"; import background from "@/assets/images/background.png";
import TextArea from "antd/es/input/TextArea";
import { EyeOutlined, UnorderedListOutlined } from "@ant-design/icons";
const MainShare: FunctionComponent = () => { const MainShare: FunctionComponent = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
return ( return (
<> <>
<div className={styles.share_main}> <div className={styles.share_main}>
<ProCard bordered={true} boxShadow={false}> <ProCard bordered={true} boxShadow={true}>
<div className={styles.share_header}> <div className={styles.share_header}>
<Search placeholder="搜索圈子" style={{ width: 500 }} /> <Search placeholder="搜索圈子" style={{ width: 500 }} />
<Button></Button> <Button onClick={showDrawer}></Button>
</div> </div>
</ProCard> </ProCard>
<ProCard bordered={true} boxShadow={false} style={{ marginTop: 20 }}> <ProCard bordered={true} boxShadow={true} style={{ marginTop: 20 }}>
<Card <Flex vertical={false} align={"center"}>
hoverable <Card
style={{ width: 240 }} hoverable
onClick={() => { style={{ width: "250px" }}
navigate("/main/share/list/1"); onClick={() => {
}} navigate("/main/share/list/1");
cover={ }}
<Image cover={
alt="example" <Image
src={background} alt="example"
style={{ height: 200 }} src={background}
preview={false} style={{ height: 200 }}
width={"100%"} preview={false}
fallback="data:image/png;base64,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" width={"100%"}
/> fallback="data:image/png;base64,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"
}> />
<Meta title="Europe Street beat" description="www.instagram.com" /> }>
</Card> <Meta title="工具软件分享" description="分享一些常用的办公软件" />
<Flex
vertical={false}
style={{ marginTop: 10 }}
align={"center"}
justify={"space-between"}>
<Avatar src={background} size={"small"} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>landaiqing</span>
<Flex
vertical={false}
align={"center"}
style={{ width: 100 }}
justify={"space-between"}>
<EyeOutlined style={{ color: "gray" }} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>1024</span>
<UnorderedListOutlined style={{ color: "gray" }} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>999</span>
</Flex>
</Flex>
</Card>
<Card
hoverable
style={{ width: "250px", marginLeft: 20 }}
onClick={() => {
navigate("/main/share/list/1");
}}
cover={
<Image
alt="example"
src={background}
style={{ height: 200 }}
preview={false}
width={"100%"}
fallback="data:image/png;base64,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"
/>
}>
<Meta title="工具软件分享" description="分享一些常用的办公软件" />
<Flex
vertical={false}
style={{ marginTop: 10 }}
align={"center"}
justify={"space-between"}>
<Avatar src={background} size={"small"} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>landaiqing</span>
<Flex
vertical={false}
align={"center"}
style={{ width: 100 }}
justify={"space-between"}>
<EyeOutlined style={{ color: "gray" }} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>1024</span>
<UnorderedListOutlined style={{ color: "gray" }} />{" "}
<span style={{ fontSize: 12, color: "gray" }}>999</span>
</Flex>
</Flex>
</Card>
</Flex>
</ProCard> </ProCard>
</div> </div>
<Drawer
title="创建圈子"
width={"40%"}
onClose={onClose}
open={open}
styles={{
body: {
paddingBottom: 80,
},
}}
extra={
<Space>
<Button onClick={onClose}></Button>
<Button onClick={onClose} type="primary">
</Button>
</Space>
}>
<Form layout="vertical">
<Form.Item
name="name"
label="名称"
rules={[{ required: true, message: "请输入圈子名称!" }]}>
<Input maxLength={30} showCount placeholder="请输入圈子名称!" />
</Form.Item>
<Form.Item
name="icon"
label="图标"
rules={[{ required: true, message: "请输入图标!" }]}>
<Input placeholder="请输入图标!" />
</Form.Item>
<Form.Item
name="description"
label="描述"
rules={[{ required: true, message: "请输入描述!" }]}>
<TextArea rows={4} maxLength={50} showCount placeholder="请输入描述!" />
</Form.Item>
</Form>
</Drawer>
</> </>
); );
}; };

View File

@@ -1,253 +1,257 @@
/** @format */ /** @format */
import { FunctionComponent, useEffect, useState } from "react"; import { FunctionComponent, useEffect, useState } from "react";
import { ProCard, ProForm, ProFormCascader } from "@ant-design/pro-components"; import { ProCard, ProForm, ProFormCascader } from "@ant-design/pro-components";
import { AntDesignOutlined } from "@ant-design/icons"; import { AntDesignOutlined } from "@ant-design/icons";
import { import {
Avatar, Avatar,
Button, Button,
Descriptions, Descriptions,
DescriptionsProps, DescriptionsProps,
Form, Flex,
FormProps, Form,
Input, FormProps,
Select, Input,
Skeleton, Select,
Space, Skeleton,
Tabs, Space,
} from "antd"; Tabs,
import styles from "./index.module.less"; } from "antd";
import TextArea from "antd/es/input/TextArea"; import styles from "./index.module.less";
import { city } from "@/context/five-level-address.ts"; import TextArea from "antd/es/input/TextArea";
import { city } from "@/context/five-level-address.ts";
const UserSetting: FunctionComponent = () => {
const [disable, setDisable] = useState(true); const UserSetting: FunctionComponent = () => {
const [loading, setLoading] = useState(true); const [disable, setDisable] = useState(true);
const items: DescriptionsProps["items"] = [ const [loading, setLoading] = useState(true);
{ const items: DescriptionsProps["items"] = [
key: "1", {
label: "用户名", key: "1",
children: "Zhou Maomao", label: "用户名",
}, children: "Zhou Maomao",
{ },
key: "2", {
label: "账号ID", key: "2",
children: "1810000000", label: "账号ID",
}, children: "1810000000",
{ },
key: "3", {
label: "注册时间", key: "3",
children: "Hangzhou, Zhejiang", label: "注册时间",
}, children: "Hangzhou, Zhejiang",
{ },
key: "4", {
label: "邮箱", key: "4",
children: "landaiqing@126.com", label: "邮箱",
}, children: "landaiqing@126.com",
{ },
key: "5", {
label: "手机号", key: "5",
children: "13333333333333", label: "手机号",
}, children: "13333333333333",
]; },
type FieldType = { ];
email?: string; type FieldType = {
nickname?: string; email?: string;
location?: string; nickname?: string;
introduce?: string; location?: string;
gender?: string; introduce?: string;
company?: string; gender?: string;
blog?: string; company?: string;
}; blog?: string;
const onFinish: FormProps<FieldType>["onFinish"] = (values) => { };
console.log("Success:", values); const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
}; console.log("Success:", values);
};
const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (errorInfo) => {
console.log("Failed:", errorInfo); const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (errorInfo) => {
}; console.log("Failed:", errorInfo);
};
const prefixSelector = (
<Form.Item name="prefix" noStyle> const prefixSelector = (
<Select style={{ width: 90 }}> <Form.Item name="prefix" noStyle>
<Select.Option value="https://">https://</Select.Option> <Select style={{ width: 90 }}>
<Select.Option value="http://">http://</Select.Option> <Select.Option value="https://">https://</Select.Option>
</Select> <Select.Option value="http://">http://</Select.Option>
</Form.Item> </Select>
); </Form.Item>
const ProFormText = (props: any) => { );
return ( const ProFormText = (props: any) => {
<ProForm.Item {...props} style={{ height: "10px" }}> return (
<ProFormCascader <ProForm.Item {...props} style={{ height: "10px" }}>
request={async () => city} <ProFormCascader
width="md" request={async () => city}
name="location" width="md"
disabled={disable}></ProFormCascader> name="location"
</ProForm.Item> disabled={disable}></ProFormCascader>
); </ProForm.Item>
}; );
useEffect(() => { };
setTimeout(() => { useEffect(() => {
setLoading(false); setTimeout(() => {
}, 2000); setLoading(false);
}, []); }, 2000);
const TabItems = [ }, []);
{ const TabItems = [
label: <span></span>, {
key: "baseInfo", label: <span></span>,
children: ( key: "baseInfo",
<> children: (
<Skeleton loading={loading} active> <>
<div> <Skeleton loading={loading} active>
<Form <div>
name="basic" <Form
labelCol={{ span: 3 }} name="basic"
wrapperCol={{ span: 16 }} labelCol={{ span: 3 }}
style={{ maxWidth: 600 }} wrapperCol={{ span: 16 }}
onFinish={onFinish} style={{ maxWidth: 600 }}
onFinishFailed={onFinishFailed} onFinish={onFinish}
initialValues={{ prefix: "https://" }} onFinishFailed={onFinishFailed}
autoComplete="off"> initialValues={{ prefix: "https://" }}
<Form.Item<FieldType> autoComplete="off">
label="邮箱" <Form.Item<FieldType>
name="email" label="邮箱"
rules={[ name="email"
{ rules={[
type: "email", {
message: "请输入正确的邮箱!", type: "email",
}, message: "请输入正确的邮箱!",
{ required: true, message: "请输入邮箱!" }, },
]}> { required: true, message: "请输入邮箱!" },
<Input allowClear disabled={disable} /> ]}>
</Form.Item> <Input allowClear disabled={disable} />
<Form.Item<FieldType> </Form.Item>
label="昵称" <Form.Item<FieldType>
name="nickname" label="昵称"
rules={[ name="nickname"
{ rules={[
type: "string", {
message: type: "string",
"用户名只能是3到16位字母数字下划线减号", message:
pattern: /^[a-zA-Z0-9_-]{3,16}$/, "用户名只能是3到16位字母数字下划线减号",
}, pattern: /^[a-zA-Z0-9_-]{3,16}$/,
{ },
required: true, {
message: "请输入昵称!", required: true,
}, message: "请输入昵称!",
]}> },
<Input allowClear disabled={disable} /> ]}>
</Form.Item> <Input allowClear disabled={disable} />
<Form.Item<FieldType> </Form.Item>
label="性别" <Form.Item<FieldType>
name="gender" label="性别"
rules={[{ required: true, message: "请输入性别!" }]}> name="gender"
<Select disabled={disable}> rules={[{ required: true, message: "请输入性别!" }]}>
<Select.Option value="男"></Select.Option> <Select disabled={disable}>
<Select.Option value=""></Select.Option> <Select.Option value=""></Select.Option>
<Select.Option value="UNKNOWN"></Select.Option> <Select.Option value=""></Select.Option>
</Select> <Select.Option value="UNKNOWN"></Select.Option>
</Form.Item> </Select>
<Form.Item<FieldType> </Form.Item>
label="地区" <Form.Item<FieldType>
name="location" label="地区"
rules={[{ required: true, message: "请输入地区!" }]}> name="location"
<ProFormText /> rules={[{ required: true, message: "请输入地区!" }]}>
</Form.Item> <ProFormText />
<Form.Item<FieldType> label="公司" name="company"> </Form.Item>
<Input allowClear disabled={disable} /> <Form.Item<FieldType> label="公司" name="company">
</Form.Item> <Input allowClear disabled={disable} />
<Form.Item<FieldType> label="博客" name="blog"> </Form.Item>
<Input <Form.Item<FieldType> label="博客" name="blog">
addonBefore={prefixSelector} <Input
allowClear addonBefore={prefixSelector}
disabled={disable} allowClear
/> disabled={disable}
</Form.Item> />
<Form.Item<FieldType> label="个人简介" name="introduce"> </Form.Item>
<TextArea <Form.Item<FieldType> label="个人简介" name="introduce">
rows={4} <TextArea
allowClear rows={4}
maxLength={200} allowClear
showCount maxLength={200}
placeholder="请输入您的个人简介最多不超过200字。" showCount
disabled={disable} placeholder="请输入您的个人简介最多不超过200字。"
/> disabled={disable}
</Form.Item> />
<Form.Item wrapperCol={{ offset: 3, span: 16 }}> </Form.Item>
<Space <Form.Item wrapperCol={{ offset: 3, span: 16 }}>
style={{ <Space
display: "flex", style={{
flexDirection: "row", display: "flex",
justifyContent: "space-between", flexDirection: "row",
width: "400px", justifyContent: "space-between",
}}> width: "400px",
<Button }}>
htmlType="button" <Button
onClick={() => { htmlType="button"
setDisable(!disable); onClick={() => {
}}> setDisable(!disable);
}}>
</Button>
<Button type="primary" htmlType="submit" disabled={disable}> </Button>
<Button type="primary" htmlType="submit" disabled={disable}>
</Button>
</Space> </Button>
</Form.Item> </Space>
</Form> </Form.Item>
</div> </Form>
</Skeleton> </div>
</> </Skeleton>
), </>
}, ),
{ },
label: <span></span>, {
key: "security", label: <span></span>,
children: ( key: "security",
<> children: (
<Skeleton loading={loading} active> <>
<Space direction={"vertical"} style={{ width: "100%" }}> <Skeleton loading={loading} active>
<ProCard hoverable bordered> <Space direction={"vertical"} style={{ width: "100%" }}>
<ProCard hoverable bordered>
</ProCard> <Flex vertical={false} align={"center"} justify={"space-between"}>
<ProCard hoverable bordered> <span style={{ width: 80 }}></span>
<Input variant="borderless" value={"******************"} />
</ProCard> </Flex>
<ProCard hoverable bordered> </ProCard>
<ProCard hoverable bordered>
</ProCard> 1333333333333333
</Space> </ProCard>
</Skeleton> <ProCard hoverable bordered>
</> landaiqing@126.com
), </ProCard>
}, </Space>
]; </Skeleton>
</>
return ( ),
<> },
<div className={styles.user_setting_main}> ];
<ProCard boxShadow>
<Skeleton loading={loading} active avatar> return (
<div className={styles.user_setting_header}> <>
<Avatar <div className={styles.user_setting_main}>
size={{ xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 }} <ProCard boxShadow>
icon={<AntDesignOutlined />} <Skeleton loading={loading} active avatar>
/> <div className={styles.user_setting_header}>
<Avatar
<Descriptions size={{ xs: 24, sm: 32, md: 40, lg: 64, xl: 80, xxl: 100 }}
style={{ width: "80%", marginLeft: "50px" }} icon={<AntDesignOutlined />}
items={items} />
column={3}
size={"small"}></Descriptions> <Descriptions
</div> style={{ width: "80%", marginLeft: "50px" }}
</Skeleton> items={items}
</ProCard> column={3}
size={"small"}></Descriptions>
<div className={styles.user_setting_content}> </div>
<ProCard boxShadow> </Skeleton>
<Tabs type="card" items={TabItems}></Tabs> </ProCard>
</ProCard>
</div> <div className={styles.user_setting_content}>
</div> <ProCard boxShadow>
</> <Tabs type="card" items={TabItems}></Tabs>
); </ProCard>
}; </div>
export default UserSetting; </div>
</>
);
};
export default UserSetting;

View File

@@ -0,0 +1,11 @@
/** @format */
import { lazy } from "react";
const ShareAdd = lazy(
() =>
new Promise((resolve: any) => {
resolve(import("@/components/Main/Share/components/ShareAdd/ShareAdd.tsx"));
}),
);
export default ShareAdd;

View File

@@ -46,6 +46,7 @@ import qiniuBucket from "@/router/modules/main/bucket/createBuckets/qiniu.ts";
import ucloudBucket from "@/router/modules/main/bucket/createBuckets/ucloud.ts"; import ucloudBucket from "@/router/modules/main/bucket/createBuckets/ucloud.ts";
import upBucket from "@/router/modules/main/bucket/createBuckets/up.ts"; import upBucket from "@/router/modules/main/bucket/createBuckets/up.ts";
import wangyiBucket from "@/router/modules/main/bucket/createBuckets/wangyi.ts"; import wangyiBucket from "@/router/modules/main/bucket/createBuckets/wangyi.ts";
import ShareAdd from "@/router/modules/main/share/modules/shareAdd.tsx";
const routes: RouteObject[] = [ const routes: RouteObject[] = [
{ {
@@ -163,6 +164,10 @@ const routes: RouteObject[] = [
path: "/main/share/detail/:id", path: "/main/share/detail/:id",
Component: ShareDetail, Component: ShareDetail,
}, },
{
path: "/main/share/add",
Component: ShareAdd,
},
{ {
path: "/main/setting", path: "/main/setting",
Component: MainSetting, Component: MainSetting,

View File

@@ -32,14 +32,14 @@ export default function AuthRoute(props: { children: React.ReactNode }) {
return <Navigate to="/404" />; return <Navigate to="/404" />;
} }
// if (!isLogin) { if (!isLogin) {
// message message
// .open({ .open({
// content: "请先登录!", content: "请先登录!",
// type: "warning", type: "warning",
// }) })
// .then(); .then();
// return <Navigate to="/login" />; return <Navigate to="/login" />;
// } }
return props.children; return props.children;
} }

View File

@@ -1,117 +1,122 @@
/** @format */ /** @format */
import { import {
GithubFilled, GithubFilled,
InfoCircleFilled, InfoCircleFilled,
LogoutOutlined, LogoutOutlined,
QuestionCircleFilled, QuestionCircleFilled,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { DefaultFooter, PageContainer, ProCard, ProLayout } from "@ant-design/pro-components"; import {
import settings from "./settings.tsx"; DefaultFooter,
import { Link, Outlet, useLocation } from "react-router-dom"; PageContainer,
import logo from "@/assets/images/logo.png"; ProCard,
import { Suspense } from "react"; ProLayout,
import { Dropdown } from "antd"; } from "@ant-design/pro-components";
// import { getUserMenuPermission } from "@/api/user"; import { Link, Outlet, useLocation } from "react-router-dom";
import logo from "@/assets/images/logo.png";
export default function Layout() { import { Suspense } from "react";
const location = useLocation(); import { Dropdown } from "antd";
return ( import settings from "@/views/Main/settings.tsx";
<div // import { getUserMenuPermission } from "@/api/user";
id="test-pro-layout"
style={{ export default function Layout() {
height: "100vh", const location = useLocation();
}}> return (
<ProLayout <div
logo={logo} id="pro-layout"
layout={"mix"} style={{
pure={false} height: "100vh",
loading={false} }}>
contentWidth={"Fluid"} <ProLayout
title={"五味子云存储"} logo={logo}
siderWidth={216} layout={"mix"}
menuItemRender={(menuItemProps, defaultDom) => { pure={false}
if (menuItemProps.isUrl || !menuItemProps.path) { loading={false}
return defaultDom; contentWidth={"Fluid"}
} title={"五味子云存储"}
return <Link to={menuItemProps.path}>{defaultDom}</Link>; siderWidth={216}
}} menuItemRender={(menuItemProps, defaultDom) => {
{...settings} if (menuItemProps.isUrl || !menuItemProps.path) {
menu={{ return defaultDom;
// request: async () => { }
// const res: any = await getUserMenuPermission("17"); return <Link to={menuItemProps.path}>{defaultDom}</Link>;
// return res.data.routes; }}
// }, {...settings}
type: "group", menu={{
defaultOpenAll: false, // request: async () => {
hideMenuWhenCollapsed: false, // const res: any = await getUserMenuPermission("17");
collapsedShowTitle: false, // return res.data.routes;
}} // },
disableMobile={false} type: "group",
location={{ defaultOpenAll: false,
pathname: location.pathname, hideMenuWhenCollapsed: false,
}} collapsedShowTitle: false,
avatarProps={{ }}
src: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg", disableMobile={false}
title: "七妮妮", location={{
size: "large", pathname: location.pathname,
// eslint-disable-next-line @typescript-eslint/ban-ts-comment }}
// @ts-expect-error avatarProps={{
render: (props, dom) => { src: "https://gw.alipayobjects.com/zos/antfincdn/efFD%24IOql2/weixintupian_20170331104822.jpg",
return ( title: "七妮妮",
<Dropdown size: "large",
menu={{ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
items: [ // @ts-expect-error
{ render: (props, dom) => {
key: "logout", return (
icon: <LogoutOutlined />, <Dropdown
label: "退出登录", menu={{
}, items: [
], {
}}> key: "logout",
{dom} icon: <LogoutOutlined />,
</Dropdown> label: "退出登录",
); },
}, ],
}} }}>
actionsRender={(props: any) => { {dom}
// eslint-disable-next-line react/prop-types </Dropdown>
if (props.isMobile) return []; );
return [ },
<InfoCircleFilled key="InfoCircleFilled" />, }}
<QuestionCircleFilled key="QuestionCircleFilled" />, actionsRender={(props: any) => {
<GithubFilled key="GithubFilled" />, // eslint-disable-next-line react/prop-types
]; if (props.isMobile) return [];
}} return [
breadcrumbRender={(routers = []) => [ <InfoCircleFilled key="InfoCircleFilled" />,
{ <QuestionCircleFilled key="QuestionCircleFilled" />,
path: "/main/home", <GithubFilled key="GithubFilled" />,
title: "主页", ];
}, }}
...routers, breadcrumbRender={(routers = []) => [
]} {
footerRender={() => ( path: "/main/home",
<DefaultFooter title: "主页",
links={[ },
{ ...routers,
key: "schisandra", ]}
title: "schisandra", footerRender={() => (
href: "https://landaiqing.cn", <DefaultFooter
}, links={[
]} {
copyright="2024" key: "schisandra",
/> title: "schisandra",
)}> href: "https://landaiqing.cn",
<PageContainer title={false}> },
<ProCard> ]}
<div> copyright="2024"
<Suspense> />
<Outlet /> )}>
</Suspense> <PageContainer title={false}>
</div> <ProCard>
</ProCard> <div>
</PageContainer> <Suspense>
</ProLayout> <Outlet />
</div> </Suspense>
); </div>
} </ProCard>
</PageContainer>
</ProLayout>
</div>
);
}