From df0da4c73d53080294f892c98b0776aa0f2014f4 Mon Sep 17 00:00:00 2001
From: lq1405 <2769838458@qq.com>
Date: Sat, 22 Mar 2025 20:50:24 +0800
Subject: [PATCH] =?UTF-8?q?V=201.0.5=20=E6=96=B0=E5=A2=9E=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E9=87=8D=E7=BD=AE=E5=AF=86=E7=A0=81=E5=92=8C=E7=94=A8?=
=?UTF-8?q?=E6=88=B7=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
config/routes.ts | 4 +-
package.json | 2 +-
src/access.ts | 10 +-
src/pages/User/Login/index.tsx | 49 ++---
src/pages/User/Register/index.tsx | 5 +-
src/pages/User/ResetPassword/index.tsx | 172 ++++++++++++++++++
src/pages/User/UserCenter/ModifyPassword.tsx | 142 +++++++++++++++
.../UserCenter/UserCenterUserInfo/index.tsx | 20 +-
src/services/typing/access.d.ts | 6 +
9 files changed, 378 insertions(+), 32 deletions(-)
create mode 100644 src/pages/User/ResetPassword/index.tsx
create mode 100644 src/pages/User/UserCenter/ModifyPassword.tsx
diff --git a/config/routes.ts b/config/routes.ts
index c3564fa..0188c33 100644
--- a/config/routes.ts
+++ b/config/routes.ts
@@ -73,13 +73,13 @@ export default [
name: 'laitoolOptions',
path: '/options/laitoolOptions',
component: './Options/LaitoolOptions/LaitoolOptions/index',
- access: 'canOptions',
+ access: 'canLaiToolOptions',
},
{
name: 'systemOptions',
path: '/options/systemOptions',
component: './Options/SystemOptions/index',
- access: 'canOptions',
+ access: 'canSystemOptions',
}
]
},
diff --git a/package.json b/package.json
index 1246552..caf6c48 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "lms",
- "version": "1.0.4",
+ "version": "1.0.5",
"private": true,
"description": "An out-of-box UI solution for enterprise applications",
"scripts": {
diff --git a/src/access.ts b/src/access.ts
index 366d77e..fda1dcc 100644
--- a/src/access.ts
+++ b/src/access.ts
@@ -16,6 +16,8 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
isAdminOrSuperAdmin: false,
canOptions: false,
+ canLaiToolOptions : false,
+ canSystemOptions : false,
canApplySoftwareControl: false,
canSofrwareControlManagement: false,
@@ -59,7 +61,7 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
if (currentUser?.roleNames?.includes("Admin")) {
access = {
...access,
- canPrompt: false,
+ canPrompt: true,
canUserManagement: true,
canEditUser: true,
@@ -67,7 +69,9 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
isAdmin: true,
isAdminOrSuperAdmin: true,
- canOptions: false,
+ canOptions: true,
+ canLaiToolOptions : true,
+ canSystemOptions : false,
canMachineManagement: true,
canEditMachine: true,
@@ -93,6 +97,8 @@ export default function access(initialState: { currentUser?: API.CurrentUser } |
isAdminOrSuperAdmin: true,
canOptions: true,
+ canLaiToolOptions : true,
+ canSystemOptions : true,
canMachineManagement: true,
canEditMachine: true,
diff --git a/src/pages/User/Login/index.tsx b/src/pages/User/Login/index.tsx
index 00fabae..b857560 100644
--- a/src/pages/User/Login/index.tsx
+++ b/src/pages/User/Login/index.tsx
@@ -16,13 +16,13 @@ import {
ProFormText,
} from '@ant-design/pro-components';
import { FormattedMessage, history, SelectLang, useIntl, useModel, Helmet } from '@umijs/max';
-import { Alert, message, Tabs } from 'antd';
+import { Alert, message, Tabs, Form, Modal } from 'antd';
import Settings from '../../../../config/defaultSettings';
import React, { useState } from 'react';
import { flushSync } from 'react-dom';
import { createStyles } from 'antd-style';
import { TokenStorage } from '@/services/define/tokenStorage';
-
+import ResetPassword from '../ResetPassword';
const useStyles = createStyles(({ token }) => {
return {
@@ -60,18 +60,6 @@ const useStyles = createStyles(({ token }) => {
};
});
-const ActionIcons = () => {
- const { styles } = useStyles();
-
- return (
- <>
-
-
-
- >
- );
-};
-
const Lang = () => {
const { styles } = useStyles();
@@ -104,6 +92,10 @@ const Login: React.FC = () => {
const { styles } = useStyles();
const intl = useIntl();
let tokenStorage = new TokenStorage();
+ const [messageApi, contextHolder] = message.useMessage();
+
+ // 重置密码相关状态
+ const [resetModalVisible, setResetModalVisible] = useState(false);
const fetchUserInfo = async () => {
let tokenObj = await tokenStorage.getTokenAndDecode();
@@ -137,6 +129,7 @@ const Login: React.FC = () => {
return (
+
+ {/* 重置密码弹窗 */}
+ setResetModalVisible(false)}
+ footer={null}
+ destroyOnClose
+ width={500}
+ >
+ setResetModalVisible(false)}
+ onSuccess={() => {
+ messageApi.success('重置密码成功,新密码将发送到您的邮箱,请尽快在个人中心修改密码');
+ setResetModalVisible(false);
+ }}
+ />
+
);
};
diff --git a/src/pages/User/Register/index.tsx b/src/pages/User/Register/index.tsx
index 941362c..6c1770f 100644
--- a/src/pages/User/Register/index.tsx
+++ b/src/pages/User/Register/index.tsx
@@ -127,7 +127,10 @@ const Register: React.FC = () => {
diff --git a/src/pages/User/ResetPassword/index.tsx b/src/pages/User/ResetPassword/index.tsx
new file mode 100644
index 0000000..8258939
--- /dev/null
+++ b/src/pages/User/ResetPassword/index.tsx
@@ -0,0 +1,172 @@
+import React, { useState } from 'react';
+import { Form, Input, Button, message, Row, Col } from 'antd';
+import { request } from '@umijs/max';
+
+interface ResetPasswordProps {
+ onCancel: () => void;
+ onSuccess?: () => void;
+}
+
+const ResetPassword: React.FC = ({ onCancel, onSuccess }) => {
+ const [form] = Form.useForm();
+ const [loading, setLoading] = useState(false);
+ const [countdown, setCountdown] = useState(0);
+ const [messageApi, contextHolder] = message.useMessage();
+
+ // 发送重置密码验证码
+ const sendResetCode = async () => {
+ try {
+ const emailValue = form.getFieldValue('email');
+ if (!emailValue) {
+ messageApi.warning('请输入邮箱');
+ return;
+ }
+
+ // 验证邮箱格式
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!emailRegex.test(emailValue)) {
+ messageApi.warning('请输入有效的邮箱格式');
+ return;
+ }
+
+ setLoading(true);
+ // 发送验证码请求
+ const res = await request>('/lms/User/SendResetPasswordCode', {
+ method: 'POST',
+ data: { email: emailValue }
+ });
+
+ if (res.code !== 1) {
+ throw new Error(res.message);
+ }
+
+ // 设置倒计时
+ setCountdown(60);
+ const timer = setInterval(() => {
+ setCountdown((prevCountdown) => {
+ if (prevCountdown <= 1) {
+ clearInterval(timer);
+ return 0;
+ }
+ return prevCountdown - 1;
+ });
+ }, 1000);
+
+ messageApi.success('验证码已发送,请查收邮箱');
+ } catch (error: any) {
+ messageApi.error(error.message || '发送验证码失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ // 提交重置密码请求
+ const handleResetPassword = async () => {
+ try {
+ debugger;
+ const values = form.getFieldsValue();
+
+ setLoading(true);
+ // 发送重置密码请求
+ const res = await request>(`/lms/User/ResetPassword/${values.email}/${values.verificationCode}`, {
+ method: 'POST'
+ });
+
+ if (res.code !== 1) {
+ throw new Error(res.message);
+ }
+
+ messageApi.success('重置密码成功,新密码将发送到您的邮箱,请尽快在个人中心修改密码');
+ onSuccess?.();
+ onCancel();
+ form.resetFields();
+ } catch (error: any) {
+ messageApi.error(error.message || '重置密码失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+ {contextHolder}
+
邮箱}
+ rules={[
+ { required: true, message: '请输入邮箱' },
+ { type: 'email', message: '请输入有效的邮箱格式' }
+ ]}
+ >
+
+
+
+ 验证码}
+ rules={[
+ { required: true, message: '请输入验证码' },
+ { pattern: /^[a-z0-9]{6}$/, message: '验证码必须是6位数字或小写字母' }
+ ]}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ResetPassword;
diff --git a/src/pages/User/UserCenter/ModifyPassword.tsx b/src/pages/User/UserCenter/ModifyPassword.tsx
new file mode 100644
index 0000000..5be219c
--- /dev/null
+++ b/src/pages/User/UserCenter/ModifyPassword.tsx
@@ -0,0 +1,142 @@
+import React, { useState } from 'react';
+import { Form, Input, Button, message, Card, Typography } from 'antd';
+import { LockOutlined } from '@ant-design/icons';
+import { request, useModel } from '@umijs/max';
+import { isEmpty } from 'lodash';
+
+const { Title } = Typography;
+
+const ResetPassword: React.FC = () => {
+ const [form] = Form.useForm();
+ const [loading, setLoading] = useState(false);
+ const [messageApi, contextHolder] = message.useMessage();
+ const { initialState, setInitialState } = useModel('@@initialState');
+
+ // 提交重置密码请求
+ const handleResetPassword = async () => {
+ try {
+ debugger;
+ const values = form.getFieldsValue();
+ if (initialState?.currentUser?.id == null) {
+ messageApi.error('用户信息不存在,请重新登录');
+ return;
+ }
+
+ // 检查两次密码是否一致
+ if (values.newPassword !== values.confirmPassword) {
+ messageApi.error('两次输入的密码不一致');
+ return;
+ }
+ if (isEmpty(values.newPassword)) {
+ messageApi.error('请输入新密码');
+ return;
+ }
+
+ setLoading(true);
+ // 发送重置密码请求
+ const res = await request>(`/lms/User/ResetPassword/${initialState?.currentUser?.id}`, {
+ method: 'POST',
+ data: {
+ "newPassword": values.newPassword,
+ }
+ });
+
+ if (res.code !== 1) {
+ throw new Error(res.message);
+ }
+ messageApi.success('密码重置成功');
+ form.resetFields();
+ } catch (error: any) {
+ messageApi.error(error.message || '密码重置失败');
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+ {contextHolder}
+
+
+
设置新密码
+
+
+
+ }
+ placeholder="请输入新密码"
+ style={{
+ height: '45px',
+ borderRadius: '4px',
+ }}
+ />
+
+
+ ({
+ validator(_, value) {
+ if (!value || getFieldValue('newPassword') === value) {
+ return Promise.resolve();
+ }
+ return Promise.reject(new Error('两次输入的密码不一致'));
+ },
+ })
+ ]}
+ >
+ }
+ placeholder="请再次输入新密码"
+ style={{
+ height: '45px',
+ borderRadius: '4px',
+ }}
+ />
+
+
+
+
+
+
+
+ );
+};
+
+export default ResetPassword;
diff --git a/src/pages/User/UserCenter/UserCenterUserInfo/index.tsx b/src/pages/User/UserCenter/UserCenterUserInfo/index.tsx
index 0b881b9..6470c14 100644
--- a/src/pages/User/UserCenter/UserCenterUserInfo/index.tsx
+++ b/src/pages/User/UserCenter/UserCenterUserInfo/index.tsx
@@ -1,29 +1,42 @@
import React from 'react';
-import { Button, Card, Divider, Dropdown, message } from 'antd';
+import { Button, Card, Divider, Dropdown, message, Modal } from 'antd';
import Icon, { LockOutlined, MailOutlined, PhoneOutlined, UserOutlined } from '@ant-design/icons';
import renderTitle from '../UserRenderList';
import { useModel } from '@umijs/max';
import { isEmpty } from 'lodash';
+import ModifyPassword from '../ModifyPassword';
const UserCenterUserInfo: React.FC = () => {
const [messageApi, messageHolder] = message.useMessage();
+ const [modalApi, modalHolder] = Modal.useModal();
const { initialState } = useModel('@@initialState');
+ async function ModifyPasswordFunc() {
+ modalApi.info({
+ title: null,
+ icon: null,
+ closable: true,
+ closeIcon: true,
+ footer: null,
+ content: ,
+ })
+ }
+
return (
,
height: 100
- })} style={{ width: "100%" }}>
+ })} style={{ width: "100%"}}>
{renderTitle({
title: '密码修改',
subTitle: '**********',
icon: ,
style: { marginLeft: 10 },
height: 60,
- button:
})}
{messageHolder}
+ {modalHolder}
);
};
diff --git a/src/services/typing/access.d.ts b/src/services/typing/access.d.ts
index deb1513..7798192 100644
--- a/src/services/typing/access.d.ts
+++ b/src/services/typing/access.d.ts
@@ -21,6 +21,12 @@ declare namespace AccessType {
//#region 软件配置项操作权限
/** 是不是可以操作配置型 */
canOptions: boolean;
+
+ /** 是不是显示LaiTool配置项的菜单 */
+ canLaiToolOptions: boolean;
+
+ /** 是不是显示系统配置项的菜单 */
+ canSystemOptions : boolean;
//#endregion
//#region 机器权限