Browse Source

答题链接简易登录页

dusenyao 1 year ago
parent
commit
ce83af4705

+ 6 - 0
package-lock.json

@@ -2105,6 +2105,12 @@
       "integrity": "sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ==",
       "dev": true
     },
+    "@types/md5": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmmirror.com/@types/md5/-/md5-2.3.5.tgz",
+      "integrity": "sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw==",
+      "dev": true
+    },
     "@types/mime": {
       "version": "1.3.3",
       "resolved": "https://registry.npmmirror.com/@types/mime/-/mime-1.3.3.tgz",

+ 1 - 0
package.json

@@ -30,6 +30,7 @@
     "@babel/core": "^7.23.5",
     "@babel/eslint-parser": "^7.23.3",
     "@rushstack/eslint-patch": "^1.6.0",
+    "@types/md5": "^2.3.5",
     "@vue/cli-plugin-babel": "~5.0.8",
     "@vue/cli-plugin-eslint": "~5.0.8",
     "@vue/cli-service": "~5.0.8",

+ 3 - 3
src/utils/http.js

@@ -61,11 +61,11 @@ service.interceptors.response.use(
       if (match && match.length > 1) {
         extractedString = match[1];
       }
+      // 答题链接特殊处理
       if (extractedString === 'open/share/exercise') {
-        window.location.href = `/#/login?temporary_link=${encodeURIComponent(`GCLS-Exercise/${window.location.hash}`)}`;
-      } else {
-        window.location.href = '/';
+        return Promise.reject(new Error(`${error}` || 'Error'));
       }
+      window.location.href = '/';
     }
 
     return res;

+ 20 - 0
src/views/exercise_questions/create/components/exercises/SelectQuestion.vue

@@ -99,6 +99,26 @@
             {{ label }}
           </el-radio>
         </el-form-item>
+        <el-form-item label="选项细分">
+          <el-radio
+            v-for="{ value, label } in switchOption"
+            :key="value"
+            v-model="data.property.is_option_subdivision"
+            :label="value"
+            @input="changeSelectType"
+          >
+            {{ label }}
+          </el-radio>
+        </el-form-item>
+        <el-form-item label-width="72px">
+          <el-input-number
+            v-model="data.property.option_number"
+            :min="2"
+            :max="5"
+            :step="1"
+            :disabled="!isEnable(data.property.is_option_subdivision)"
+          />
+        </el-form-item>
         <el-form-item label="听力">
           <el-radio
             v-for="{ value, label } in switchOption"

+ 1 - 0
src/views/login/index.vue

@@ -127,6 +127,7 @@ export default {
 
         .el-image {
           height: 30px;
+          vertical-align: bottom;
           cursor: pointer;
         }
       }

+ 223 - 15
src/views/share/ShareExercise.vue

@@ -1,26 +1,96 @@
 <template>
-  <h1></h1>
+  <div v-show="showLogin" class="share-exercise">
+    <div class="login">
+      <div class="login-type">
+        <div :class="['login-type-item', { active: 'TEACHER' === form.user_type }]" @click="form.user_type = 'TEACHER'">
+          教师
+        </div>
+        <div :class="['login-type-item', { active: 'STUDENT' === form.user_type }]" @click="form.user_type = 'STUDENT'">
+          学生
+        </div>
+      </div>
+      <el-form ref="loginForm" :model="form" :rules="rules" label-position="right">
+        <el-form-item prop="user_name">
+          <el-input v-model="form.user_name" />
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input v-model="form.password" type="password" show-password />
+        </el-form-item>
+        <el-form-item prop="verification_code_image_text" class="verification-code">
+          <el-input v-model="form.verification_code_image_text" placeholder="验证码" @keyup.enter.native="signIn" />
+          <el-image
+            v-if="image_content_base64.length > 0"
+            :src="`data:image/jpg;base64,${image_content_base64}`"
+            @click="updateVerificationCode"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button class="submit" type="primary" @click="signIn">登录</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="tip">{{ tip }}</div>
+  </div>
 </template>
 
 <script>
-import { GetShareRecordInfo } from '@/api/exercise';
-import { setItem } from '@/utils/storage';
+import { GetShareRecordInfo, PageQueryExerciseList } from '@/api/exercise';
+import md5 from 'md5';
+import { GetVerificationCodeImage, GetLogo } from '@/api/app';
+import { setConfig } from '@/utils/auth';
 
 export default {
   name: 'ShareExercise',
 
   data() {
     const { query } = this.$route;
-    const { share_record_id, answer_record_id, exercise_id, question_index } = query;
+    const { share_record_id } = query;
 
     return {
       query,
       share_record_id,
-      answer_record_id: answer_record_id || '',
-      question_index: question_index || -1,
-      exercise_id: exercise_id || '',
+      share_record: {
+        access_popedom: -1,
+        exercise_id: '',
+      },
+      showLogin: false,
+      // 登录表单
+      form: {
+        user_type: 'STUDENT',
+        user_name: '',
+        password: '',
+        is_password_md5: 'true',
+        verification_code_image_id: '',
+        verification_code_image_text: '',
+      },
+      rules: {
+        user_name: [
+          {
+            required: true,
+            message: '请输入用户名',
+            trigger: 'blur',
+          },
+        ],
+        password: [
+          {
+            required: true,
+            message: '请输入密码',
+            trigger: 'blur',
+          },
+        ],
+        verification_code_image_text: [{ required: true, trigger: 'blur', message: '验证码不能为空' }],
+      },
+      image_content_base64: '',
     };
   },
+  computed: {
+    tip() {
+      if (this.share_record.access_popedom === -1) return '正在加载...';
+      return this.share_record.access_popedom === 1
+        ? '分享链接为练习题答题链接,登录后可以开始答题'
+        : '分享链接为练习题编辑链接,登录后可以开始编辑练习题';
+    },
+  },
   created() {
     let info = navigator.userAgent;
     // 通过正则表达式的test方法判断是否包含“Mobile”字符串
@@ -38,18 +108,156 @@ export default {
         share_record_id: this.share_record_id,
       })
         .then(({ share_record }) => {
-          if (share_record.access_popedom === 1) {
-            this.$router.push({ path: '/exercise', query: { id: share_record.exercise_id } });
-          }
-          if (share_record.access_popedom === 2) {
-            this.$router.push({
-              path: '/answer',
-              query: this.query,
+          this.share_record = share_record;
+        })
+        .then(() => {
+          PageQueryExerciseList({ page_capacity: 0, cur_page: 1, store_type: 0, search_content: '' })
+            .then(() => {
+              this.exerciseLink();
+            })
+            .catch(() => {
+              this.updateVerificationCode();
+              this.getLogo();
+              this.showLogin = true;
             });
-          }
         })
         .catch(() => {});
     },
+
+    exerciseLink() {
+      // 1. 教师在没有权限的情况下,不能访问编辑练习题
+      // 2. 学生不能访问编辑练习题
+      if (
+        (!this.$store.state.user.popedom_code_list.includes(2000007) &&
+          this.form.user_type === 'TEACHER' &&
+          this.share_record.access_popedom === 1) ||
+        (this.form.user_type === 'STUDENT' && this.share_record.access_popedom === 1)
+      ) {
+        this.$message.error('您没有权限访问该页面');
+        return;
+      }
+      if (this.share_record.access_popedom === 1) {
+        this.$router.push({ path: '/exercise', query: { id: this.share_record.exercise_id } });
+      }
+      if (this.share_record.access_popedom === 2) {
+        this.$router.push({
+          path: '/answer',
+          query: this.query,
+        });
+      }
+    },
+
+    updateVerificationCode() {
+      GetVerificationCodeImage().then(({ image_id, image_content_base64: image }) => {
+        this.form.verification_code_image_id = image_id;
+        this.image_content_base64 = image;
+      });
+    },
+
+    getLogo() {
+      GetLogo().then((res) => {
+        setConfig(res);
+      });
+    },
+
+    signIn() {
+      this.$refs.loginForm.validate((valid) => {
+        if (!valid) return false;
+
+        let _form = { ...this.form, password: md5(this.form.password).toUpperCase() };
+        this.$store
+          .dispatch('user/login', _form)
+          .then(() => {
+            this.exerciseLink();
+          })
+          .catch(() => {
+            this.updateVerificationCode();
+          });
+      });
+    },
   },
 };
 </script>
+
+<style lang="scss" scoped>
+.share-exercise {
+  width: 100%;
+  height: 100%;
+  padding-top: 20%;
+  background-color: $content-color;
+
+  .login {
+    width: 50vw;
+    max-width: 1200px;
+    padding: 24px;
+    margin: auto;
+    background-color: #f0f0f0;
+    border: $border;
+    border-radius: 4px;
+
+    &-type {
+      display: flex;
+      align-items: center;
+      justify-content: center;
+      width: 400px;
+      padding: 2px;
+      margin: 0 auto;
+      margin-bottom: 12px;
+      background-color: #fafafa;
+      border-radius: 4px;
+
+      &-item {
+        width: 200px;
+        height: 36px;
+        line-height: 36px;
+        color: $text-color;
+        text-align: center;
+        cursor: pointer;
+
+        &.active {
+          color: $main-color;
+          background-color: $fill-color;
+          border-radius: 4px;
+          box-shadow: 0 2px 8px rgba(0, 0, 0, 10%);
+        }
+      }
+    }
+
+    :deep(.el-form) {
+      max-width: 400px;
+      margin: 0 auto;
+
+      .verification-code {
+        .el-input {
+          width: calc(100% - 90px);
+          margin-right: 10px;
+
+          &__inner {
+            background-color: #fff;
+          }
+        }
+
+        .el-image {
+          height: 30px;
+          vertical-align: bottom;
+          cursor: pointer;
+        }
+      }
+
+      .submit {
+        width: 100%;
+      }
+    }
+  }
+
+  .tip {
+    width: 100%;
+    padding: 8px 0;
+    margin-top: 40px;
+    text-align: center;
+    background-color: #fff;
+    border-top: $border;
+    border-bottom: $border;
+  }
+}
+</style>