2 Achegas 3e61cebdad ... a87467c4e2

Autor SHA1 Mensaxe Data
  sunsheng a87467c4e2 登录新增验证码校验 hai 2 meses
  sunsheng 519bc04715 登录新增验证码校验 hai 2 meses
Modificáronse 6 ficheiros con 99 adicións e 6 borrados
  1. 10 0
      env/.env.development
  2. 10 1
      src/apis/index.ts
  3. 32 3
      src/pages/login/index.tsx
  4. 31 1
      src/pages/login/store.tsx
  5. 7 0
      src/pages/login/types.ts
  6. 9 1
      vite.config.ts

+ 10 - 0
env/.env.development

@@ -0,0 +1,10 @@
+# 开发环境
+VITE_ENV = 'development'
+
+# Api地址
+VITE_API_URL = 'http://192.168.3.123:8090'
+VITE_API_URL_img = 'http://192.168.3.123'
+# VITE_API_URL = 'http://xia0miduo.gicp.net:8091'
+
+#跳转地址
+VITE_JUMP_URL = 'http://localhost:4000/#/knowledgeChat?showMenu=true&chatMode=LOCAL'

+ 10 - 1
src/apis/index.ts

@@ -6,6 +6,8 @@ import audit from '@/pages/deepseek/audit';
 export type LoginApiParams = {
     userName: string,
     password: string,
+    uuid: string,
+    code: string|number,
 };
 
 // Api参数类型
@@ -196,10 +198,16 @@ const jkloginApi: JkLoginApi = async (data) => {
     return api.post('/jk_code_login', data);
 };
 
-// 登录
+// 登录 prod-api/admin/login
 const loginApi: LoginApi = async (data) => {
+    // return api.post('-captchaImage/dev-api/admin/login', data);
     return api.post('/login', data);
 };
+// 验证码 prod-api/captchaImage
+const captchaImage = async () => {
+    const url = import.meta.env.VITE_ENV==='development'?'-captchaImage/dev-api/captchaImage':'/prod-api/captchaImage';
+    return api.get(url, {});
+};
 
 // 登出
 const logoutApi: LogoutApi = async () => {
@@ -486,6 +494,7 @@ export const apis = {
     checkToken: checkTokenApi,
     jklogin: jkloginApi,
     login: loginApi,
+    captchaImage:captchaImage,
     logout: logoutApi,
     fetchAppList: fetchAppListApi,
     fetchKnowledgeLibList: fetchKnowledgeLibListApi,

+ 32 - 3
src/pages/login/index.tsx

@@ -1,6 +1,6 @@
 import * as React from 'react';
 import { observer } from 'mobx-react';
-import { Form, Input, Checkbox, Button } from 'antd';
+import { Form, Input, Checkbox, Button,Row,Col } from 'antd';
 import Copyright from './components/Copyright';
 import backgroundSrc from '@/assets/login/background.jpg';
 import { regex } from '@/utils';
@@ -13,13 +13,14 @@ const Login: React.FC = () => {
     const {
         state,
         onClickLogin,
+        onCaptchaImage,
         init,
         reset
     } = store;
     const {
-        buttonLoading
+        buttonLoading,
+        captchaData
     } = state;
-
     const [form] = Form.useForm();
 
     React.useEffect(() => {
@@ -66,6 +67,32 @@ const Login: React.FC = () => {
                         >
                             <Input.Password size='large' placeholder='请输入密码' />
                         </FormItem>
+                        <FormItem
+                            name='code'
+                            rules={[{ required: true, message: '验证码' }]}
+                        > 
+                              <Row gutter={8} >
+                                    {/* 输入框占大部分宽度 */}
+                                    <Col span={17}>
+                                        <Input size='large' placeholder='请输入验证码' />
+                                    </Col>
+                                    {/* 验证码图片固定宽度 */}
+                                    <Col span={7}>
+                                        <div>
+                                            <img 
+                                                src={`data:image/png;base64,${captchaData.img}`} 
+                                                alt="验证码"
+                                                style={{ 
+                                                    width: '101px', 
+                                                    height: '38px', 
+                                                    cursor: 'pointer'  // 提示可点击刷新
+                                                }}
+                                                onClick={() => { onCaptchaImage()}}
+                                            />
+                                        </div>
+                                    </Col>
+                                </Row>
+                        </FormItem>
                         <FormItem
                             name='remember'
                             valuePropName='checked'
@@ -85,6 +112,8 @@ const Login: React.FC = () => {
                                         const data = {
                                             userName: values.account,
                                             password: values.password,
+                                            code: values.code,
+                                            uuid: captchaData.uuid
                                         }
                                         await onClickLogin(data, values.remember);
                                     }).catch((error) => {

+ 31 - 1
src/pages/login/store.tsx

@@ -8,6 +8,10 @@ import { State, ReadonlyState, StateAction, LoginStore } from './types';
 // 定义状态
 const stateGenerator = (): ReadonlyState => ({
     buttonLoading: false,
+    captchaData: {
+        uuid: '',
+        img: ''
+    }
 });
 
 // 修改状态
@@ -16,6 +20,9 @@ const stateActionsGenerator = (state: State): StateAction => {
         setButtonLoading: (loading) => {
             state.buttonLoading = loading;
         },
+        setCaptchaData:(data:any)=>{
+            state.captchaData = data
+        }
     };
 };
 
@@ -29,7 +36,9 @@ const useLoginStore = (): LoginStore => {
         login: async (data: LoginApiParams, remember: boolean) => {
             actions.setButtonLoading(true);
             try {
-                const res = await apis.login(data);
+                const res = await apis.login({
+                    ...data,
+                });
                 const info = res.data;
                 if (remember) {// 记住密码
                     LocalStorage.setAccountPassword({
@@ -74,6 +83,19 @@ const useLoginStore = (): LoginStore => {
                 actions.setButtonLoading(false);
             }
         },
+        // 验证码
+        captchaImage: async()=>{
+            console.log('验证码图片加载')
+            try {
+                const res = await apis.captchaImage();
+                console.log('验证码图片加载成功',res)
+                actions.setCaptchaData(res?.data||{});
+                return res;
+            } catch (error: any) {
+                console.log('error',error)
+                message.error(error);
+            }
+        }
     }
 
     // 点击登录
@@ -81,9 +103,16 @@ const useLoginStore = (): LoginStore => {
         // 登录
         await api.login(data, remember);
     }
+    // 切换验证码
+    const onCaptchaImage = async ()=>{
+        await api.captchaImage();
+    }
+
+
 
     // 初始渲染
     const init: LoginStore['init'] = (form) => {
+        api.captchaImage();
         const accountPassword = LocalStorage.getAccountPassword();
         if (accountPassword) {
             form.setFieldsValue({
@@ -104,6 +133,7 @@ const useLoginStore = (): LoginStore => {
     return {
         state,
         onClickLogin,
+        onCaptchaImage,
         init,
         reset
     };

+ 7 - 0
src/pages/login/types.ts

@@ -1,9 +1,14 @@
 import { FormInstance } from 'antd';
 import { LoginApiParams } from '@/apis';
 
+interface CaptchaData{
+    uuid: string,
+    img: string,
+};
 // 定义状态
 export type State = {
     buttonLoading: boolean,
+    captchaData:CaptchaData
 };
 
 // 只读状态
@@ -12,12 +17,14 @@ export type ReadonlyState = Readonly<State>;
 // 修改状态
 export type StateAction = {
     setButtonLoading: (loading: State['buttonLoading']) => void,
+    setCaptchaData: (data: any) => void,
 };
 
 // 仓库类型
 export type LoginStore = {
     state: ReadonlyState,
     onClickLogin: (data: LoginApiParams, remember: boolean) => Promise<any>,
+    onCaptchaImage: () => Promise<any>,
     init: (form: FormInstance) => void,
     reset: () => void,
 };

+ 9 - 1
vite.config.ts

@@ -38,6 +38,14 @@ export default defineConfig(({ mode, command }) => {
       strictPort: false,
       // 代理规则
       proxy: {
+        '/api/-captchaImage': {
+          // 开启跨域
+          changeOrigin: true,
+          // 转发地址
+          target: env.VITE_API_URL_img,
+          // 路径重写
+          rewrite: (path) => path.replace(/^\/api\/-captchaImage/i, '')
+        },
         '/api': {
           // 开启跨域
           changeOrigin: true,
@@ -45,7 +53,7 @@ export default defineConfig(({ mode, command }) => {
           target: env.VITE_API_URL,
           // 路径重写
           rewrite: (path) => path.replace(/^\/api/, ''),
-        },
+        }
       }
     },
     build: {