panhui 4 gadi atpakaļ
vecāks
revīzija
00eb9f8a18

+ 2 - 0
src/main/java/com/izouma/nineth/security/WebSecurityConfig.java

@@ -62,6 +62,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 //swagger-ui放行路径
                 .antMatchers("/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**", "/webjars/**").permitAll()
                 .antMatchers("/user/register").permitAll()
+                .antMatchers("/user/registerByPhone").permitAll()
                 .antMatchers("/upload/**").permitAll()
                 .antMatchers("/files/**").permitAll()
                 .antMatchers("/static/**").permitAll()
@@ -72,6 +73,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 .antMatchers("/**/excel").permitAll()
                 .antMatchers("/wx/**").permitAll()
                 .antMatchers("/sms/sendVerify").permitAll()
+                .antMatchers("/sms/verify").permitAll()
                 .antMatchers("/error").permitAll()
                 .antMatchers("/401").permitAll()
                 .antMatchers("/404").permitAll()

+ 13 - 0
src/main/java/com/izouma/nineth/web/UserController.java

@@ -45,6 +45,19 @@ public class UserController extends BaseController {
         return userService.create(user);
     }
 
+    @PostMapping("/registerByPhone")
+    public User registerByPhone(@RequestParam String phone,
+                         @RequestParam String password) {
+        UserRegister user = UserRegister.builder()
+                .username("用户"+phone)
+                .nickname("用户"+phone)
+                .phone(phone)
+                .password(new BCryptPasswordEncoder().encode(password))
+                .authorities(Collections.singleton(Authority.get(AuthorityName.ROLE_USER)))
+                .build();
+        return userService.create(user);
+    }
+
     @PreAuthorize("hasRole('ADMIN')")
     @PostMapping("/create")
     public User create(@RequestBody UserRegister userRegister) {

+ 2 - 0
src/main/nine-space/src/main.js

@@ -12,11 +12,13 @@ import http from "./plugins/http";
 import PageTitle from "./components/PageTitle";
 import LikeButton from "./components/LikeButton.vue";
 import Driver from "./components/Driver.vue";
+import common from "./mixins/common";
 
 createApp(App)
   .use(Vant)
   .use(http)
   .use(ConfigProvider)
+  .mixin(common)
   .component("page-title", PageTitle)
   .component("like-button", LikeButton)
   .component("driver", Driver)

+ 7 - 0
src/main/nine-space/src/mixins/common.js

@@ -0,0 +1,7 @@
+export default {
+  computed: {
+    isLogin() {
+      return !!this.$store.state.userInfo;
+    },
+  },
+};

+ 17 - 0
src/main/nine-space/src/mixins/phone.js

@@ -56,5 +56,22 @@ export default {
           return Promise.reject();
         });
     },
+    loginByPhone(phone, psd) {
+      return this.$http
+        .post("/auth/phonePwdLogin", {
+          phone: phone,
+          password: psd,
+        })
+        .catch((e) => {
+          if (e) {
+            this.$toast(e.error);
+          }
+          return Promise.reject();
+        })
+        .then((res) => {
+          localStorage.setItem("nineToken", res);
+          return this.$store.dispatch("getUserInfo");
+        });
+    },
   },
 };

+ 103 - 103
src/main/nine-space/src/plugins/http.js

@@ -1,123 +1,123 @@
-import axios from 'axios';
-import qs from 'qs';
+import axios from "axios";
+import qs from "qs";
 /* eslint-disable */
-let baseUrl = 'http://localhost:8080';
+let baseUrl = "http://localhost:8080";
 switch (process.env.NODE_ENV) {
-    case 'development':
-        // baseUrl = 'http://zhirongip.izouma.com';
-        // baseUrl = 'http://192.168.50.190:8080';
-        baseUrl = 'http://localhost:8080';
-        // baseUrl = 'http://192.168.50.190:8080';
-        break;
-    case 'test':
-        baseUrl = 'http://localhost:8080';
-        break;
-    case 'production':
-        baseUrl = '../../';
-        break;
+  case "development":
+    // baseUrl = 'http://zhirongip.izouma.com';
+    // baseUrl = 'http://192.168.50.190:8080';
+    baseUrl = "http://localhost:8080";
+    // baseUrl = 'http://192.168.50.190:8080';
+    break;
+  case "test":
+    baseUrl = "http://localhost:8080";
+    break;
+  case "production":
+    baseUrl = "../../";
+    break;
 }
 const axiosInstance = axios.create({
-    baseURL: baseUrl
+  baseURL: baseUrl
 });
 
 axiosInstance.interceptors.request.use(
-    function (config) {
-        config.headers = config.headers || {};
-        let token = localStorage.getItem('webToken');
-        if (token) {
-            config.headers['Authorization'] = 'Bearer ' + token;
-        }
-        return config;
-    },
-    function (error) {
-        return Promise.reject(error);
+  function (config) {
+    config.headers = config.headers || {};
+    let token = localStorage.getItem("nineToken");
+    if (token) {
+      config.headers["Authorization"] = "Bearer " + token;
     }
+    return config;
+  },
+  function (error) {
+    return Promise.reject(error);
+  }
 );
 
 axiosInstance.interceptors.response.use(
-    function (response) {
-        return response;
-    },
-    function (error) {
-        let errorData = {};
-        if (!error.response) {
-            errorData = {
-                error: '网络错误,请检查网络链接'
-            };
-        } else {
-            errorData = error.response.data;
-            // if (401 === error.response.status) {
-            //     if (router.currentRoute.name !== 'login') {
-            //         router.replace({
-            //             name: 'login',
-            //             params: {
-            //                 from: router.currentRoute.name
-            //             }
-            //         });
-            //     } else {
-            //     }
-            // }
-        }
-        console.log(typeof errorData);
-        if (typeof errorData != 'object') {
-            errorData = {
-                error: '请求失败' + error.response.status
-            };
-        }
-        return Promise.reject(errorData);
+  function (response) {
+    return response;
+  },
+  function (error) {
+    let errorData = {};
+    if (!error.response) {
+      errorData = {
+        error: "网络错误,请检查网络链接"
+      };
+    } else {
+      errorData = error.response.data;
+      // if (401 === error.response.status) {
+      //     if (router.currentRoute.name !== 'login') {
+      //         router.replace({
+      //             name: 'login',
+      //             params: {
+      //                 from: router.currentRoute.name
+      //             }
+      //         });
+      //     } else {
+      //     }
+      // }
     }
+    console.log(typeof errorData);
+    if (typeof errorData != "object") {
+      errorData = {
+        error: "请求失败" + error.response.status
+      };
+    }
+    return Promise.reject(errorData);
+  }
 );
 
 const http = {
-    get(url, params) {
-        params = params || {};
-        return new Promise((resolve, reject) => {
-            axiosInstance
-                .get(
-                    url,
-                    {
-                        params: params
-                    },
-                    {
-                        withCredentials: true
-                    }
-                )
-                .then(res => {
-                    resolve(res.data);
-                })
-                .catch(e => {
-                    reject(e);
-                });
-        });
-    },
-    post(url, body, options) {
-        options = options || {};
-        body = body || {};
-        if (!(body instanceof FormData)) {
-            if (options.body !== 'json') {
-                body = qs.stringify(body);
-            }
-        }
-        return new Promise((resolve, reject) => {
-            axiosInstance
-                .post(url, body, {
-                    withCredentials: true
-                })
-                .then(res => {
-                    resolve(res.data);
-                })
-                .catch(e => {
-                    reject(e);
-                });
+  get(url, params) {
+    params = params || {};
+    return new Promise((resolve, reject) => {
+      axiosInstance
+        .get(
+          url,
+          {
+            params: params
+          },
+          {
+            withCredentials: true
+          }
+        )
+        .then((res) => {
+          resolve(res.data);
+        })
+        .catch((e) => {
+          reject(e);
         });
+    });
+  },
+  post(url, body, options) {
+    options = options || {};
+    body = body || {};
+    if (!(body instanceof FormData)) {
+      if (options.body !== "json") {
+        body = qs.stringify(body);
+      }
     }
+    return new Promise((resolve, reject) => {
+      axiosInstance
+        .post(url, body, {
+          withCredentials: true
+        })
+        .then((res) => {
+          resolve(res.data);
+        })
+        .catch((e) => {
+          reject(e);
+        });
+    });
+  }
 };
 export default {
-    axios: axiosInstance,
-    http: http,
-    install(app, options) {
-        app.config.globalProperties.$baseUrl = baseUrl;
-        app.config.globalProperties.$axios = axiosInstance;
-        app.config.globalProperties.$http = http;
-    }
+  axios: axiosInstance,
+  http: http,
+  install(app, options) {
+    app.config.globalProperties.$baseUrl = baseUrl;
+    app.config.globalProperties.$axios = axiosInstance;
+    app.config.globalProperties.$http = http;
+  }
 };

+ 58 - 9
src/main/nine-space/src/router/index.js

@@ -1,4 +1,7 @@
 import { createRouter, createWebHistory } from "vue-router";
+import store from "../store";
+import { Page } from "./Page";
+import { Dialog } from "vant";
 
 const routes = [
   {
@@ -13,21 +16,37 @@ const routes = [
         path: "/home",
         name: "home",
         component: () => import("../views/Home.vue"),
+        meta: {
+          pageType: Page.Every,
+          title: "第九空间",
+        },
       },
       {
         path: "/discover",
         name: "discover",
         component: () => import("../views/Discover.vue"),
+        meta: {
+          pageType: Page.Every,
+          title: "第九空间",
+        },
       },
       {
         path: "/store",
         name: "store",
         component: () => import("../views/Store.vue"),
+        meta: {
+          pageType: Page.Every,
+          title: "第九空间",
+        },
       },
       {
         path: "/mine",
         name: "mine",
         component: () => import("../views/Mine.vue"),
+        meta: {
+          pageType: Page.Every,
+          title: "第九空间",
+        },
       },
     ],
   },
@@ -35,16 +54,28 @@ const routes = [
     path: "/login",
     name: "userLogin",
     component: () => import("../views/user/Login.vue"),
+    meta: {
+      pageType: Page.Login,
+      title: "登录",
+    },
   },
   {
     path: "/register",
     name: "userRegister",
     component: () => import("../views/user/Register.vue"),
+    meta: {
+      pageType: Page.Login,
+      title: "注册",
+    },
   },
   {
     path: "/forget",
     name: "userForget",
     component: () => import("../views/user/Forget.vue"),
+    meta: {
+      pageType: Page.Login,
+      title: "忘记密码",
+    },
   },
   {
     path: "/verified",
@@ -55,15 +86,10 @@ const routes = [
     path: "/detail",
     name: "detail",
     component: () => import("../views/Detail.vue"),
-  },
-  {
-    path: "/about",
-    name: "About",
-    // route level code-splitting
-    // this generates a separate chunk (about.[hash].js) for this route
-    // which is lazy-loaded when the route is visited.
-    component: () =>
-      import(/* webpackChunkName: "about" */ "../views/About.vue"),
+    meta: {
+      pageType: Page.Every,
+      title: "第九空间",
+    },
   },
 ];
 
@@ -72,4 +98,27 @@ const router = createRouter({
   routes,
 });
 
+router.beforeEach((to, from, next) => {
+  if (!store.state.userInfo && to.meta.pageType !== Page.Login) {
+    store
+      .dispatch("getUserInfo")
+      .then(() => {
+        next();
+      })
+      .catch(() => {
+        if (to.meta.pageType != Page.Every) {
+          Dialog.alert({
+            message: "用户未登录",
+          }).then(() => {
+            next("/login");
+          });
+        } else {
+          next();
+        }
+      });
+  } else {
+    next();
+  }
+});
+
 export default router;

+ 19 - 1
src/main/nine-space/src/store/index.js

@@ -1,14 +1,32 @@
 import { createStore } from "vuex";
+import http from "../plugins/http";
 
 export default createStore({
   state: {
     finished: false,
+    userInfo: null,
   },
   mutations: {
     setFinished(state, finished) {
       state.finished = finished;
     },
+    setUserInfo(state, userInfo) {
+      state.userInfo = userInfo;
+    },
+  },
+  actions: {
+    getUserInfo(context) {
+      return http.http
+        .get("/user/my")
+        .then((res) => {
+          context.commit("setUserInfo", res);
+          return Promise.resolve();
+        })
+        .catch(() => {
+          context.commit("setUserInfo", null);
+          return Promise.reject();
+        });
+    },
   },
-  actions: {},
   modules: {},
 });

+ 4 - 0
src/main/nine-space/src/styles/app.less

@@ -38,3 +38,7 @@ input:-webkit-autofill {
   box-shadow: 0 0 0px 1000px @bg inset;
   -webkit-text-fill-color: #fff;
 }
+
+.van-dialog {
+  color: #000;
+}

+ 7 - 1
src/main/nine-space/src/views/Mine.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="mine">
+    <div class="userInfo"></div>
     <div class="top">
       <van-image
         round
@@ -112,7 +113,12 @@
 </template>
 
 <script>
-export default {};
+import { mapState } from "vuex";
+export default {
+  computed: {
+    ...mapState(["userInfo"]),
+  },
+};
 </script>
 
 <style lang="less" scoped>

+ 2 - 4
src/main/nine-space/src/views/user/Forget.vue

@@ -79,16 +79,14 @@
           native-type="submit"
           color="linear-gradient(to right, #FDFB60, #FF8F3E)"
           class="sure"
-          @click="$router.push('/register')"
-          >立即注册</van-button
+          >找回密码</van-button
         >
         <van-button
           class="del"
           round
           block
-          native-type="submit"
           plain
-          @click="$router.push('/login')"
+          @click="$router.replace('/login')"
           >想起密码,立即登陆</van-button
         >
       </div>

+ 60 - 9
src/main/nine-space/src/views/user/Login.vue

@@ -17,13 +17,19 @@
       </div>
     </div>
 
-    <van-form @submit="submit">
+    <van-form @submit="submit" ref="form">
       <van-field
         type="tel"
         name="用户名"
-        placeholder="请输入用户名"
+        placeholder="请输入手机号码"
         v-model="form.phone"
-        :rules="[{ required: true, message: '请填写用户名' }]"
+        :rules="[
+          { required: true, message: '请输入手机号码' },
+          {
+            pattern: phonePattern,
+            message: '手机号码格式错误',
+          },
+        ]"
       >
         <template #left-icon>
           <img
@@ -63,13 +69,22 @@
           />
         </template>
         <template #button>
-          <van-button class="sub-code" size="small" plain type="primary"
-            >发送验证码</van-button
+          <van-button
+            class="sub-code"
+            size="small"
+            plain
+            type="primary"
+            @click="sendPhone"
+            :disabled="isSend"
           >
+            {{ isSend ? `已发送(${sendNum})S` : "发送验证码" }}
+          </van-button>
         </template>
       </van-field>
       <div class="button">
-        <van-button plain class="forget">忘记密码?</van-button>
+        <van-button plain class="forget" @click="$router.replace('/forget')">
+          忘记密码?
+        </van-button>
 
         <van-button
           round
@@ -83,9 +98,8 @@
           class="del"
           round
           block
-          native-type="submit"
           plain
-          @click="$router.push('/register')"
+          @click="$router.replace('/register')"
           >暂无账号,立即注册</van-button
         >
       </div>
@@ -94,7 +108,9 @@
 </template>
 
 <script>
+import phone from "../../mixins/phone";
 export default {
+  mixins: [phone],
   data() {
     return {
       active: "phone",
@@ -106,8 +122,43 @@ export default {
     };
   },
   methods: {
+    sendPhone() {
+      this.$refs.form.validate("手机号码").then(() => {
+        this.sendMsg(this.form.phone);
+      });
+    },
     submit() {
-      console.log("63772");
+      this.$toast.loading({
+        message: "加载中...",
+        forbidClick: true,
+      });
+      this.check().then(() => {
+        this.$toast.success("登录成功");
+        setTimeout(() => {
+          this.$router.back();
+        }, 1500);
+      });
+    },
+    check() {
+      if (this.active === "phone") {
+        return this.loginByPhone(this.form.phone, this.form.password);
+      } else {
+        return this.$http
+          .post("/auth/phoneLogin", {
+            phone: this.form.phone,
+            code: this.form.code,
+          })
+          .catch((e) => {
+            if (e) {
+              this.$toast(e.error);
+            }
+            return Promise.reject();
+          })
+          .then((res) => {
+            localStorage.setItem("nineToken", res);
+            return this.$store.dispatch("getUserInfo");
+          });
+      }
     },
   },
 };

+ 67 - 10
src/main/nine-space/src/views/user/Register.vue

@@ -4,14 +4,20 @@
       <div class="tab active">用户注册</div>
     </div>
 
-    <van-form @submit="submit">
+    <van-form @submit="submit" ref="form">
       <van-field
         type="tel"
-        name="用户名"
-        placeholder="请输入用户名"
+        name="手机号码"
+        placeholder="请输入手机号码"
         v-model="form.phone"
         :maxlength="11"
-        :rules="[{ required: true, message: '请填写用户名' }]"
+        :rules="[
+          { required: true, message: '请输入手机号码' },
+          {
+            pattern: phonePattern,
+            message: '手机号码格式错误',
+          },
+        ]"
       >
         <template #left-icon>
           <img
@@ -36,9 +42,16 @@
           />
         </template>
         <template #button>
-          <van-button class="sub-code" size="small" plain type="primary"
-            >发送验证码</van-button
+          <van-button
+            @click="sendPhone"
+            class="sub-code"
+            size="small"
+            plain
+            :disabled="isSend"
+            type="primary"
           >
+            {{ isSend ? `已发送(${sendNum})S` : "发送验证码" }}
+          </van-button>
         </template>
       </van-field>
 
@@ -62,7 +75,19 @@
         name="密码"
         placeholder="请再次输入密码"
         v-model="form.password2"
-        :rules="[{ required: true, message: '请再次填写密码' }]"
+        :rules="[
+          { required: true, message: '请再次填写密码' },
+          {
+            validator: (val) => {
+              if (val == form.password) {
+                return true;
+              } else {
+                return false;
+              }
+            },
+            message: '两次密码输入不一致',
+          },
+        ]"
       >
         <template #left-icon>
           <img
@@ -85,9 +110,8 @@
           class="del"
           round
           block
-          native-type="submit"
           plain
-          @click="$router.push('/login')"
+          @click="$router.replace('/login')"
           >已有账号,立即登陆</van-button
         >
       </div>
@@ -96,7 +120,9 @@
 </template>
 
 <script>
+import phone from "../../mixins/phone";
 export default {
+  mixins: [phone],
   data() {
     return {
       active: "phone",
@@ -109,8 +135,39 @@ export default {
     };
   },
   methods: {
+    sendPhone() {
+      this.$refs.form.validate("手机号码").then(() => {
+        this.sendMsg(this.form.phone);
+      });
+    },
     submit() {
-      console.log("63772");
+      this.$toast.loading({
+        message: "加载中...",
+        forbidClick: true,
+      });
+      this.verifyMsg(this.form.phone, this.form.code)
+        .then(() => {
+          return this.$http.post(
+            "/user/registerByPhone?phone=" +
+              this.form.phone +
+              "&password=" +
+              this.form.password
+          );
+        })
+        .then(() => {
+          return this.loginByPhone(this.form.phone, this.form.password);
+        })
+        .then(() => {
+          this.$toast.success("注册成功");
+          setTimeout(() => {
+            this.$router.back();
+          }, 1500);
+        })
+        .catch((e) => {
+          if (e) {
+            this.$toast(e.error);
+          }
+        });
     },
   },
 };

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 225 - 225
src/main/nine-space/yarn.lock


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels