2 Commits d2a66e086c ... 1f1e54d8c3

Author SHA1 Message Date
  PrettyCat1 1f1e54d8c3 主页展示,路由判断拦截,获取用户信息,并存储至pinia中 1 year ago
  PrettyCat1 ecd47765c2 登录注册实现,备注拖拽 增删查改 备注实现编辑文本 以及上传图片 1 year ago

+ 63 - 15
vue_project/package-lock.json

@@ -32,6 +32,7 @@
         "element-plus": "^2.7.4",
         "js-cookie": "^3.0.5",
         "pinia": "^2.1.7",
+        "sass": "^1.77.4",
         "tippy.js": "^6.3.7",
         "vue": "^3.2.13",
         "vue-router": "^4.3.2"
@@ -46,6 +47,7 @@
         "eslint": "^7.32.0",
         "eslint-plugin-vue": "^8.0.3",
         "postcss": "^8.4.38",
+        "sass-loader": "^14.2.1",
         "tailwindcss": "^3.4.3"
       }
     },
@@ -3925,7 +3927,6 @@
       "version": "3.1.3",
       "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
       "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "dev": true,
       "dependencies": {
         "normalize-path": "^3.0.0",
         "picomatch": "^2.0.4"
@@ -4180,7 +4181,6 @@
       "version": "2.3.0",
       "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
       "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
-      "dev": true,
       "engines": {
         "node": ">=8"
       }
@@ -4313,7 +4313,6 @@
       "version": "3.0.3",
       "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
       "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
-      "dev": true,
       "dependencies": {
         "fill-range": "^7.1.1"
       },
@@ -4506,7 +4505,6 @@
       "version": "3.6.0",
       "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
       "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
-      "dev": true,
       "dependencies": {
         "anymatch": "~3.1.2",
         "braces": "~3.0.2",
@@ -4530,7 +4528,6 @@
       "version": "5.1.2",
       "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
       "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
       "dependencies": {
         "is-glob": "^4.0.1"
       },
@@ -6782,7 +6779,6 @@
       "version": "7.1.1",
       "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
       "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
-      "dev": true,
       "dependencies": {
         "to-regex-range": "^5.0.1"
       },
@@ -7059,7 +7055,6 @@
       "version": "2.3.3",
       "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
       "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "dev": true,
       "hasInstallScript": true,
       "optional": true,
       "os": [
@@ -7605,6 +7600,11 @@
         "node": ">= 4"
       }
     },
+    "node_modules/immutable": {
+      "version": "4.3.6",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-4.3.6.tgz",
+      "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ=="
+    },
     "node_modules/import-fresh": {
       "version": "3.3.0",
       "resolved": "https://registry.npmmirror.com/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -7666,7 +7666,6 @@
       "version": "2.1.0",
       "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
       "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
       "dependencies": {
         "binary-extensions": "^2.0.0"
       },
@@ -7717,7 +7716,6 @@
       "version": "2.1.1",
       "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
       "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -7744,7 +7742,6 @@
       "version": "4.0.3",
       "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
       "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
       "dependencies": {
         "is-extglob": "^2.1.1"
       },
@@ -7765,7 +7762,6 @@
       "version": "7.0.0",
       "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
       "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
       "engines": {
         "node": ">=0.12.0"
       }
@@ -8873,7 +8869,6 @@
       "version": "3.0.0",
       "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
       "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
       "engines": {
         "node": ">=0.10.0"
       }
@@ -9398,7 +9393,6 @@
       "version": "2.3.1",
       "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz",
       "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
       "engines": {
         "node": ">=8.6"
       },
@@ -10440,7 +10434,6 @@
       "version": "3.6.0",
       "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
       "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
       "dependencies": {
         "picomatch": "^2.2.1"
       },
@@ -10697,6 +10690,62 @@
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
       "dev": true
     },
+    "node_modules/sass": {
+      "version": "1.77.4",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.77.4.tgz",
+      "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==",
+      "dependencies": {
+        "chokidar": ">=3.0.0 <4.0.0",
+        "immutable": "^4.0.0",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/sass-loader": {
+      "version": "14.2.1",
+      "resolved": "https://registry.npmmirror.com/sass-loader/-/sass-loader-14.2.1.tgz",
+      "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==",
+      "dev": true,
+      "dependencies": {
+        "neo-async": "^2.6.2"
+      },
+      "engines": {
+        "node": ">= 18.12.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      },
+      "peerDependencies": {
+        "@rspack/core": "0.x || 1.x",
+        "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+        "sass": "^1.3.0",
+        "sass-embedded": "*",
+        "webpack": "^5.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@rspack/core": {
+          "optional": true
+        },
+        "node-sass": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "webpack": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/schema-utils": {
       "version": "2.7.1",
       "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-2.7.1.tgz",
@@ -11721,7 +11770,6 @@
       "version": "5.0.1",
       "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
       "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
       "dependencies": {
         "is-number": "^7.0.0"
       },

+ 2 - 0
vue_project/package.json

@@ -31,6 +31,7 @@
     "element-plus": "^2.7.4",
     "js-cookie": "^3.0.5",
     "pinia": "^2.1.7",
+    "sass": "^1.77.4",
     "tippy.js": "^6.3.7",
     "vue": "^3.2.13",
     "vue-router": "^4.3.2"
@@ -45,6 +46,7 @@
     "eslint": "^7.32.0",
     "eslint-plugin-vue": "^8.0.3",
     "postcss": "^8.4.38",
+    "sass-loader": "^14.2.1",
     "tailwindcss": "^3.4.3"
   },
   "eslintConfig": {

+ 10 - 15
vue_project/src/api/index.js

@@ -26,22 +26,17 @@ export const registerApi = (userInfo) => {
   return request.post("/manage/register", userInfo)
 }
 
-// // 获取用户信息
-// export const getUserInfo = (token) => {
-//   return request.post("/getUserInfo", token)
-// }
 
-
-// 注册获取用户信息的接口 
-// export const getUserInfo = () => {
-//   return request({
-//     method: "get",
-//     url: "/user/getUserInfo",
-//     headers: {
-//       "Authorization": "Bearer " + getToken(),
-//     }
-//   })
-// };
+// 获取用户信息
+export const getUserInfo = () => {
+  return request({
+    method: "get",
+    url: "/user/getUserInfo",
+    headers: {
+      "Authorization": "Bearer " + getToken(),
+    }
+  })
+};
 
 //获取备注数据接口
 export const getCalendarsInfo = () => {

BIN
vue_project/src/assets/images/moon.png


BIN
vue_project/src/assets/images/mountains_behind.png


BIN
vue_project/src/assets/images/mountains_front.png


BIN
vue_project/src/assets/images/stars.png


BIN
vue_project/src/assets/images/修改.png


+ 270 - 0
vue_project/src/components/home.vue

@@ -0,0 +1,270 @@
+<template>
+  <header>
+    <a href="#" class="logo">校历管理系统 </a>
+    <ul>
+      <li><a href="#" class="active">Home</a></li>
+      <li>
+        <router-link to="/login"> 登录 </router-link>
+      </li>
+      <li>
+        <router-link to="/register"> 注册 </router-link>
+      </li>
+      <li><router-link to="/index"> Calendar </router-link></li>
+    </ul>
+  </header>
+  <section>
+    <img src="../assets/images/stars.png" id="stars" />
+    <img src="../assets/images/moon.png" id="moon" />
+    <img src="../assets/images/mountains_behind.png" id="mountains_behind" />
+    <h2 id="text">Moon Light</h2>
+    <a href="#sec" id="btn">Explore</a>
+    <img src="../assets/images/mountains_front.png" id="mountains_front" />
+  </section>
+  <div class="sec" id="sec">
+    <h2 style="text-align: center">校园校历管理系统</h2>
+    <p style="text-align: center; font-weight: 600; font-style: oblique">
+      校园校历管理系统是一款专为教育机构设计的高效管理工具,
+      它集课程安排、学术活动、节假日设置及特殊事件提醒等功能于一体。<br />
+      通过直观的日历视图,教师、学生及家长能轻松查看每日课表、考试安排及校园活动,促进信息透明化,提升教育资源协调效率。<br />
+      系统支持多用户权限管理,确保数据安全,同时提供定制化通知推送,确保重要日程不错过,为打造智能化、有序化的校园生活提供强有力支持。
+    </p>
+    <!-- <img src="../assets/images/xiaoli.png"> -->
+  </div>
+</template>
+
+<script>
+export default {};
+</script>
+
+<style scoped lang="scss">
+/* 这是引入了一些字体 */
+@import url("https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700,800,900&display=swap");
+
+* {
+  margin: 0;
+  padding: 0;
+  box-sizing: border-box;
+  font-family: "Poppins", sans-serif;
+  /* 当用户手动导航或者 CSSOM scrolling API 触发滚动操作时 */
+  scroll-behavior: smooth;
+}
+
+body {
+  min-height: 100vh;
+  overflow-x: hidden;
+  background: linear-gradient(#2b1055, #7597de);
+  font-family: Georgia, "Times New Roman", Times, serif;
+}
+
+header {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  padding: 30px 100px;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  z-index: 10000;
+}
+
+header .logo {
+  color: #fff;
+  font-weight: 700;
+  text-decoration: none;
+  font-size: 2em;
+  text-transform: uppercase;
+  /* 大写 */
+  letter-spacing: 2px;
+  /* 字符间距 */
+}
+
+header ul {
+  display: flex;
+  justify-content: center;
+  align-items: center;
+}
+
+header ul li {
+  list-style: none;
+  margin-left: 20px;
+}
+
+header ul li a {
+  text-decoration: none;
+  padding: 6px 15px;
+  color: #fff;
+  border-radius: 20px;
+}
+
+header ul li a:hover,
+header ul li a.active {
+  background: #fff;
+  color: #2b1055;
+}
+
+section {
+  position: relative;
+  width: 100%;
+  height: 100vh;
+  padding: 100px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  overflow: hidden;
+}
+
+section::before {
+  content: "";
+  position: absolute;
+  bottom: 0;
+  width: 100%;
+  height: 100px;
+  background: linear-gradient(to top, #1c0522, transparent);
+  z-index: 1000;
+}
+
+section img {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* object-fit CSS 属性指定可替换元素(例如:<img> 或 <video>)的内容应该如何适应到其使用高度和宽度确定的框。 */
+  object-fit: cover;
+  pointer-events: none;
+}
+
+section img#moon {
+  /* mix-blend-mode CSS 属性描述了元素的内容应该与元素的直系父元素的内容和元素的背景如何混合。 */
+  mix-blend-mode: screen;
+}
+
+section img#mountains_front {
+  z-index: 10;
+}
+
+#text {
+  position: absolute;
+  right: -350px;
+  color: #fff;
+  white-space: nowrap;
+  font-size: 7.5vw;
+  z-index: 9;
+}
+
+#btn {
+  text-decoration: none;
+  display: inline-block;
+  padding: 8px 30px;
+  border-radius: 40px;
+  background: #fff;
+  color: #2b1055;
+  font-size: 1.5em;
+  z-index: 9;
+  transform: translateY(100px);
+}
+
+.sec {
+  position: relative;
+  padding: 100px;
+  background: #1c0522;
+}
+
+.sec h2 {
+  font-size: 3.5em;
+  margin-bottom: 10px;
+  color: #fff;
+}
+
+.sec p {
+  font-size: 1em;
+  color: #fff;
+}
+
+#stars {
+  animation: twinkle 2s linear infinite;
+}
+
+@keyframes twinkle {
+  0% {
+    opacity: 1;
+  }
+
+  50% {
+    opacity: 0.5;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+
+#moon {
+  animation: moonRise 10s ease-in-out infinite alternate-reverse;
+  transform: translateY(10%);
+}
+
+@keyframes moonRise {
+  0% {
+    transform: translateY(10%);
+  }
+
+  100% {
+    transform: translateY(-10%);
+  }
+}
+
+#text {
+  opacity: 0;
+  animation: fadeIn 3s forwards;
+}
+
+@keyframes fadeIn {
+  0% {
+    opacity: 0;
+  }
+
+  100% {
+    opacity: 1;
+  }
+}
+
+#btn {
+  opacity: 0;
+  transform: translateY(100px);
+  animation: slideIn 1s ease forwards 0.5s;
+}
+
+@keyframes slideIn {
+  0% {
+    transform: translateY(100px);
+    opacity: 0;
+  }
+
+  100% {
+    transform: translateY(0);
+    opacity: 1;
+  }
+}
+
+body {
+  background-image: linear-gradient(to bottom, #401055, #7c75de);
+  background-size: 100% 200%;
+  animation: gradientShift 15s ease infinite;
+}
+
+@keyframes gradientShift {
+  0% {
+    background-position: 0% 50%;
+  }
+
+  50% {
+    background-position: 100% 50%;
+  }
+
+  100% {
+    background-position: 0% 50%;
+  }
+}
+</style>

+ 11 - 2
vue_project/src/components/indexBody.vue

@@ -200,6 +200,7 @@ export default {
         editable: true, // 确定是否可以修改日历上的事件。
         dayMaxEventRows: 2, // 允许事件堆叠,但不超过设定的行数
         navLinks: true, // 可以单击日/周名称来导航视图
+        timeZone: 'none' ,  //时区关闭
 
         buttonText: {
           prev: "上一页",
@@ -260,6 +261,10 @@ export default {
   },
 
   methods: {
+    eventChangeEdit() {
+      this.calendarOptions.events[0].editable = true
+      console.log(this.calendarOptions.events);
+    },
     // 多选框变换
     changeTerm() {
       let minStartDate = null;
@@ -307,6 +312,7 @@ export default {
     uploadSuccess(data, a) {
       this.form.url = data.data[0];
       console.log(this.form.url);
+      this.InfoCalGet();
     },
     // 文件上传超出范围
     exceedRange() {
@@ -334,14 +340,13 @@ export default {
       let list = this.calendarOptions.events.filter(
         (item) => item.id == e.event.id
       );
-      console.log(list);
+      console.log(e);
       let images = "";
       images =
         (list[0].file == null || list[0].file == "") && this.form.url == ""
           ? require("@/assets/images/unUpload.png")
           : "/api/" + list[0].file;
       let imagesUrl = '<div><img src="' + images + '"+alt="Your Image"/></div>';
-      console.log(images);
       new tippy(e.el, {
         content:
           imagesUrl +
@@ -353,6 +358,10 @@ export default {
           e.event.endStr,
         theme: "tomato",
         allowHTML: true,
+        onHidden(tip) {
+          // 隐藏时销毁提示框
+          tip.destroy();
+        },
       });
     },
     // 点击备注后触发   进行备注修改 -- 修改或者删除

+ 263 - 91
vue_project/src/components/indexNav.vue

@@ -1,108 +1,280 @@
 <template>
-    <el-affix :offset="0">
+  <el-affix :offset="0">
     <Disclosure as="nav" class="bg-gray-800" v-slot="{ open }">
-        <div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
-            <div class="relative flex h-16 items-center justify-between">
-                <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
-                    <!-- Mobile menu button-->
-                    <DisclosureButton
-                        class="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
-                        <span class="absolute -inset-0.5" />
-                        <span class="sr-only">Open main menu</span>
-                        <Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
-                        <XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
-                    </DisclosureButton>
-                </div>
-                <div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
-                    <div class="flex flex-shrink-0 items-center">
-                        <img class="h-8 w-auto" src="../assets/images/苹果.png"
-                            alt="Your Company" />
-                    </div>
-                    <div class="hidden sm:ml-6 sm:block">
-                        <div class="flex space-x-4">
-                            <a v-for="item in navigation" :key="item.name" :href="item.href"
-                                :class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'rounded-md px-3 py-2 text-sm font-medium']"
-                                :aria-current="item.current ? 'page' : undefined">{{ item.name }}</a>
-                        </div>
+      <div class="mx-auto max-w-7xl px-2 sm:px-6 lg:px-8">
+        <div class="relative flex h-16 items-center justify-between">
+          <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
+            <!-- Mobile menu button-->
+            <DisclosureButton
+              class="relative inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
+            >
+              <span class="absolute -inset-0.5" />
+              <span class="sr-only">Open main menu</span>
+              <Bars3Icon
+                v-if="!open"
+                class="block h-6 w-6"
+                aria-hidden="true"
+              />
+              <XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
+            </DisclosureButton>
+          </div>
+          <div
+            class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start"
+          >
+            <div class="flex flex-shrink-0 items-center">
+              <img
+                class="h-8 w-auto"
+                src="../assets/images/苹果.png"
+                alt="Your Company"
+              />
+            </div>
+            <div class="hidden sm:ml-6 sm:block">
+              <div class="flex space-x-4">
+                <a
+                  v-for="item in navigation"
+                  :key="item.name"
+                  :href="item.href"
+                  :class="[
+                    item.current
+                      ? 'bg-gray-900 text-white'
+                      : 'text-gray-300 hover:bg-gray-700 hover:text-white',
+                    'rounded-md px-3 py-2 text-sm font-medium',
+                  ]"
+                  :aria-current="item.current ? 'page' : undefined"
+                  >{{ item.name }}</a
+                >
+              </div>
+            </div>
+          </div>
+          <div
+            class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0"
+          >
+            <button
+              type="button"
+              class="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800"
+            >
+              <span class="absolute -inset-1.5" />
+              <span class="sr-only">View notifications</span>
+              <BellIcon class="h-6 w-6" aria-hidden="true" />
+            </button>
+
+            <!-- Profile dropdown -->
+            <Menu as="div" class="relative ml-3">
+              <div class="relative ml-3">
+                <div>
+                  <button
+                    @click="showMenu = !showMenu"
+                    class="relative flex rounded-full bg-gray-800 text-sm focus:outline-none"
+                  >
+                    <span class="absolute -inset-1.5" />
+                    <span class="sr-only">Open user menu</span>
+                    <img
+                      class="h-8 w-8 rounded-full"
+                      src="../assets/images/商务职业男.png"
+                      alt="User Avatar"
+                    />
+                  </button>
+
+                  <transition name="fade-scale" appear>
+                    <div
+                      v-if="showMenu"
+                      class="absolute right-0 z-10 mt-2 w-80 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none"
+                    >
+                      <!-- 在这里添加头像 -->
+                      <img
+                        class="h-12 w-12 rounded-full mx-auto mb-2"
+                        src="../assets/images/商务职业男.png"
+                        alt="User Avatar"
+                      />
+
+                      <!-- 用户名和修改按钮 -->
+                      <div
+                        class="dropdown-menu-item flex items-center justify-between px-4 py-2"
+                      >
+                        <div class="flex-1 text-center ml-2">{{ username }}</div>
+                        <!-- 名字居中显示 -->
+                        <button class="flex items-center justify-center ml-1">
+                          <!-- 减少左边距 -->
+                          <img
+                            src="../assets/images/修改.png"
+                            alt="Edit"
+                            class="h-6 w-6 mr-2"
+                          />
+                        </button>
+                      </div>
+
+                      <!-- 添加的两个按钮 -->
+                      <div class="dropdown-menu-item px-4 py-2">
+                        <button
+                          class="flex items-center justify-between w-full dropdown-button"
+                        >
+                          <!-- 左侧文本和图标 -->
+                          <div class="flex items-center">
+                            <span>电话号码:{{phone}}</span>
+                          </div>
+                        </button>
+                      </div>
+
+                      <!-- 退出登录按钮 -->
+                      <div class="dropdown-menu-item px-1 py-1 text-left">
+                        <button class="btn-logout" @click="LogOut">
+                          <span
+                            class="iconify"
+                            data-icon="mdi:logout"
+                            data-inline="false"
+                            >退出登录</span
+                          >
+                        </button>
+                      </div>
                     </div>
+                  </transition>
                 </div>
-                <div class="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
-                    
-                    <button type="button"
-                        class="relative rounded-full bg-gray-800 p-1 text-gray-400 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
-                        <span class="absolute -inset-1.5" />
-                        <span class="sr-only">View notifications</span>
-                        <BellIcon class="h-6 w-6" aria-hidden="true" />
-                    </button>
-
-                    <!-- Profile dropdown -->
-                    <Menu as="div" class="relative ml-3">
-                        <div>
-                            <MenuButton
-                                class="relative flex rounded-full bg-gray-800 text-sm focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-gray-800">
-                                <span class="absolute -inset-1.5" />
-                                <span class="sr-only">Open user menu</span>
-                                <img class="h-8 w-8 rounded-full"
-                                    src="../assets/images/商务职业男.png"
-                                    alt="" />
-                            </MenuButton>
-                        </div>
-                        <transition enter-active-class="transition ease-out duration-100"
-                            enter-from-class="transform opacity-0 scale-95"
-                            enter-to-class="transform opacity-100 scale-100"
-                            leave-active-class="transition ease-in duration-75"
-                            leave-from-class="transform opacity-100 scale-100"
-                            leave-to-class="transform opacity-0 scale-95">
-                            <MenuItems
-                                class="absolute right-0 z-10 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
-                                <MenuItem v-slot="{ active }">
-                                <a href="#"
-                                    :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Your
-                                    Profile</a>
-                                </MenuItem>
-                                <MenuItem v-slot="{ active }">
-                                <a href="#"
-                                    :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Settings</a>
-                                </MenuItem>
-                                <MenuItem v-slot="{ active }">
-                                <a href="#"
-                                    :class="[active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm text-gray-700']">Sign
-                                    out</a>
-                                </MenuItem>
-                            </MenuItems>
-                        </transition>
-                    </Menu>
-                </div>
-            </div>
+              </div>
+            </Menu>
+          </div>
         </div>
+      </div>
 
-        <DisclosurePanel class="sm:hidden">
-            <div class="space-y-1 px-2 pb-3 pt-2">
-                <DisclosureButton v-for="item in navigation" :key="item.name" as="a" :href="item.href"
-                    :class="[item.current ? 'bg-gray-900 text-white' : 'text-gray-300 hover:bg-gray-700 hover:text-white', 'block rounded-md px-3 py-2 text-base font-medium']"
-                    :aria-current="item.current ? 'page' : undefined">{{ item.name }}</DisclosureButton>
-            </div>
-        </DisclosurePanel>
+      <DisclosurePanel class="sm:hidden">
+        <div class="space-y-1 px-2 pb-3 pt-2">
+          <DisclosureButton
+            v-for="item in navigation"
+            :key="item.name"
+            as="a"
+            :href="item.href"
+            :class="[
+              item.current
+                ? 'bg-gray-900 text-white'
+                : 'text-gray-300 hover:bg-gray-700 hover:text-white',
+              'block rounded-md px-3 py-2 text-base font-medium',
+            ]"
+            :aria-current="item.current ? 'page' : undefined"
+            >{{ item.name }}</DisclosureButton
+          >
+        </div>
+      </DisclosurePanel>
     </Disclosure>
-</el-affix>
+  </el-affix>
 </template>
-
+<script>
+export default {
+  // ... 其他选项 ...
+  data() {
+    return {
+      showMenu: false, // 假设这是控制下拉菜单显示与否的数据属性
+      menuItems: [],
+      // ... 其他数据属性 ...
+    };
+  },
+};
+</script>
 <script setup>
-import { Disclosure, DisclosureButton, DisclosurePanel, Menu, MenuButton, MenuItem, MenuItems } from '@headlessui/vue'
-import { Bars3Icon, BellIcon, XMarkIcon } from '@heroicons/vue/24/outline'
+import {
+  Disclosure,
+  DisclosureButton,
+  DisclosurePanel,
+  Menu,
+  MenuButton,
+  MenuItem,
+  MenuItems,
+} from "@headlessui/vue";
+import { Bars3Icon, BellIcon, XMarkIcon } from "@heroicons/vue/24/outline";
+import { useUserInfoStore } from "@/stores/userInfo";
+import { useRouter } from "vue-router";
+import { ref, onMounted } from "vue";
+import pinia from "../stores/index";
+const userInfoStore = useUserInfoStore(pinia);
+const router = useRouter();
 // Initialization for ES Users
-
+const username = ref("");
+const phone = ref("");
+const LogOut = () => {
+  username.value = "";
+  userInfoStore.initUserInfo();
+  router.push({ path: "/home" });
+};
 
 const navigation = [
-    { name: 'Dashboard', href: '#', current: false },
-    { name: 'Team', href: '#', current: false },
-    { name: 'Projects', href: '#', current: false },
-    { name: 'Calendar', href: '#', current: true },
-]
+  { name: "Dashboard", href: "#", current: false },
+  { name: "Team", href: "#", current: false },
+  { name: "Projects", href: "#", current: false },
+  { name: "Calendar", href: "#", current: true },
+];
+
+onMounted(() => {
+      userInfoStore.getInfo().then(
+      (response) => {
+        username.value = userInfoStore.username;
+        phone.value = userInfoStore.phone;
+      }
+    );
+});
 </script>
 
 <style scoped>
-a{
-    text-decoration: none;
+a {
+  text-decoration: none;
+}
+.dropdown-menu {
+  /* 其他样式 */
+}
+
+.dropdown-button {
+  /* 您的按钮样式 */
+  background-color: white; /* 默认背景色 */
+  color: #403d3d; /* 默认文字颜色 */
+  border: none;
+  padding: 0.5em 1em; /* 根据需要调整 */
+  transition: all 0.3s ease; /* 添加过渡效果 */
+  cursor: pointer;
+  /* 其他样式... */
+}
+
+/* 添加悬浮效果 */
+.dropdown-button:hover {
+  background-color: #f5f1f1; /* 悬浮时的背景色 */
+  color: black; /* 悬浮时的文字颜色 */
+  /* 如果有其他样式也想改变,可以在这里添加 */
+}
+
+.ml-1 {
+  /* 修改图标 */
+  /* 或者你想要的任何值 */
+  margin-right: 70px;
+}
+
+.ml-2 {
+  /* 用户名 */
+  margin-left: 100px;
+  font-size: 18px;
+}
+
+.mt-2 {
+  /* 下拉菜单 */
+  height: 330px;
+}
+
+.mb-2 {
+  /* 头像 */
+  width: 80px;
+  height: 80px;
+}
+
+.btn-logout {
+  padding: 0.5rem 1rem;
+  background-color: #f44336;
+  color: #fff;
+  border-radius: 4px;
+  border: none;
+  cursor: pointer;
+  transition: background-color 0.3s ease;
+  text-decoration: none;
+  margin-top: 10px;
+  margin-left: 110px;
+}
+
+.btn-logout:hover {
+  background-color: #e53935;
+  /* 悬停时的颜色 */
 }
 </style>

+ 16 - 30
vue_project/src/router/router.js

@@ -1,13 +1,27 @@
 export const staticRoutes = [
     {
       path: "/",
-      redirect: "/login",
+      redirect: "/home",
     },
     {
-      // 主页
+      //demo
+      path: "/home",
+      component: () => import("../components/home.vue"),
+      name: "home",
+    },
+    {
+      // 管理员日历主页
       path: "/index",
       component: () => import("../components/index.vue"),
       name: "Index",
+      meta:{isAuth:true}
+    },
+    {
+      //用户日历主页
+      path:"/userIndex",
+      component: () => import("../components/index.vue"),
+      name: "userIndex",
+      meta:{isAuth:true}
     },
     {
       // 登录
@@ -27,33 +41,5 @@ export const staticRoutes = [
       component: () => import("../components/index.vue"),
       name: "index",
     },
-    {
-      //demo
-      path: "/demo",
-      component: () => import("../components/demo.vue"),
-      name: "demo",
-    }
-    // {
-    //   //商品
-    //   path: "/calendar",
-    //   component: () => import("../components/CalendarTable.vue"),
-    //   name: "calendar",
-    //   meta:{isAuth:true}
-    // },
-    // {
-    //   //结算中心
-    //   path: "/pay",
-    //   component: () => import("../components/pay.vue"),
-    //   name: "pay",
-    //   meta:{isAuth:true}
-    // },
-    // {
-    //   //付款中心
-    //   path: "/ToPay",
-    //   component: () => import("../components/order/ToPay.vue"),
-    //   name: "ToPay",
-    //   meta:{isAuth:true}
-    // },
-    
   ];
   

+ 28 - 0
vue_project/src/stores/userInfo.js

@@ -0,0 +1,28 @@
+import { defineStore } from 'pinia';
+import { getToken, removeToken, setToken } from '../utils/token-utils';
+import { getUserInfo } from '../api/index';
+import { ElMessage } from "element-plus";
+
+export const useUserInfoStore = defineStore('userInfo', {
+	state: () => ({
+    token: getToken(),
+    username: '',
+    phone:""
+  }),
+
+  actions: {
+    async getInfo() {
+      const result = await getUserInfo()
+      this.username = result.data.data.username
+      this.phone = result.data.data.phone
+      return result.data
+    },
+    initUserInfo() {
+      console.log("删除token");
+      removeToken()
+      this.username = ""
+      this.token=""
+      ElMessage.success("退出登录");
+    }
+  },
+})

+ 2 - 0
vue_project/src/utils/request.js

@@ -17,7 +17,9 @@ service.interceptors.request.use(config => {
   const TokenKey = 'vue_admin_template_token'
   const token = Cookies.get(TokenKey)
   if (token && typeof token !='undefined' && token != "") {
+    // 管理员
     (config.headers)['Authorization'] = "Bearer " + token
+    // 学生 (config.headers)['Authorization'] = "Bearer " + token
   }
   return config
 }, error => {