zhangjie před 1 rokem
rodič
revize
39444a323d

+ 6 - 5
package.json

@@ -13,10 +13,10 @@
     "format": "prettier .  --write"
   },
   "dependencies": {
-    "@ant-design/icons-vue": "^6.1.0",
+    "@ant-design/icons-vue": "^7.0.1",
     "@vueuse/core": "^7.6.0",
     "@vueuse/router": "^7.6.0",
-    "ant-design-vue": "^2.2.8",
+    "ant-design-vue": "^4.1.2",
     "axios": "^0.25.0",
     "axios-progress-bar": "^1.2.0",
     "axios-retry": "^3.2.4",
@@ -27,11 +27,11 @@
     "lodash-es": "^4.17.21",
     "mitt": "^3.0.0",
     "moment": "^2.29.1",
-    "pinia": "^2.0.11",
+    "pinia": "~2.0.11",
     "qs": "^6.10.3",
     "tailwindcss": "^3.0.19",
     "ua-parser-js": "^1.0.2",
-    "vue": "^3.2.30",
+    "vue": "~3.2.30",
     "vue-echarts": "^6.0.2",
     "vue-router": "^4.0.12"
   },
@@ -52,9 +52,10 @@
     "eslint": "^8.8.0",
     "eslint-config-prettier": "^8.3.0",
     "eslint-plugin-vue": "^8.4.1",
+    "less": "^4.2.0",
     "postcss": "^8.4.6",
     "typescript": "^4.5.5",
-    "unplugin-vue-components": "^0.17.18",
+    "unplugin-vue-components": "^0.26.0",
     "vite": "^2.8.0",
     "vue-eslint-parser": "^8.2.0",
     "vue-tsc": "^0.31.2"

+ 29 - 33
src/App.vue

@@ -1,47 +1,43 @@
 <template>
-  <router-view> </router-view>
-  <a-spin
-    v-if="spinning"
-    size="large"
-    :spinning="spinning"
-    :delay="1000"
-    class="global-mask fade-in"
-  />
-  <ExplainModal />
+  <a-config-provider :theme="theme">
+    <router-view> </router-view>
+    <a-spin
+      v-if="spinning"
+      size="large"
+      :spinning="spinning"
+      :delay="1000"
+      class="global-mask fade-in"
+    />
+    <ExplainModal />
+  </a-config-provider>
 </template>
 
-<script lang="ts">
-import { defineComponent, watch, watchEffect } from "vue";
+<script setup lang="ts">
+import { watch, watchEffect } from "vue";
 import { useMainStore } from "@/store";
 import { useTimers } from "./setups/useTimers";
 import { getToken } from "./auth/auth";
 import { httpApp } from "./plugins/axiosApp";
+import { theme } from "./theme";
 
-export default defineComponent({
-  name: "App",
-
-  setup() {
-    const { addInterval } = useTimers();
-    addInterval(() => {
-      if (getToken()) {
-        void httpApp.post("/api/ess/user/online/signal");
-      }
-    }, 60 * 1000);
+const { addInterval } = useTimers();
+addInterval(() => {
+  if (getToken()) {
+    void httpApp.post("/api/ess/user/online/signal");
+  }
+}, 60 * 1000);
 
-    let spinning = $ref(false);
-    const mainStore = useMainStore();
+let spinning = $ref(false);
+const mainStore = useMainStore();
 
-    watch(
-      () => mainStore.globalMask,
-      () => (spinning = mainStore.globalMask)
-    );
+watch(
+  () => mainStore.globalMask,
+  () => (spinning = mainStore.globalMask)
+);
 
-    watchEffect(() => {
-      const bodyScrollProp = spinning ? "hidden" : "auto";
-      document.body.style.overflow = bodyScrollProp;
-    });
-    return { spinning };
-  },
+watchEffect(() => {
+  const bodyScrollProp = spinning ? "hidden" : "auto";
+  document.body.style.overflow = bodyScrollProp;
 });
 </script>
 

binární
src/assets/bg-login-theme.jpg


binární
src/assets/bg-login-title.jpg


+ 57 - 49
src/features/login/Login.vue

@@ -1,31 +1,44 @@
 <template>
-  <div class="tw-h-screen tw-flex tw-justify-center tw-items-center">
-    <div class="tw-flex" style="width: 860px; height: 558px">
-      <div style="width: 400px" class="left-panel">
-        <div class="tw-text-2xl">欢迎登录,<br />考试成绩综合分析系统</div>
-        <div style="font-size: 12px">武汉启明泰和软件服务有限公司技术支持</div>
+  <div class="login login-home">
+    <div class="login-box">
+      <div class="login-theme">
+        <h1>研究生成绩分析</h1>
+        <p>Copyright ©启明泰和 Rights Reserved.</p>
       </div>
-
-      <div class="tw-bg-white" style="padding: 0 70px 0 90px">
-        <div style="padding: 80px 0"><img class="qm-logo-img" /></div>
-
-        <div style="width: 300px">
-          <a-form-item>
-            <a-input v-model:value="accountValue" placeholder="请输入用户名" />
-          </a-form-item>
-          <a-form-item>
-            <a-input-password
-              v-model:value="password"
-              placeholder="请输入密码"
-              @keypress.enter="login"
-            />
-          </a-form-item>
-
-          <div class="tw-text-red-500 tw-pb-4">
-            {{ errorInfo }}
-          </div>
-
-          <qm-button type="primary" @click="login">立即登录</qm-button>
+      <div class="login-body" @keyup.enter="submit">
+        <div class="login-title">
+          <h2>输入信息</h2>
+          <p>请输入账号与密码</p>
+        </div>
+        <div class="login-form">
+          <a-form ref="formRef" :model="formData" :rules="rules">
+            <a-form-item name="accountValue">
+              <a-input
+                v-model:value="formData.accountValue"
+                size="large"
+                placeholder="请输入你的账号"
+                allow-clear
+              />
+            </a-form-item>
+            <a-form-item name="password">
+              <a-input-password
+                v-model:value="formData.password"
+                placeholder="请输入你的密码"
+                size="large"
+                allow-clear
+              />
+            </a-form-item>
+            <a-form-item>
+              <a-button
+                type="primary"
+                size="large"
+                block
+                :loading="loading"
+                @click="submit"
+                >登录</a-button
+              >
+            </a-form-item>
+          </a-form>
         </div>
       </div>
     </div>
@@ -37,10 +50,11 @@ import { loginByUsername } from "@/api/loginPage";
 import { useRouteQuery } from "@vueuse/router";
 import { useRouter } from "vue-router";
 import { useMainStore } from "@/store";
+import { reactive } from "vue";
+import type { Rule } from "ant-design-vue/es/form";
+import type { FormInstance } from "ant-design-vue";
 const store = useMainStore();
 
-let accountValue = $ref("");
-let password = $ref("");
 let rootOrgId = $(useRouteQuery("rootOrgId"));
 const router = useRouter();
 if (!rootOrgId) {
@@ -48,12 +62,24 @@ if (!rootOrgId) {
 }
 
 let errorInfo = $ref("");
+let loading = $ref(false);
+const formRef = $ref<FormInstance>();
+const formData = reactive({
+  accountValue: "",
+  password: "",
+});
 
-async function login() {
+const rules: Record<string, Rule[]> = {
+  accountValue: [
+    { required: true, message: "请输入你的账号", trigger: "change" },
+  ],
+  password: [{ required: true, message: "请输入你的密码", trigger: "change" }],
+};
+async function submit() {
   try {
     const res = await loginByUsername({
-      accountValue,
-      password,
+      accountValue: formData.accountValue,
+      password: formData.password,
       rootOrgId: parseInt(rootOrgId?.toString() ?? "1"),
     });
     console.log(res);
@@ -69,21 +95,3 @@ async function login() {
   }
 }
 </script>
-
-<style scoped>
-.left-panel {
-  width: 400px;
-  padding: 58px 100px 30px 60px;
-  color: white;
-  background-image: url(./left.png);
-
-  display: flex;
-  flex-direction: column;
-  justify-content: space-between;
-}
-
-.qm-logo-img {
-  content: url(@/assets/qm-logo.png);
-  height: 120px;
-}
-</style>

+ 15 - 11
src/main.ts

@@ -5,23 +5,25 @@ if (!validUA) {
   );
   location.href = "about:blank";
 }
-// vite-plugin-components 不能引入message的style
-import "ant-design-vue/es/message/style/css.js";
 
-import "./styles/global.css";
+// import "./styles/tailwind.css";
+import "./styles/index.less";
 import "./features/report/assets/report.css";
+
 import { createApp } from "vue";
 import App from "./App.vue";
+// import Antd from "ant-design-vue";
+// import "ant-design-vue/dist/reset.css";
+
 import router from "@/router";
 import filters from "@/filters";
 import roundNumber from "@/directives/roundNumber";
 import numberToPercent from "@/directives/numberToPercent";
-// import Antd from "ant-design-vue";
-// import "ant-design-vue/dist/antd.css";
+
 import ECharts from "vue-echarts";
 import { use } from "echarts/core";
 
-import { CanvasRenderer,SVGRenderer } from "echarts/renderers";
+import { CanvasRenderer, SVGRenderer } from "echarts/renderers";
 import { LineChart, BarChart } from "echarts/charts";
 import {
   GridComponent,
@@ -30,10 +32,10 @@ import {
   LegendComponent,
   MarkLineComponent,
 } from "echarts/components";
-import { Table } from "ant-design-vue";
-[Table].forEach((element) => {
-  element.props.size.default = "small";
-});
+// import { Table } from "ant-design-vue";
+// [Table].forEach((element) => {
+//   element.props.size.default = "small";
+// });
 
 use([
   SVGRenderer,
@@ -43,7 +45,8 @@ use([
   GridComponent,
   TitleComponent,
   TooltipComponent,
-  LegendComponent,MarkLineComponent
+  LegendComponent,
+  MarkLineComponent,
 ]);
 
 import { createPinia } from "pinia";
@@ -58,5 +61,6 @@ app.config.globalProperties.$filters = filters;
 app.component("VChart", ECharts);
 app.directive("round-number", roundNumber);
 app.directive("number-to-percent", numberToPercent);
+// app.use(Antd);
 
 app.mount("#app");

+ 0 - 153
src/styles/global.css

@@ -1,153 +0,0 @@
-@import "./tailwind.css";
-@import "./nprogress.css";
-
-:root {
-  --header-bg-color: #191b37;
-  --app-container-bg-color: white;
-  --app-main-bg-color: #dee4f3;
-  --app-main-text-color: #283e76;
-  --app-secondary-text-color: #9193a1;
-  --app-min-width: 1280px;
-  --app-bold-text-color: #435488;
-  --app-small-header-text-color: #7584ac;
-  --app-score-color: #5d65ff;
-  --app-primary-button-bg-color: #5d65ff;
-  --app-ant-select-bg-override-color: #5d6d7d;
-  --app-undo-button-bg-color: #4ed885;
-
-  --app-main-font-size: 14px;
-  --app-secondary-font-size: 12px;
-  --app-title-font-size: 16px;
-}
-
-body {
-  margin: 0;
-  font-size: var(--app-main-font-size);
-  /* min-width: var(--app-min-width); */
-  background-color: var(--app-main-bg-color);
-  min-height: 600px;
-  user-select: none;
-}
-
-.main-text-color {
-  color: var(--app-main-text-color);
-}
-
-.secondary-text {
-  color: var(--app-small-header-text-color);
-  font-size: var(--app-secondary-font-size);
-}
-
-.ant-message {
-  z-index: 6001 !important;
-  font-size: 16px !important;
-}
-
-.ant-pagination-item-link span[role="img"],
-.ant-message-custom-content span[role="img"] {
-  vertical-align: 0.2em !important;
-}
-
-button.ant-btn {
-  height: 32px;
-  padding: 4px 16px;
-  font-size: 14px;
-  border-radius: 8px;
-}
-
-button.ant-btn span[role="img"] {
-  display: inline-flex !important;
-}
-
-button.ant-btn-primary {
-  background-color: var(--app-primary-button-bg-color);
-}
-
-button.ant-btn.query-btn {
-  background-color: #fe8398;
-  color: white;
-}
-
-button.ant-btn.download-tpl-btn {
-  background-color: #fe8398;
-  color: white;
-}
-
-.ant-select .ant-select-selector {
-  border-radius: 5px !important;
-}
-
-.ant-input-affix-wrapper {
-  border-radius: 5px !important;
-}
-
-.ant-input,
-.ant-input-number {
-  border-radius: 5px !important;
-}
-
-.ant-pagination li,
-.ant-pagination li a {
-  border-radius: 50% !important;
-}
-.ant-pagination .ant-pagination-item-active {
-  background-color: #4d66fd;
-}
-.ant-pagination .ant-pagination-item-active a {
-  color: white !important;
-}
-
-.ant-table-tbody td .ant-btn {
-  margin-right: 8px;
-}
-.ant-table-column-title {
-  font-weight: 500;
-  color: #7a7c85;
-}
-
-table.custom-table {
-  width: 100%;
-  border-collapse: collapse !important;
-  border-spacing: 0;
-  text-align: center;
-}
-.custom-table td {
-  border: 1px solid #eeeeee;
-  border-radius: 6px;
-  border-collapse: separate !important;
-  padding: 10px;
-}
-
-.section-title {
-  color: #212534;
-  font-size: 16px;
-  font-weight: 700;
-}
-
-/* 左侧菜单 */
-.ant-menu .ant-menu-title-content {
-  color: #212534;
-}
-.ant-menu .ant-menu-title-content a[class=""] {
-  color: #7a7c85;
-}
-
-/* modal 不要“取消按钮” */
-.ant-modal-content .ant-modal-footer button:first-child {
-  display: none;
-}
-
-.ant-popover-arrow {
-  border-top-color: #4c4e5c !important;
-  border-left-color: #4c4e5c !important;
-}
-.ant-popover-inner-content {
-  background: linear-gradient(180deg, #4c4e5c 0%, #3d404e 100%);
-  box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.3);
-  opacity: 0.98;
-  border-radius: 10px;
-  /* color: rgba(0, 0, 0, 0.3); */
-}
-.ant-select-clear {
-  margin-top: -8px !important;
-}

+ 88 - 0
src/styles/global.less

@@ -0,0 +1,88 @@
+@import "./var.less";
+@import "./reset.less";
+
+body {
+  margin: 0;
+  font-size: var(--app-main-font-size);
+  /* min-width: var(--app-min-width); */
+  background-color: var(--app-main-bg-color);
+  min-height: 600px;
+  user-select: none;
+}
+
+.main-text-color {
+  color: var(--app-main-text-color);
+}
+
+.secondary-text {
+  color: var(--app-small-header-text-color);
+  font-size: var(--app-secondary-font-size);
+}
+
+.ant-message {
+  z-index: 6001 !important;
+  font-size: 16px !important;
+}
+
+.ant-pagination-item-link span[role="img"],
+.ant-message-custom-content span[role="img"] {
+  vertical-align: 0.2em !important;
+}
+
+// button.ant-btn {
+//   height: 32px;
+//   padding: 4px 16px;
+//   font-size: 14px;
+//   border-radius: 8px;
+// }
+
+button.ant-btn span[role="img"] {
+  display: inline-flex !important;
+}
+
+// button.ant-btn-primary {
+//   background-color: var(--app-primary-button-bg-color);
+// }
+
+// button.ant-btn.query-btn {
+//   background-color: #fe8398;
+//   color: white;
+// }
+
+button.ant-btn.download-tpl-btn {
+  background-color: #fe8398;
+  color: white;
+}
+
+// .ant-select .ant-select-selector {
+//   border-radius: 5px !important;
+// }
+
+// .ant-input-affix-wrapper {
+//   border-radius: 5px !important;
+// }
+
+// .ant-input,
+// .ant-input-number {
+//   border-radius: 5px !important;
+// }
+
+/* modal 不要“取消按钮” */
+.ant-modal-content .ant-modal-footer button:first-child {
+  display: none;
+}
+
+.ant-popover-arrow {
+  border-top-color: #4c4e5c !important;
+  border-left-color: #4c4e5c !important;
+}
+.ant-popover-inner-content {
+  background: linear-gradient(180deg, #4c4e5c 0%, #3d404e 100%);
+  box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.3);
+  opacity: 0.98;
+  border-radius: 10px;
+  /* color: rgba(0, 0, 0, 0.3); */
+}
+.ant-select-clear {
+  margin-top: -8px !important;
+}

+ 0 - 0
src/styles/home.less


+ 6 - 0
src/styles/index.less

@@ -0,0 +1,6 @@
+@import "./global.less";
+@import "./nprogress.less";
+
+@import "./login.less";
+@import "./home.less";
+@import "./pages.less";

+ 113 - 0
src/styles/login.less

@@ -0,0 +1,113 @@
+/* login */
+.login-home {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  z-index: 8;
+  overflow: auto;
+  background-color: var(--color-background);
+}
+
+.login-footer {
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  padding: 10px;
+  color: var(--color-text-gray);
+  text-align: center;
+
+  a {
+    margin: 0 5px;
+
+    &:hover {
+      color: var(--color-primary);
+    }
+  }
+}
+
+.login-box {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 800px;
+  height: 500px;
+  transform: translate(-50%, -50%);
+  overflow: hidden;
+  border-radius: 30px;
+  background-color: #fff;
+}
+.login-theme {
+  width: 400px;
+  height: 100%;
+  border-radius: 20px;
+  background-image: url(../assets/bg-login-theme.jpg);
+  background-size: 100% 100%;
+  float: left;
+  position: relative;
+
+  > h1 {
+    position: absolute;
+    width: 100%;
+    top: 48px;
+    left: 48px;
+
+    font-weight: bold;
+    font-size: 22px;
+    color: var(--app-main-text-color);
+    line-height: 28px;
+    padding-left: 36px;
+
+    background-image: url(../assets/bg-login-title.jpg);
+    background-size: auto 100%;
+    background-repeat: no-repeat;
+  }
+
+  > p {
+    position: absolute;
+    height: 22px;
+    font-weight: 400;
+    font-size: 14px;
+    color: var(--app-secondary-text-color);
+    line-height: 22px;
+    left: 48px;
+    bottom: 48px;
+  }
+}
+.login-body {
+  margin-left: 400px;
+  height: 100%;
+  overflow: hidden;
+  padding: 126px 40px;
+}
+.login-title {
+  margin-bottom: 24px;
+  h2 {
+    height: 32px;
+    font-weight: bold;
+    font-size: 24px;
+    color: var(--app-main-text-color);
+    line-height: 32px;
+    margin-bottom: 4px;
+  }
+  p {
+    height: 28px;
+    font-weight: 400;
+    font-size: 16px;
+    color: var(--app-secondary-text-color);
+    line-height: 28px;
+  }
+}
+.login-form {
+  .login-submit-btn {
+    width: 100%;
+    height: 48px;
+    border-radius: 24px;
+    font-size: 18px;
+  }
+
+  .ant-form-item {
+    margin-bottom: 22px !important;
+  }
+}

+ 0 - 0
src/styles/nprogress.css → src/styles/nprogress.less


+ 0 - 0
src/styles/pages.less


+ 119 - 0
src/styles/reset.less

@@ -0,0 +1,119 @@
+/* reset */
+body,
+div,
+ul,
+ol,
+li,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+input,
+p,
+tr,
+th,
+td,
+span,
+a,
+header,
+footer,
+i {
+  box-sizing: border-box;
+  margin: 0;
+  padding: 0;
+  -webkit-tap-highlight-color: rgb(255 255 255);
+}
+
+em,
+i,
+u {
+  font-style: normal;
+}
+
+input {
+  font-family: var(--font-family);
+  background: rgba(245 245 245 1);
+  border: none;
+  outline: none;
+}
+
+input:-webkit-input-placeholder {
+  color: var(--color-text-gray-4);
+  font-weight: bold;
+  font-size: 12px;
+}
+
+button,
+textarea {
+  font-family: var(--font-family);
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+  font-size: 100%;
+}
+
+fieldset,
+img {
+  border: 0;
+}
+
+abbr {
+  font-variant: normal;
+  border: 0;
+}
+
+a {
+  color: inherit;
+  text-decoration: none;
+}
+
+img {
+  vertical-align: middle;
+}
+
+/* common-style */
+input:-webkit-autofill {
+  box-shadow: 0 0 0 1000px white inset;
+}
+
+input[type="text"]:focus,
+input[type="password"]:focus,
+input[type="number"]:focus,
+textarea:focus {
+  box-shadow: 0 0 0 1000px white inset;
+}
+
+/* browse style */
+::-webkit-scrollbar {
+  width: 8px;
+  height: 8px;
+  background: transparent;
+}
+
+::-webkit-scrollbar-button {
+  display: none;
+}
+
+::-webkit-scrollbar-track {
+  background: transparent;
+}
+
+::-webkit-scrollbar-thumb {
+  background: #666;
+  border-radius: 8px;
+}
+
+::-webkit-scrollbar-corner {
+  background: transparent;
+}
+
+::-webkit-scrollbar-resizer {
+  background: transparent;
+}

+ 39 - 0
src/styles/var.less

@@ -0,0 +1,39 @@
+:root {
+  --header-bg-color: #191b37;
+  --app-container-bg-color: white;
+  --app-main-bg-color: #f2f3f5;
+  --app-main-text-color: #262626;
+  --app-mid-text-color: #595959;
+  --app-secondary-text-color: #8c8c8c;
+  --app-min-width: 1280px;
+  --app-bold-text-color: #435488;
+  --app-small-header-text-color: #7584ac;
+  --app-score-color: #165dff;
+  --app-primary-button-bg-color: #165dff;
+  --app-ant-select-bg-override-color: #5d6d7d;
+  --app-undo-button-bg-color: #4ed885;
+
+  --app-main-font-size: 14px;
+  --app-secondary-font-size: 12px;
+  --app-title-font-size: 16px;
+
+  --color-border: #e5e5e5;
+  --color-background: #f2f3f5;
+
+  /* status */
+  --color-primary: #165dff;
+  --color-primary-light: #e8f3ff;
+  --color-success: #00b42a;
+  --color-success-light: #e8ffea;
+  --color-warning: #ff9427;
+  --color-danger: #f53f3f;
+  --color-danger-light: #ffece8;
+  --color-cyan: #2abcff;
+  --color-cyan-light: #5fc9fa;
+  --color-white: #fff;
+  --color-dark: #262626;
+
+  --border-radius: 4px;
+  --border-radius-large: 12px;
+  --border-radius-huge: 20px;
+}

+ 7 - 0
src/theme.ts

@@ -0,0 +1,7 @@
+export const theme = {
+  token: {
+    colorPrimary: "#165dff",
+    colorSuccess: "#00b42a",
+    colorError: "#f53f3f",
+  },
+};

+ 7 - 4
vite.config.ts

@@ -1,6 +1,6 @@
 import { defineConfig } from "vite";
 import vue from "@vitejs/plugin-vue";
-import ViteComponents from "unplugin-vue-components/vite";
+import Components from "unplugin-vue-components/vite";
 import { AntDesignVueResolver } from "unplugin-vue-components/resolvers";
 
 // const SERVER_URL = "http://192.168.10.108:7180";
@@ -15,9 +15,12 @@ export default defineConfig({
     vue({
       reactivityTransform: true,
     }),
-    ViteComponents({
-      resolvers: [AntDesignVueResolver()],
-      dts: true,
+    Components({
+      resolvers: [
+        AntDesignVueResolver({
+          importStyle: false,
+        }),
+      ],
     }),
   ],
   server: {

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 432 - 241
yarn.lock


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů