Sfoglia il codice sorgente

开发规范重做

Michael Wang 4 anni fa
parent
commit
1795bdba75

+ 18 - 5
http-test/user.http

@@ -1,12 +1,25 @@
 ### login
-POST http://192.168.10.30:10060/ocean/api/ocean-cloud-security/security/partitionUserLogin
+POST http://192.168.10.36:6001/api/admin/user/login/account
 Content-Type: application/json;charset=UTF-8
+platform: web
+deviceId: 1
+
+{"loginName":"sysadmin","password":"1jdzWuniG6UMtoa3T6uNLA==", "code": "test1"}
+
+
+
+
+### getMenu
+GET http://192.168.10.36:6001/api/admin/sys/getMenu
+Content-Type: application/json;charset=UTF-8
+Authorization: Token 1-1591624781-admin_web:iua0xVxyUyudOfayBJLjKZ1XZBg=
+platform: web
+deviceId: 1
+time: 0
+
 
 {
-  "$partitionId": 1,
-  "accountType": "loginName",
-  "accountValue": "wzj",
-  "password": 123456
+
 }
 
 

+ 3 - 1
jsconfig.json

@@ -1,6 +1,8 @@
 {
   "compilerOptions": {
-    "target": "es6",
+    "target": "es2020",
+    "module": "commonjs",
+    "allowSyntheticDefaultImports": true,
     "baseUrl": "./",
     "paths": {
       "@/*": ["src/*"]

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
-  "name": "vue-starter",
-  "version": "0.5.0-dev",
+  "name": "exam-admin",
+  "version": "1.0.0",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",

+ 4 - 5
public/index.html

@@ -5,20 +5,19 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0" />
     <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
-    <title><%= htmlWebpackPlugin.options.title %></title>
+    <title>在线考试管理后台</title>
   </head>
   <body>
     <noscript>
       <strong
-        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
-        properly without JavaScript enabled. Please enable it to
-        continue.</strong
+        >We're sorry but 在线考试管理后台 doesn't work properly without
+        JavaScript enabled. Please enable it to continue.</strong
       >
     </noscript>
     <div id="app"></div>
     <script>
       var _hmt = _hmt || [];
-      (function() {
+      (function () {
         var hmId = "xxxxx";
         var hm = document.createElement("script");
         hm.src = "https://hm.baidu.com/hm.js?" + hmId;

+ 0 - 0
src/api/.gitkeep


+ 26 - 33
src/api/login.js

@@ -1,42 +1,35 @@
 import { httpApp } from "@/plugins/axiosIndex";
 
-export function loginByUsername({
-  accountType,
-  accountValue,
-  sessionType,
-  password,
-}) {
-  const data = {
-    accountType,
-    accountValue,
-    password,
-    sessionType,
-  };
-  return httpApp.post(
-    "/ocean/api/ocean-cloud-security/security/adminUserLogin",
-    data
-  );
-}
+const CryptoJS = require("crypto-js");
 
-export function loginByPhone({ securityPhone, securityCode }) {
-  const data = {
-    securityPhone,
-    securityCode,
-  };
-  return httpApp.post(
-    "/ocean/api/ocean-cloud-security/security/adminUserSmsLogin",
-    data
-  );
-}
+const AES = (content) => {
+  const KEY = "1234567890123456";
+  const IV = "1234567890123456";
+  // const key = CryptoJS.enc.Utf8.parse("1234567890123456");
+  // console.log(key);
+  // const key = "1234567890123456";
+  console.log(content);
+
+  var key = CryptoJS.enc.Utf8.parse(KEY);
+  var iv = CryptoJS.enc.Utf8.parse(IV);
+  var encrypted = CryptoJS.AES.encrypt(content, key, { iv: iv });
+  return encrypted.toString();
+
+  // const enstr = CryptoJS.AES.encrypt(content + "", key, {
+  //   // mode: CryptoJS.mode.ECB,
+  //   // padding: CryptoJS.pad.Pkcs7,
+  // }).toString();
+
+  // return enstr;
+};
 
-export function sendSMS({ securityPhone }) {
+export function loginByUsername({ loginName, password, code }) {
   const data = {
-    securityPhone,
+    loginName,
+    password: AES(password),
+    code,
   };
-  return httpApp.post(
-    "/ocean/api/ocean-cloud-security/security/sendSms4AdminUser",
-    data
-  );
+  return httpApp.post("/api/admin/user/login/account", data);
 }
 
 export function logout() {

+ 6 - 0
src/constant/constants.js

@@ -1 +1,7 @@
 export const YYYYMMDDHHmmss = "YYYY-MM-DD HH:mm:ss";
+export const PLATFORM = "web";
+
+if (!localStorage.getItem("deviceId")) {
+  localStorage.setItem("deviceId", Math.random() + "-" + Date.now());
+}
+export const DEVICE_ID = localStorage.getItem("deviceId");

+ 36 - 38
src/features/Login/Login.vue

@@ -7,7 +7,7 @@
     <div class="content-wrapper">
       <h2 class="slogan">
         欢迎使用 <br />
-        ICE 内容管理系统
+        在线考试管理系统
       </h2>
       <div class="form-container">
         <h4 class="form-title">登录</h4>
@@ -48,13 +48,22 @@
                 </el-form-item>
               </el-col>
             </el-row>
-            <el-row class="form-item">
+            <el-row class="form-item error-info">
               <el-col>
                 <el-form-item>
-                  <el-checkbox class="checkbox">记住账号</el-checkbox>
+                  <div v-show="user.errorInfo">
+                    {{ user.errorInfo }}
+                  </div>
                 </el-form-item>
               </el-col>
             </el-row>
+            <!-- <el-row class="form-item">
+              <el-col>
+                <el-form-item>
+                  <el-checkbox class="checkbox">记住账号</el-checkbox>
+                </el-form-item>
+              </el-col>
+            </el-row> -->
             <el-row class="form-item">
               <el-button
                 type="primary"
@@ -66,7 +75,7 @@
               </el-button>
             </el-row>
           </div>
-          <el-row class="tips">
+          <!-- <el-row class="tips">
             <a href="/" class="link">
               立即注册
             </a>
@@ -74,7 +83,7 @@
             <a href="/" class="link">
               忘记密码
             </a>
-          </el-row>
+          </el-row> -->
         </el-form>
       </div>
     </div>
@@ -94,46 +103,30 @@ export default {
       user: {
         username: "",
         password: "",
+        errorInfo: "",
       },
     };
   },
-  created() {},
   methods: {
     async submitBtn() {
-      const CryptoJS = require("crypto-js");
-
-      const AES = (content) => {
-        const KEY = "1234567890123456";
-        const IV = "1234567890123456";
-        // const key = CryptoJS.enc.Utf8.parse("1234567890123456");
-        // console.log(key);
-        // const key = "1234567890123456";
-        console.log(content);
-
-        var key = CryptoJS.enc.Utf8.parse(KEY);
-        var iv = CryptoJS.enc.Utf8.parse(IV);
-        var encrypted = CryptoJS.AES.encrypt(content, key, { iv: iv });
-        return encrypted.toString();
-
-        // const enstr = CryptoJS.AES.encrypt(content + "", key, {
-        //   // mode: CryptoJS.mode.ECB,
-        //   // padding: CryptoJS.pad.Pkcs7,
-        // }).toString();
-
-        // return enstr;
-      };
-
       this.$refs["form"].validate(async (valid) => {
         if (valid) {
-          const res = await this.$http.post("/api/admin/user/login/account", {
-            loginName: this.user.username,
-            password: AES(this.user.password),
-          });
-          console.log(res);
-          this.$message({
-            message: "登录成功",
-            type: "success",
-          });
+          try {
+            await this.$store.dispatch("LOGIN_BY_USERNAME", {
+              loginName: this.user.username,
+              password: this.user.password,
+              code: "test1",
+            });
+            // console.log(res);
+            // localStorage.setItem("themis-user", res.data);
+            this.$message({
+              message: "登录成功",
+              type: "success",
+            });
+          } catch (error) {
+            // console.log(error?.response?.data?.message);
+            this.user.errorInfo = error?.response?.data?.message || "";
+          }
         }
       });
     },
@@ -266,4 +259,9 @@ export default {
     }
   }
 }
+.error-info {
+  height: 30px;
+  overflow: hidden;
+  color: red;
+}
 </style>

+ 94 - 0
src/global.d.ts

@@ -0,0 +1,94 @@
+// Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~]
+// Project: [~THE PROJECT NAME~]
+// Definitions by: [~YOUR NAME~] <[~A URL FOR YOU~]>
+
+/*~ If this library is callable (e.g. can be invoked as myLib(3)),
+ *~ include those call signatures here.
+ *~ Otherwise, delete this section.
+ */
+// declare function myLib(a: string): string;
+// declare function myLib(a: number): number;
+
+// /*~ If you want the name of this library to be a valid type name,
+//  *~ you can do so here.
+//  *~
+//  *~ For example, this allows us to write 'var x: myLib';
+//  *~ Be sure this actually makes sense! If it doesn't, just
+//  *~ delete this declaration and add types inside the namespace below.
+//  */
+// interface myLib {
+//   name: string;
+//   length: number;
+//   extras?: string[];
+// }
+
+// /*~ If your library has properties exposed on a global variable,
+//  *~ place them here.
+//  *~ You should also place types (interfaces and type alias) here.
+//  */
+// declare namespace myLib {
+//   //~ We can write 'myLib.timeout = 50;'
+//   let timeout: number;
+
+//   //~ We can access 'myLib.version', but not change it
+//   const version: string;
+
+//   //~ There's some class we can create via 'let c = new myLib.Cat(42)'
+//   //~ Or reference e.g. 'function f(c: myLib.Cat) { ... }
+//   class Cat {
+//     constructor(n: number);
+
+//     //~ We can read 'c.age' from a 'Cat' instance
+//     readonly age: number;
+
+//     //~ We can invoke 'c.purr()' from a 'Cat' instance
+//     purr(): void;
+//   }
+
+//   //~ We can declare a variable as
+//   //~   'var s: myLib.CatSettings = { weight: 5, name: "Maru" };'
+//   interface CatSettings {
+//     weight: number;
+//     name: string;
+//     tailLength?: number;
+//   }
+
+//   //~ We can write 'const v: myLib.VetID = 42;'
+//   //~  or 'const v: myLib.VetID = "bob";'
+//   type VetID = string | number;
+
+//   //~ We can invoke 'myLib.checkCat(c)' or 'myLib.checkCat(c, v);'
+//   function checkCat(c: Cat, s?: VetID);
+// }
+
+import Vue from "vue";
+import { AxiosInstance } from "axios";
+
+// 可惜内部代码不能通过此类型推导
+//import * as api from "./api";
+
+declare module "vue/types/vue" {
+  interface Vue {
+    $http: AxiosInstance;
+    // $api: api;
+  }
+}
+// declare module "*.vue" {
+//   import Vue from "vue";
+//   export default Vue;
+//   interface Vue {
+//     $isLocalEnv: boolean;
+//   }
+// }
+
+// import Vue, { VueConstructor } from "vue";
+
+// declare module "vue/types/vue" {
+//   interface Vue {
+//     $ga: any;
+//   }
+
+//   interface VueConstructor {
+//     $ga: any;
+//   }
+// }

+ 22 - 21
src/plugins/axiosApp.js

@@ -1,11 +1,12 @@
 import Vue from "vue";
-import Store from "@/store";
+// import Store from "@/store";
 import axios from "axios";
 import { loadProgressBar } from "axios-progress-bar";
 import cachingGet from "./axiosCache";
 import { notifyInvalidTokenThrottled } from "./axiosNotice";
 import { getToken, removeToken } from "../auth/auth";
 import axiosRetry from "axios-retry";
+import { DEVICE_ID } from "@/constant/constants";
 
 const PLATFORM = "web";
 
@@ -23,33 +24,33 @@ const cacheGetUrls = [];
 const _axiosApp = axios.create(config);
 axiosRetry(_axiosApp);
 
-function gToken(uri, token) {
-  const now = Date.now();
-  // console.log(`${uri}&${now}&${token}`);
-  const a = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
-  let randomStr = "";
-  for (let i = 0; i < 6; i++) {
-    const idx = Math.round(Math.random() * 100) % a.length;
-    randomStr += a[idx];
-  }
+// function gToken(uri, token) {
+//   const now = Date.now();
+//   // console.log(`${uri}&${now}&${token}`);
+//   const a = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+//   let randomStr = "";
+//   for (let i = 0; i < 6; i++) {
+//     const idx = Math.round(Math.random() * 100) % a.length;
+//     randomStr += a[idx];
+//   }
 
-  const Authorization = `Token ${randomStr}${btoa(
-    uri + "&" + now + "&" + token
-  )}`;
+//   const Authorization = `Token ${randomStr}${btoa(
+//     uri + "&" + now + "&" + token
+//   )}`;
 
-  return Authorization;
-}
+//   return Authorization;
+// }
 
 _axiosApp.interceptors.request.use(
   function (config) {
     const wk_token = getToken();
     if (wk_token) {
-      config.headers.common["Authorization"] = gToken(config.url, wk_token);
-      config.headers.common["deviceId"] = Store.state.user.deviceId;
-      config.headers.common["domain"] = Store.state.user.domain;
+      // config.headers.common["Authorization"] = gToken(config.url, wk_token);
+      config.headers.common["Authorization"] = wk_token;
     }
     config.headers.common["platform"] = PLATFORM;
-    config.headers.common["deviceId"] = Store.state.user.deviceId;
+    config.headers.common["deviceId"] = DEVICE_ID;
+    config.headers.common["time"] = Date.now();
     return config;
   },
   function (error) {
@@ -105,10 +106,10 @@ _axiosApp.interceptors.response.use(
 
     if (status != 200) {
       const data = error.response.data;
-      if (data && data.desc) {
+      if (data && data.message) {
         Vue.prototype.$notify({
           showClose: true,
-          message: data.desc,
+          message: data.message,
           type: "error",
         });
       } else {

+ 2 - 2
src/plugins/axiosIndex.js

@@ -1,2 +1,2 @@
-export { default as httpApp } from "./axiosApp";
-export { default as httpNoAuth } from "./axiosNoAuth";
+export { httpApp } from "./axiosApp";
+export { httpNoAuth } from "./axiosNoAuth";

+ 0 - 241
src/samples/Login_01/Login_01.vue

@@ -1,241 +0,0 @@
-<template>
-  <div class="user-login">
-    <div
-      class="user-login-bg"
-      :style="{ 'background-image': `url(${backgroundImage})` }"
-    ></div>
-    <div class="content-wrapper">
-      <h2 class="slogan">
-        欢迎使用 <br />
-        ICE 内容管理系统
-      </h2>
-      <div class="form-container">
-        <h4 class="form-title">登录</h4>
-        <el-form ref="form" :model="user" label-width="0">
-          <div class="form-items">
-            <el-row class="form-item">
-              <el-col>
-                <el-form-item
-                  prop="username"
-                  :rules="[
-                    { required: true, message: '会员名/邮箱/手机号不能为空' },
-                  ]"
-                >
-                  <div class="form-line">
-                    <i class="el-icon-user input-icon"></i>
-                    <el-input
-                      placeholder="会员名/邮箱/手机号"
-                      v-model="user.username"
-                    ></el-input>
-                  </div>
-                </el-form-item>
-              </el-col>
-            </el-row>
-            <el-row class="form-item">
-              <el-col>
-                <el-form-item
-                  prop="password"
-                  :rules="[{ required: true, message: '密码不能为空' }]"
-                >
-                  <div class="form-line">
-                    <i class="el-icon-lock input-icon"></i>
-                    <el-input
-                      type="password"
-                      placeholder="密码"
-                      v-model="user.password"
-                    ></el-input>
-                  </div>
-                </el-form-item>
-              </el-col>
-            </el-row>
-            <el-row class="form-item">
-              <el-col>
-                <el-form-item>
-                  <el-checkbox class="checkbox">记住账号</el-checkbox>
-                </el-form-item>
-              </el-col>
-            </el-row>
-            <el-row class="form-item">
-              <el-button
-                type="primary"
-                class="submit-btn"
-                size="small"
-                @click="submitBtn"
-              >
-                登 录
-              </el-button>
-            </el-row>
-          </div>
-          <el-row class="tips">
-            <a href="/" class="link">
-              立即注册
-            </a>
-            <span class="line">|</span>
-            <a href="/" class="link">
-              忘记密码
-            </a>
-          </el-row>
-        </el-form>
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-// import BasicContainer from "@/samples/BasicContainer/BasicContainer";
-const backgroundImage =
-  "https://img.alicdn.com/tfs/TB1zsNhXTtYBeNjy1XdXXXXyVXa-2252-1500.png";
-export default {
-  // components: { BasicContainer },
-  name: "Login_01",
-  data() {
-    return {
-      backgroundImage: backgroundImage,
-      user: {
-        username: "",
-        password: "",
-      },
-    };
-  },
-  created() {},
-  methods: {
-    submitBtn() {
-      this.$refs["form"].validate((valid) => {
-        if (valid) {
-          this.$message({
-            message: "登录成功",
-            type: "success",
-          });
-        }
-      });
-    },
-  },
-};
-</script>
-
-<style lang="scss" scoped>
-.user-login {
-  .user-login-bg {
-    position: absolute;
-    top: 0;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    background-size: cover;
-  }
-  .el-checkbox__label {
-    color: #999;
-    font-size: 13px;
-  }
-  .content-wrapper {
-    position: absolute;
-    top: -100px;
-    left: 0;
-    right: 0;
-    bottom: 0;
-    max-width: 1080px;
-    margin: 0 auto;
-    display: flex;
-    justify-content: space-around;
-    align-items: center;
-    .slogan {
-      text-align: center;
-      color: blue;
-      font-size: 36px;
-      letter-spacing: 2px;
-      line-height: 48px;
-    }
-  }
-  .form-container {
-    display: flex;
-    justify-content: center;
-    flex-direction: column;
-    padding: 30px 40px;
-    background-color: #fff;
-    border-radius: 6px;
-    box-shadow: 1px 1px 2px #eee;
-  }
-  .el-form-item {
-    margin-bottom: 15px;
-  }
-  .form-Item {
-    position: relative;
-    flex-direction: column;
-  }
-  .form-line {
-    position: relative;
-    display: flex;
-    align-items: center;
-    &:after {
-      content: "";
-      position: absolute;
-      bottom: 3px;
-      left: 0;
-      width: 100%;
-      box-sizing: border-box;
-      border-width: 1px;
-      border-style: solid;
-      border-top: 0;
-      border-left: 0;
-      border-right: 0;
-      border-color: #dcdcdc;
-      border-radius: 0;
-    }
-  }
-  .el-input {
-    width: 240px;
-    // FIXME: 此处css没有生效
-    input {
-      border: none;
-      margin: 0;
-      padding-left: 10px;
-      font-size: 13px;
-    }
-  }
-  .form-title {
-    margin: 0 0 20px;
-    text-align: center;
-    color: #3080fe;
-    letter-spacing: 12px;
-  }
-  .input-icon {
-    color: #999;
-  }
-  .checkbox {
-    margin-left: 5px;
-  }
-  .submit-btn {
-    margin-bottom: 25px;
-    width: 100%;
-    background: #3080fe;
-    border-radius: 28px;
-  }
-  .tips {
-  }
-  .link {
-    color: #999;
-    text-decoration: none;
-    font-size: 13px;
-  }
-  .line {
-    color: #dcd6d6;
-    margin: 0 8px;
-  }
-}
-
-@media screen and (max-width: 720px) {
-  .user-login {
-    .content-wrapper {
-      margin: 20px auto;
-      top: 40px;
-      max-width: 300px;
-      display: block;
-      .slogan {
-        color: #666;
-        font-size: 22px;
-        line-height: 30px;
-      }
-    }
-  }
-}
-</style>

+ 5 - 19
src/store/modules/user.js

@@ -1,9 +1,8 @@
-import { loginByUsername, loginByPhone, sendSMS, logout } from "@/api/login";
+import { loginByUsername, logout } from "@/api/login";
 // import { removeKeyToken, setKeyToken } from "@/auth/auth";
 import { omit } from "lodash-es";
-import { LOGIN_BY_USERNAME, LOGIN_BY_PHONE, SEND_SMS } from "../action-types";
-
-const DEVICE_ID = Math.random() + "-" + Date.now();
+import { LOGIN_BY_USERNAME } from "../action-types";
+import { setToken } from "@/auth/auth";
 
 const user = {
   state: {
@@ -14,7 +13,6 @@ const user = {
     partitionId: null,
     roleList: null,
     smsSendDate: null,
-    deviceId: DEVICE_ID,
   },
 
   mutations: {
@@ -35,20 +33,8 @@ const user = {
     [LOGIN_BY_USERNAME]({ commit }, userInfo) {
       return loginByUsername(userInfo).then((response) => {
         const data = response.data;
-        commit("SET_USER", omit(data.accessAdminUser, ["token", "uid"]));
-        // setKeyToken(response.data.accessAdminUser);
-      });
-    },
-    [LOGIN_BY_PHONE]({ commit }, userInfo) {
-      return loginByPhone(userInfo).then((response) => {
-        const data = response.data;
-        commit("SET_USER", omit(data.accessAdminUser, ["token", "uid"]));
-        // setKeyToken(response.data.accessAdminUser);
-      });
-    },
-    [SEND_SMS]({ commit }, userInfo) {
-      return sendSMS(userInfo).then(() => {
-        commit("SET_SMS_SEND_DATE", Date.now());
+        commit("SET_USER", omit(data.account, ["token", "uid"]));
+        setToken(data.accessToken);
       });
     },
 

+ 2 - 1
vue.config.js

@@ -1,6 +1,7 @@
 let proxy = {
   "/api": {
-    target: "http://192.168.10.36:6001/backend",
+    target: "http://192.168.10.36:6001/",
+    // target: "http://192.168.11.224:6001/backend",
     changeOrigin: true,
   },
 };