Ver Fonte

实现用户登录和注册功能,更新表单验证规则,修改状态管理以支持邮箱登录

张涛 há 1 ano atrás
pai
commit
a9fc05e8c7

+ 0 - 5
package-lock.json

@@ -2377,11 +2377,6 @@
       "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
       "license": "MIT"
     },
-    "node_modules/@vueuse/core": {
-      "dev": true,
-      "optional": true,
-      "peer": true
-    },
     "node_modules/@vueuse/metadata": {
       "version": "11.3.0",
       "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-11.3.0.tgz",

+ 65 - 0
src/apis/login.js

@@ -0,0 +1,65 @@
+import request from '../base/ajax';
+// 登录
+export function login(data) {
+  return request({
+    url: '/console/api/login',
+    method: 'post',
+    data
+  });
+}
+// 注册
+export function register(data) {
+  return request({
+    url: '/api/auth/v2/register',
+    method: 'post',
+    data
+  });
+}
+// 注册完成同步数据
+
+export function asycData(userFlag) {
+  return request({
+    url: `/api/auth/v2/sync?userFlag=${userFlag}`,
+    method: 'get'
+  });
+}
+// 获取用户信息
+export function QueyrUserInfo() {
+  return request({
+    url: '/api/user/user_info',
+    method: 'get'
+  });
+}
+
+// 获取用户路由
+export function QueyrRoutesList() {
+  return request({
+    url: '/api/user/user_routers',
+    method: 'get'
+  });
+}
+// token转化
+export function tokenExchange() {
+  return request({
+    url: `/api/auth/token`,
+    method: 'get'
+  });
+}
+
+/**
+ * 修改用户密码
+ * @see https://app.apifox.com/link/project/5404857/apis/api-244151743
+ * @param {String} pre - 旧密码(需要加密)
+ * @param {String} cur - 新密码(需要加密)
+ * @returns
+ */
+export function changeUserPassword(pre, cur) {
+  return request({
+    url: '/api/user/change_password',
+    method: 'put',
+    data: JSON.stringify({
+      oldPassword: pre,
+      newPassword: cur
+    })
+  });
+}

+ 1 - 1
src/base/storage.js

@@ -9,7 +9,7 @@ import { MyCookie } from './storage/cookie';
  * 任意localStorage的定义,必须添加 localST_ 前缀
  */
 export const localST_UserInfo = new MyLocalStorage('user_info'); // 用户信息
-
+export const localST_RoutesList = new MyLocalStorage('routes_list'); // 用户身份token
 /**
  * session storage定义
  * 任意 sessionStorage的定义,必须添加 sessionST_ 前缀

+ 6 - 6
src/base/store/use-current-user.js

@@ -13,7 +13,7 @@ export const useCurrentUserStore = defineStore('current_user', {
       {
         key: 'info',
         storage: localStorage,
-        paths: ['username'] // 只持久化 username 属性
+        paths: ['email'] // 只持久化 email 属性
       }
     ]
   },
@@ -22,7 +22,7 @@ export const useCurrentUserStore = defineStore('current_user', {
       name: '',
       token_type: '',
       token: kuky_Authorization.get(),
-      username: '',
+      email: '',
       nickname: '',
       dept: [],
       roles: [],
@@ -35,7 +35,7 @@ export const useCurrentUserStore = defineStore('current_user', {
       this.name = '';
       this.token_type = '';
       this.token = '';
-      this.username = '';
+      this.email = '';
       this.nickname = '';
       this.dept = [];
       this.roles = [];
@@ -46,9 +46,9 @@ export const useCurrentUserStore = defineStore('current_user', {
       this.name = name;
     },
     toLogin(data) {
-      const { username, password } = data;
+      const { email, password } = data;
       return new Promise((resolve, reject) => {
-        login({ username, password })
+        login({ email, password })
           .then((res) => {
             if (res.code === 200) {
               const res_data = res.data;
@@ -56,7 +56,7 @@ export const useCurrentUserStore = defineStore('current_user', {
               if (res_data) {
                 this.token = res_data.access_token;
                 this.token_type = res_data.token_type;
-                this.username = res_data.username;
+                this.email = res_data.email;
                 this.nickname = res_data.nickname;
 
                 kuky_Authorization.set(res_data.access_token);

+ 16 - 0
src/modules/login/auth.js

@@ -0,0 +1,16 @@
+export function getLoginFormRules() {
+  return {
+    username: [
+      { required: true, message: '请输入账号', trigger: 'blur' },
+      { min: 3, max: 20, message: '账号长度应为3到20个字符', trigger: 'blur' }
+    ],
+    email: [
+      { required: true, message: '请输入邮箱', trigger: 'blur' },
+      { type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
+    ],
+    password: [
+      { required: true, message: '请输入密码', trigger: 'blur' },
+      { min: 8, max: 20, message: '密码长度应为8到20个字符', trigger: 'blur' }
+    ]
+  };
+}

+ 54 - 41
src/modules/login/login_window.vue

@@ -1,65 +1,78 @@
 <template>
-  <main>
-    <section class='login-section'>
-      <header>用户登录</header>
-      <section>
-        <label for='username' class="label-bold">账号</label>
-        <a-input id='username' placeholder='请输入账号' v-model='username' />
-      </section>
-      <section>
-        <label for='password' class="label-bold">密码</label>
-        <a-input-password id='password' placeholder='请输入密码' />
-      </section>
-      <div class='login-button' @click='register'>登录</div>
-    </section>
-  </main>
+  <section class="login-form-container">
+    <header>用户登录</header>
+    <a-form ref="ref_form" :model="form" :rules="rules" layout="vertical" @submit-success="handleSubmit">
+      <a-form-item label="邮箱" field="email" hide-asterisk="true">
+        <a-input v-model="form.email" placeholder="请输入邮箱">
+          <template #prefix> <icon-user /> </template>
+        </a-input>
+      </a-form-item>
+      <a-form-item label="密码" field="password" hide-asterisk="true">
+        <a-input-password placeholder="请输入密码" v-model="form.password">
+          <template #prefix> <icon-lock /> </template>
+        </a-input-password>
+      </a-form-item>
+      <a-form-item><a-button class="login-button" html-type="submit">登录</a-button></a-form-item>
+    </a-form>
+  </section>
 </template>
 
 <script setup>
-import { ref } from 'vue';
+import { ref, reactive } from 'vue';
+import { useRouter } from 'vue-router';
+import { encrypt } from '../../utils/jsencrypt';
+import { useCurrentUserStore } from '../../base/store/use-current-user';
+import { getLoginFormRules } from './auth';
+import { Message } from '../../3rd-libs/arco-vue-libs';
 
-const username = ref('');
+const router = useRouter();
+const userStore = useCurrentUserStore();
 
-function register() {
-  console.log('登录');
-}
+const ref_form = ref();
+const form = reactive({
+  email: 'xyh@basic.com',
+  password: 'Xyh741852'
+});
+const rules = getLoginFormRules();
+
+const handleSubmit = (data) => {
+  console.log('data222222222222222222', data);
+  userStore
+    .toLogin({ email: data.email, password: data.password })
+    .then(async (res) => {
+      Message.success(res);
+
+      // // 登录成功后,获取路由列表
+      // await userStore.getRoutesList();
+      // // 登录成功后,获取用户权限
+      // await userStore.getUserInfo();
+
+      router.replace({ path: '/' });
+    })
+    .catch((err) => {
+      Message.error('登录失败,请检查您的邮箱和密码');
+    });
+};
 </script>
 
 <style scoped>
-main {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  width: 65%;
-}
-
-.login-section {
+.login-form-container {
   padding: 40px;
   background-color: #fff;
   border-radius: 12px;
   box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
-  width: 100%;
+  width: 55%;
 }
 
-.login-section header {
+.login-form-container header {
   font-size: 32px;
   font-weight: 600;
   margin-bottom: 30px;
   text-align: center;
 }
 
-.login-section section {
-  margin-bottom: 30px;
-}
-
-.login-section label {
-  display: block;
-  margin-bottom: 10px;
-  font-size: 20px;
-}
-
-.login-section .a-input,
-.login-section .a-input-password {
+.login-form-container .a-input,
+.login-form-container .a-input-password {
   width: 100%;
   height: 48px;
   border: 1px solid #ccc;

+ 13 - 15
src/views/Login.vue

@@ -1,30 +1,28 @@
 <template>
-  <div class='page'>
-    <div class='login-logo'>
-      <img class='logo-img' src='/logo.png' alt='logo' />
-      <div class='logo-title'>
-        SmartAI大模型平台
-      </div>
+  <div class="page">
+    <div class="login-logo">
+      <img class="logo-img" src="/logo.png" alt="logo" />
+      <div class="logo-title">SmartAI大模型平台</div>
     </div>
 
-    <div class='login-section'>
-      <div class='intro'>
-        <div class='intro-title'>SmartAI大模型平台</div>
-        <div class='intro-title'>覆盖大多数典型业务场景</div>
-        <img src='../assets/image/login/login_group.png' alt='' />
+    <div class="login-section">
+      <div class="intro">
+        <div class="intro-title">SmartAI大模型平台</div>
+        <div class="intro-title">覆盖大多数典型业务场景</div>
+        <img src="../assets/image/login/login_group.png" alt="" />
       </div>
-      <div class='login-window'>
-        <login_window/>
+      <div class="login-window">
+        <login_window />
       </div>
     </div>
   </div>
 </template>
 
 <script setup>
-import login_window from "../modules/login/login_window.vue";
+import login_window from '../modules/login/login_window.vue';
 </script>
 
-<style scoped lang='css'>
+<style scoped lang="css">
 .page {
   display: flex;
   flex-direction: column;

+ 9 - 1
vite.config.mjs

@@ -42,7 +42,15 @@ export default defineConfig(({ mode }) => {
           cors: true,
           rewrite: (path) => path.replace(/^\/proxy_url/, '')
         },
-
+        '/console/': {
+          target: 'http://smartai.com:8163',
+          // target: 'http://192.168.20.119:9303',
+          changeOrigin: true,
+          secure: false,
+          ws: true,
+          cors: true,
+          rewrite: (path) => path.replace(/^\/proxy_url/, '')
+        },
         '/dify': {
           target: 'http://192.168.20.119:28003/',
           changeOrigin: true,