刘洋 1 år sedan
förälder
incheckning
20b240cb10

+ 5 - 1
src/App.vue

@@ -1,5 +1,9 @@
 <template>
-  <router-view />
+  <router-view v-slot="{ Component }">
+    <transition name="zoom-fade" mode="out-in" appear>
+      <component :is="Component" />
+    </transition>
+  </router-view>
 </template>
 <script setup name="App">
 import { getUrlParam } from "./utils";

BIN
src/assets/imgs/apply_fail.png


BIN
src/assets/imgs/apply_success.png


BIN
src/assets/imgs/sys_disabled.png


+ 20 - 45
src/assets/styles/main.css

@@ -1,41 +1,3 @@
-/* 动画 */
-@keyframes ani-breathing {
-  from {
-    transform: scale(0.85);
-  }
-  to {
-    transform: scale(1);
-  }
-}
-@keyframes ani-move-to-right {
-  0%,
-  50% {
-    left: -100%;
-  }
-  100% {
-    left: 100%;
-  }
-}
-@keyframes ani-cursor {
-  0% {
-    opacity: 0;
-  }
-  100% {
-    opacity: 1;
-  }
-}
-/* 呼吸按钮 */
-.ani-breathing {
-  animation: ani-breathing 0.6s ease-out alternate infinite;
-}
-/* 高光动画 */
-.ani-move-to-right {
-  animation: ani-move-to-right 2s ease-out infinite;
-}
-/** 自定义光标闪烁 **/
-.ani-cursor {
-  animation: ani-cursor 0.5s linear alternate infinite;
-}
 @font-face {
   font-family: "DIN-Bold";
   src: url("/fonts/din-bold.otf");
@@ -44,17 +6,10 @@
   font-family: "DIN-Regular";
   src: url("/fonts/din-regular.otf");
 }
-@font-face {
-  font-family: "DIN-Black";
-  src: url("/fonts/DIN-Black.otf");
-}
 /* 字体名称 */
 .ff-DIN-Bold {
   font-family: "DIN-Bold";
 }
-.ff-DIN-Black {
-  font-family: "DIN-Black";
-}
 .ff-DIN-Regular {
   font-family: "DIN-Regular";
 }
@@ -86,6 +41,26 @@
   height: 100vh;
   background-color: #f0f0f0;
 }
+.cus-btn {
+  border-radius: 8px;
+  background-color: #fff;
+  height: 44px;
+  margin-top: 36px;
+  color: #00b42a;
+  font-weight: bold;
+  display: inline-flex;
+  justify-content: center;
+  align-items: center;
+  padding: 0 32px;
+}
+.cus-btn:active {
+  background-color: #f8f8f8;
+}
+.cus-btn.default {
+  background-color: #f0f0f0;
+  border: 1px solid #d9d9d9;
+  color: #262626;
+}
 /* 公共样式 */
 * {
   touch-action: pan-y;

+ 22 - 47
src/assets/styles/main.less

@@ -1,42 +1,3 @@
-/* 动画 */
-@keyframes ani-breathing {
-  from {
-    transform: scale(0.85);
-  }
-  to {
-    transform: scale(1);
-  }
-}
-@keyframes ani-move-to-right {
-  0%,
-  50% {
-    left: -100%;
-  }
-  100% {
-    left: 100%;
-  }
-}
-@keyframes ani-cursor {
-  0% {
-    opacity: 0;
-  }
-  100% {
-    opacity: 1;
-  }
-}
-/* 呼吸按钮 */
-.ani-breathing {
-  animation: ani-breathing 0.6s ease-out alternate infinite;
-}
-/* 高光动画 */
-.ani-move-to-right {
-  animation: ani-move-to-right 2s ease-out infinite;
-}
-/** 自定义光标闪烁 **/
-.ani-cursor {
-  animation: ani-cursor 0.5s linear alternate infinite;
-}
-
 @font-face {
   font-family: "DIN-Bold";
   src: url("/fonts/din-bold.otf");
@@ -45,17 +6,12 @@
   font-family: "DIN-Regular";
   src: url("/fonts/din-regular.otf");
 }
-@font-face {
-  font-family: "DIN-Black";
-  src: url("/fonts/DIN-Black.otf");
-}
+
 /* 字体名称 */
 .ff-DIN-Bold {
   font-family: "DIN-Bold";
 }
-.ff-DIN-Black {
-  font-family: "DIN-Black";
-}
+
 .ff-DIN-Regular {
   font-family: "DIN-Regular";
 }
@@ -89,7 +45,26 @@
     background-color: #f0f0f0;
   }
 }
-
+.cus-btn {
+  border-radius: 8px;
+  background-color: #fff;
+  height: 44px;
+  margin-top: 36px;
+  color: #00b42a;
+  font-weight: bold;
+  display: inline-flex;
+  justify-content: center;
+  align-items: center;
+  padding: 0 32px;
+  &:active {
+    background-color: #f8f8f8;
+  }
+  &.default {
+    background-color: #f0f0f0;
+    border: 1px solid #d9d9d9;
+    color: #262626;
+  }
+}
 /* 公共样式 */
 * {
   touch-action: pan-y;

+ 12 - 3
src/components/noData.vue

@@ -1,7 +1,10 @@
 <template>
   <div class="no-data">
     <slot name="img" />
-    <p>
+    <p class="title">
+      <slot name="title" />
+    </p>
+    <p class="txt">
       <slot />
     </p>
   </div>
@@ -12,10 +15,16 @@
   text-align: center;
   :deep(img) {
     width: 62px;
+    margin-bottom: 5px;
+  }
+  .title {
+    font-size: 16px;
+    font-weight: bold;
+    line-height: 24px;
   }
-  p {
+  .txt {
     color: #8c8c8c;
-    margin-top: 8px;
+    margin-top: 5px;
   }
 }
 </style>

+ 45 - 0
src/pages/applyResult.vue

@@ -0,0 +1,45 @@
+<template>
+  <div class="apply-result vh-100 flex-h-center">
+    <div>
+      <NoData>
+        <template #img>
+          <img
+            v-if="route.query?.status === 'success'"
+            src="../assets/imgs/apply_success.png"
+          />
+          <img v-else src="../assets/imgs/apply_fail.png" />
+        </template>
+        <template #title>
+          预约{{ route.query?.status === "success" ? "成功" : "失败" }}!
+        </template>
+        <span v-if="route.query?.status === 'fail'">当前时段已约满</span>
+      </NoData>
+      <div class="btn-box d-flex align-items-center">
+        <div class="cus-btn flex-h-center" @click="continueApply">继续预约</div>
+        <div
+          class="cus-btn default flex-h-center ml-20"
+          @click="seeOrders"
+          v-if="route.query?.status === 'success'"
+        >
+          查看订单
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+<script name="ApplyResult" setup>
+import { useRoute, useRouter } from "vue-router";
+const route = useRoute();
+const router = useRouter();
+const continueApply = () => {
+  router.back();
+};
+const seeOrders = () => {
+  router.push({ name: "MyHistory" });
+};
+</script>
+<style lang="less" scoped>
+.apply-result {
+  background: #f0f0f0;
+}
+</style>

+ 57 - 32
src/pages/login.vue

@@ -1,36 +1,50 @@
 <template>
   <div class="login">
-    <div class="title">{{ appStore.globalConfig.orgTitle }}</div>
-    <div class="sub-title">{{ appStore.globalConfig.taskTitle }}</div>
-    <van-form @submit="onSubmit" class="login-form">
-      <van-cell-group inset>
-        <van-field
-          v-model="account"
-          name="学号"
-          label=""
-          placeholder="请输入学号"
-          clearable
-          label-width="0px"
-          :rules="[{ required: true, message: '请输入学号' }]"
-        />
-        <van-field
-          v-model="password"
-          :type="passwordShow ? 'text' : 'password'"
-          name="密码"
-          label=""
-          placeholder="请输入证件号后六位"
-          :right-icon="passwordShow ? 'closed-eye' : 'eye-o'"
-          @click-right-icon="passwordShow = !passwordShow"
-          label-width="0px"
-          :rules="[{ required: true, message: '请输入证件号后六位' }]"
-        />
-        <div style="margin: 16px">
-          <van-button block type="success" native-type="submit">
-            提交
-          </van-button>
-        </div>
-      </van-cell-group>
-    </van-form>
+    <div v-if="!appStore.globalConfig.taskTitle" class="sys-disabled">
+      <div class="text-center">
+        <NoData>
+          <template #img>
+            <img src="../assets/imgs/sys_disabled.png" />
+          </template>
+          <template #title>{{ appStore.globalConfig.orgTitle }}</template>
+          当前预约系统未开放</NoData
+        >
+        <div class="cus-btn" @click="exit">退出</div>
+      </div>
+    </div>
+    <template v-else>
+      <div class="title">{{ appStore.globalConfig.orgTitle }}</div>
+      <div class="sub-title">{{ appStore.globalConfig.taskTitle }}</div>
+      <van-form @submit="onSubmit" class="login-form">
+        <van-cell-group inset>
+          <van-field
+            v-model="account"
+            name="学号"
+            label=""
+            placeholder="请输入学号"
+            clearable
+            label-width="0px"
+            :rules="[{ required: true, message: '请输入学号' }]"
+          />
+          <van-field
+            v-model="password"
+            :type="passwordShow ? 'text' : 'password'"
+            name="密码"
+            label=""
+            placeholder="请输入证件号后六位"
+            :right-icon="passwordShow ? 'closed-eye' : 'eye-o'"
+            @click-right-icon="passwordShow = !passwordShow"
+            label-width="0px"
+            :rules="[{ required: true, message: '请输入证件号后六位' }]"
+          />
+          <div style="margin: 16px">
+            <van-button block type="success" native-type="submit">
+              提交
+            </van-button>
+          </div>
+        </van-cell-group>
+      </van-form>
+    </template>
   </div>
 </template>
 <script name="Login" setup>
@@ -52,17 +66,28 @@ const onSubmit = () => {
     }
   });
 };
+const exit = () => {
+  window.location.href = "about:blank";
+  window.close();
+};
 </script>
 <style lang="less" scoped>
 .login {
   background-color: #fff !important;
   height: 100vh;
-  padding-top: 48px;
+  .sys-disabled {
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background: #f0f0f0;
+  }
   .title {
     font-size: 24px;
     font-weight: 600;
     color: #262626;
     padding-left: 24px;
+    padding-top: 48px;
   }
   .sub-title {
     font-size: 16px;

+ 1 - 12
src/pages/tab-pages/index.vue

@@ -9,7 +9,7 @@
         :key="item.applyId"
       ></ApplyItem>
     </template>
-    <div class="vh-100 flex-h-center" v-else>
+    <div class="vh-100 text-center" v-else>
       <div>
         <NoData>
           <template #img>
@@ -49,16 +49,5 @@ function toReservation() {
 </script>
 <style lang="less" scoped>
 .index {
-  .cus-btn {
-    border-radius: 8px;
-    background-color: #fff;
-    height: 44px;
-    margin-top: 36px;
-    color: #00b42a;
-    font-weight: bold;
-    &:active {
-      background-color: #f8f8f8;
-    }
-  }
 }
 </style>

+ 8 - 3
src/pages/tab-pages/reservation.vue

@@ -272,9 +272,14 @@ function reservationHandle(item) {
     reservationSave({
       examSiteId: params.examSiteId.value,
       timePeriodId: item.timePeriodId,
-    }).then(() => {
-      showSuccessToast("预约成功");
-    });
+    })
+      .then(() => {
+        // showSuccessToast("预约成功");
+        router.push({ name: "ApplyResult", query: { status: "success" } });
+      })
+      .catch(() => {
+        router.push({ name: "ApplyResult", query: { status: "fail" } });
+      });
   });
 }
 

+ 7 - 0
src/router/index.js

@@ -20,6 +20,13 @@ const router = createRouter({
 const whiteList = ["Login", "WxLogin"];
 router.beforeEach(async (to, from, next) => {
   const appStore = useAppStore();
+  if (!appStore.globalConfig) {
+    let config = await appStore.getGlobalConfig();
+    if (config && !config?.taskTitle) {
+      next({ name: "Login", replace: true });
+      return;
+    }
+  }
   if (to.meta.jsApiList) {
     await LibForWeixin.initJSSDK(to.meta.jsApiList)
       .then(() => {

+ 6 - 0
src/router/routes.js

@@ -55,6 +55,12 @@ const routes = [
     component: () => import("@/pages/myHistory.vue"),
     meta: { title: "预约订单" },
   },
+  {
+    path: "/applyResult",
+    name: "ApplyResult",
+    component: () => import("@/pages/applyResult.vue"),
+    meta: { title: "预约结果" },
+  },
   {
     path: "/404",
     name: "NotFound",

+ 8 - 7
src/store/modules/app.js

@@ -3,15 +3,16 @@ import { getProperties } from "@/api/common";
 
 const useAppStore = defineStore("app", {
   state: () => ({
-    globalConfig: {},
+    globalConfig: null,
   }),
   actions: {
-    getGlobalConfig() {
-      getProperties().then((res) => {
-        if (Object.prototype.toString.call(res) === "[object Object]") {
-          this.globalConfig = res;
-        }
-      });
+    async getGlobalConfig() {
+      let res = await getProperties().catch(() => {});
+      if (Object.prototype.toString.call(res) === "[object Object]") {
+        this.globalConfig = res;
+        return res;
+      }
+      return null;
     },
   },
 });