소스 검색

Editprofile Fix

NanceTide 6 달 전
부모
커밋
49c6cd3cb3
7개의 변경된 파일485개의 추가작업 그리고 269개의 파일을 삭제
  1. 2 2
      src/App.vue
  2. 2 0
      src/components/AdminMenu.vue
  3. 2 2
      src/components/Header.vue
  4. 1 1
      src/router/index.js
  5. 155 245
      src/views/EditProfile.vue
  6. 323 0
      src/views/EditProfile_.vue
  7. 0 19
      src/views/TeacherDetail.vue

+ 2 - 2
src/App.vue

@@ -1,8 +1,8 @@
 <template>
   <div id="app">
-    <Suspense>
+    <!-- <Suspense> -->
       <Header />
-    </Suspense>
+    <!-- </Suspense> -->
     <main>
       <router-view></router-view>
     </main>

+ 2 - 0
src/components/AdminMenu.vue

@@ -14,9 +14,11 @@
   <script setup>
   import { ref } from 'vue';
   import { useAuthStore } from '@/store/modules/auth';
+  import { useTeachersStore } from '@/store/modules/teachers';
   import { useRouter } from 'vue-router';
   
   const authStore = useAuthStore();
+
   const router = useRouter();
   const isOpen = ref(false);
 

+ 2 - 2
src/components/Header.vue

@@ -13,7 +13,7 @@
         </template>
       </div>
       <div class="auth">
-        <Suspense>
+        <!-- <Suspense> -->
 
           <template v-if="!isLoggedIn">
             <router-link to="/login" class="auth-link">登录</router-link>
@@ -23,7 +23,7 @@
             <UserMenu v-if="isAdmin" />
             <AdminMenu v-else />
           </template>
-        </Suspense>
+        <!-- </Suspense> -->
       </div>
     </nav>
   </header>

+ 1 - 1
src/router/index.js

@@ -4,7 +4,7 @@ import Login from '../views/Login.vue'
 import Register from '../views/Register.vue'
 import ForgotPassword from '../views/ForgotPassword.vue'
 import Profile from '../views/Profile.vue'
-import EditProfile from '../views/EditProfile.vue'
+import EditProfile from '../views/EditProfile_.vue'
 import ChangePassword from '../views/ChangePassword.vue'
 import TeacherDetail from '../views/TeacherDetail.vue'
 import PaperDetail from '../views/PaperDetail.vue'

+ 155 - 245
src/views/EditProfile.vue

@@ -1,261 +1,171 @@
 <template>
-    <div class="edit-profile">
-      <h1>编辑个人资料</h1>
-      
-      <!-- 基本信息部分 -->
-      <div class="basic-info">
-        <div>
-          <label for="name">姓名:</label>
-          <input type="text" v-model="teacher.name" id="name">
-          
-          <label for="email">邮箱:</label>
-          <input type="email" v-model="teacher.email" id="email">
-          
-          <label for="phoneNumber">电话:</label>
-          <input type="tel" v-model="teacher.phoneNumber" id="phoneNumber">
-          
-          <label for="profile">简介:</label>
-          <textarea v-model="teacher.profile" id="profile"></textarea>
-          
-          <label for="undergraduateCourse">本科课程:</label>
-          <input type="text" v-model="teacher.undergraduateCourse" id="undergraduateCourse">
-          
-          <label for="graduateCourse">研究生课程:</label>
-          <input type="text" v-model="teacher.graduateCourse" id="graduateCourse">
-          
-          <label for="researchField">研究领域:</label>
-          <textarea v-model="teacher.researchField.information" id="researchField"></textarea>
-        </div>
-      </div>
-  
-      <!-- 专利信息 -->
-      <CollapsibleSection title="专利信息">
-        <div v-for="(patent, index) in teacher.patent" :key="index" class="patent-item">
-          <label>专利号:</label>
-          <input type="text" v-model="patent.patentNum">
-          <label>授权号:</label>
-          <input type="text" v-model="patent.authorizationNum">
-          <label>证书号:</label>
-          <input type="text" v-model="patent.certificateNum">
-          <label>日期:</label>
-          <input type="date" v-model="patent.date">
-        </div>
-      </CollapsibleSection>
-  
-      <!-- 获奖信息 -->
-      <CollapsibleSection title="获奖信息">
-        <div v-for="(award, index) in awards" :key="index" class="award-item">
-          <label>获奖名称:</label>
-          <input type="text" v-model="award.name">
-          <label>时间:</label>
-          <input type="date" v-model="award.time">
-          <label>图片链接:</label>
-          <input type="url" v-model="award.image">
-        </div>
-      </CollapsibleSection>
-  
-      <!-- 论文信息 -->
-      <CollapsibleSection title="论文信息">
-        <div v-for="(thesis, index) in theses" :key="index" class="thesis-item">
-          <label>论文名称:</label>
-          <input type="text" v-model="thesis.name">
-          <label>发表时间:</label>
-          <input type="date" v-model="thesis.time">
-          <label>网站链接:</label>
-          <input type="url" v-model="thesis.website">
-          <label>图片链接:</label>
-          <input type="url" v-model="thesis.image">
-          <label>文件链接:</label>
-          <input type="url" v-model="thesis.file">
-        </div>
-      </CollapsibleSection>
-  
-      <!-- 著作信息 -->
-      <CollapsibleSection title="著作信息">
-        <div v-for="(work, index) in works" :key="index" class="work-item">
-          <label>著作名称:</label>
-          <input type="text" v-model="work.name">
-          <label>出版社:</label>
-          <input type="text" v-model="work.press">
-          <label>出版时间:</label>
-          <input type="date" v-model="work.time">
-          <label>图片链接:</label>
-          <input type="url" v-model="work.image">
-          <label>文件链接:</label>
-          <input type="url" v-model="work.file">
-        </div>
-      </CollapsibleSection>
-  
-      <!-- 保存按钮 -->
-      
-    <button @click="saveProfile" class="save-button">保存</button>
+  <div>
+    <el-form
+      ref="teacherForm"
+      :model="teacher"
+      :rules="rules"
+      size="default"
+      label-width="100px"
+    >
+      <el-form-item label="姓名" prop="name">
+        <el-input
+          v-model="teacher.name"
+          placeholder="请输入姓名"
+          :maxlength="240"
+          clearable
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="邮箱" prop="email">
+        <el-input
+          v-model="teacher.email"
+          placeholder="请输入邮箱"
+          :maxlength="240"
+          clearable
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="电话" prop="phoneNumber">
+        <el-input
+          v-model="teacher.phoneNumber"
+          placeholder="请输入电话"
+          :maxlength="240"
+          clearable
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="简介" prop="profile">
+        <el-input
+          v-model="teacher.profile"
+          type="textarea"
+          placeholder="请输入简介"
+          :maxlength="800"
+          :autosize="{ minRows: 12, maxRows: 12 }"
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="本科课程" prop="undergraduateCourse">
+        <el-input
+          v-model="teacher.undergraduateCourse"
+          type="textarea"
+          placeholder="请输入本科课程"
+          :maxlength="240"
+          :autosize="{ minRows: 4, maxRows: 4 }"
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="研究生课程" prop="graduateCourse">
+        <el-input
+          v-model="teacher.graduateCourse"
+          type="textarea"
+          placeholder="请输入研究生课程"
+          :maxlength="240"
+          :autosize="{ minRows: 4, maxRows: 4 }"
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="研究领域" prop="researchField">
+        <el-input
+          v-model="teacher.researchField"
+          type="textarea"
+          placeholder="请输入研究领域"
+          :maxlength="800"
+          :autosize="{ minRows: 4, maxRows: 4 }"
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item label="奖项" prop="researchField">
+        <el-input
+          v-model="teacher.awards"
+          type="textarea"
+          placeholder="请输入奖项"
+          :maxlength="800"
+          :autosize="{ minRows: 4, maxRows: 4 }"
+          :style="{ width: '100%' }"
+        ></el-input>
+      </el-form-item>
+      <el-form-item size="large">
+        <el-button type="primary" @click="submitForm">提交</el-button>
+        <el-button @click="fetchTeacherData">重置</el-button>
+      </el-form-item>
+    </el-form>
   </div>
 </template>
-
 <script>
-import { ref, watchEffect } from 'vue';
-import { useRouter } from 'vue-router';
-import { updateTeacherById, getTeacherById } from '@/api/Teacher';
-import { useAuthStore } from '@/store/modules/auth';
+import { reactive, ref, watchEffect } from 'vue'
+import { useRouter } from 'vue-router'
+import { updateTeacherById, getTeacherById } from '@/api/Teacher'
+import { useAuthStore } from '@/store/modules/auth'
+import { useTeachersStore } from '@/store/modules/teachers'
 
 export default {
-  name: 'EditProfile',
   setup() {
-    const router = useRouter();
-    const authStore = useAuthStore();
-    
-    const teacher = ref({
-      name: '',
-      email: '',
-      phoneNumber: '',
-      undergraduateCourse: '',
-      graduateCourse: '',
-      profile: '',
-      image: '',
-      researchField: {}
-    });
-
-    const teacherId = authStore.user.id;
-    const token = authStore.token;
-
-    // 使用 watchEffect 来监控 teacherId 的变化并获取教师数据
-    watchEffect(async () => {
+    const router = useRouter()
+    const authStore = useAuthStore()
+    const teachersStore = useTeachersStore()
+    const token = localStorage.getItem('token')
+    const teacherId = ref(authStore.user.id)
+
+    const teacher = ref({})
+
+    const rules = reactive({
+      name: [
+        {
+          required: true,
+          message: '请输入姓名',
+          trigger: 'blur',
+        },
+      ],
+      email: [],
+      phoneNumber: [],
+      profile: [
+        {
+          required: true,
+          message: '请输入简介',
+          trigger: 'blur',
+        },
+      ],
+      undergraduateCourse: [],
+      graduateCourse: [],
+      researchField: [],
+      awards: []
+    })
+
+    const teacherForm = ref(null)
+
+    const submitForm = async () => {
+      teacherForm.value.validate(async (valid) => {
+        if (!valid) return
+        try {
+          await updateTeacherById(authStore.user.id, { ...teacher.value })
+        } catch (error) {
+          console.error('保存个人资料失败:', error)
+        }
+      })
+    }
+
+    const fetchTeacherData = async () => {
       try {
-        const response = await getTeacherById(teacherId, token);
-        teacher.value = response;
+        await teachersStore.fetchTeacherDetails(teacherId.value) // 调用 Pinia 方法
+        teacher.value = teachersStore.currentTeacher // 从 store 获取教师信息
       } catch (error) {
-        console.error('获取教师信息失败:', error);
+        console.error('获取教师信息失败:', error)
       }
-    });
+    }
 
-    const saveProfile = async () => {
-      try {
-        await updateTeacherById(teacherId, { ...teacher.value });
-        router.push({ name: 'Profile' }); // 返回个人资料页面
-      } catch (error) {
-        console.error('保存个人资料失败:', error);
-      }
-    };
+    watchEffect(async () => {
+      if (!authStore.user.id || !token) return
+      fetchTeacherData()
+    })
 
     return {
       teacher,
-      saveProfile
-    };
-  }
+      rules,
+      teacherForm,
+      submitForm,
+      fetchTeacherData,
+    }
+  },
 }
 </script>
-
-<style scoped>
-.edit-profile {
-  max-width: 800px;
-  margin: 0 auto;
-  padding: 20px;
-  background: #f9f9f9;
-  border-radius: 8px;
-  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
-}
-
-h1 {
-  text-align: center;
-  color: #333;
-  margin-bottom: 20px;
-}
-
-.basic-info {
-  display: flex;
-  align-items: center;
-  margin-bottom: 30px;
-}
-
-.profile-image {
-  width: 100px;
-  height: 100px;
-  border-radius: 50%;
-  margin-right: 20px;
-  border: 2px solid #007bff;
-}
-
-.basic-info div {
-  flex: 1;
-}
-
-label {
-  display: block;
-  font-weight: bold;
-  margin-bottom: 5px;
-  color: #555;
-}
-
-input[type="text"],
-input[type="email"],
-input[type="tel"],
-input[type="url"],
-textarea {
-  width: 100%;
-  padding: 10px;
-  margin-bottom: 15px;
-  border: 1px solid #ccc;
-  border-radius: 5px;
-  font-size: 14px;
-  transition: border-color 0.3s;
-}
-
-input[type="text"]:focus,
-input[type="email"]:focus,
-input[type="tel"]:focus,
-input[type="url"]:focus,
-textarea:focus {
-  border-color: #007bff;
-  outline: none;
-}
-
-.CollapsibleSection {
-  margin-bottom: 20px;
-  border: 1px solid #e0e0e0;
-  border-radius: 5px;
-  background: #fff;
-}
-
-.CollapsibleSection h2 {
-  cursor: pointer;
-  padding: 10px;
-  background: #f1f1f1;
-  margin: 0;
-  border-bottom: 1px solid #e0e0e0;
-  color: #333;
-}
-
-.CollapsibleSection-content {
-  padding: 10px;
-}
-
-.award-item,
-.thesis-item,
-.work-item,
-.patent-item {
-  margin-bottom: 15px;
-  padding: 10px;
-  border: 1px solid #e0e0e0;
-  border-radius: 5px;
-  background: #f9f9f9;
-}
-
-.save-button {
-  display: block;
-  width: 100%;
-  padding: 10px;
-  background: #28a745;
-  color: white;
-  border: none;
-  border-radius: 5px;
-  font-size: 16px;
-  cursor: pointer;
-  transition: background 0.3s;
-}
-
-.save-button:hover {
-  background: #218838;
-}
-</style>
-
-  
+<style></style>

+ 323 - 0
src/views/EditProfile_.vue

@@ -0,0 +1,323 @@
+<template>
+  <div class="common-layout">
+    <el-container>
+      <el-anchor :offset="70" style="width: 150px; color: #fff;">
+        <el-anchor-link :href="`#basic-usage`">
+          编辑个人资料
+        </el-anchor-link>
+        <el-anchor-link :href="`#basic-usage`">
+          编辑个人资料
+        </el-anchor-link>
+        <el-anchor-link :href="`#basic-usage`">
+          编辑个人资料
+        </el-anchor-link>
+        <el-anchor-link :href="`#basic-usage`">
+          编辑个人资料
+        </el-anchor-link>
+      </el-anchor>
+
+      <el-main>
+        <div style="max-width: 100vh;">
+          <p id="basic-usage">编辑个人资料</p>
+          <el-form :model="teacher" label-width="auto">
+            <el-form-item label="姓名">
+              <el-input v-model="teacher.name" />
+            </el-form-item>
+            <el-form-item label="邮箱">
+              <el-input v-model="teacher.email" />
+            </el-form-item>
+            <el-form-item label="电话">
+              <el-input v-model="teacher.phoneNumber" />
+            </el-form-item>
+            <el-form-item label="简介">
+              <el-input
+                v-model="teacher.profile"
+                type="textarea"
+                maxlength="800"
+              />
+            </el-form-item>
+            <el-form-item label="本科课程">
+              <el-input
+                v-model="teacher.undergraduateCourse"
+                type="textarea"
+                maxlength="240"
+              />
+            </el-form-item>
+            <el-form-item label="研究生课程">
+              <el-input
+                v-model="teacher.graduateCourse"
+                type="textarea"
+                maxlength="240"
+              />
+            </el-form-item>
+            <el-form-item label="研究领域">
+              <el-input
+                v-model="teacher.researchField"
+                type="textarea"
+                maxlength="800"
+              />
+            </el-form-item>
+
+            <el-form-item>
+              <el-button type="primary" @click="onSubmit">Create</el-button>
+              <el-button>Cancel</el-button>
+            </el-form-item>
+          </el-form>
+        </div>
+
+        <el-card shadow="hover"> </el-card>
+      </el-main>
+    </el-container>
+  </div>
+
+  <div style="display: grid; place-items: center; height: 100vh"></div>
+  <!-- 专利信息 -->
+  <!-- <CollapsibleSection title="专利信息">
+      <div
+        v-for="(patent, index) in teacher.patent"
+        :key="index"
+        class="patent-item"
+      >
+        <label>专利号:</label>
+        <input type="text" v-model="patent.patentNum" />
+        <label>授权号:</label>
+        <input type="text" v-model="patent.authorizationNum" />
+        <label>证书号:</label>
+        <input type="text" v-model="patent.certificateNum" />
+        <label>日期:</label>
+        <input type="date" v-model="patent.date" />
+      </div>
+    </CollapsibleSection>
+
+    <CollapsibleSection title="获奖信息">
+      <div v-for="(award, index) in awards" :key="index" class="award-item">
+        <label>获奖名称:</label>
+        <input type="text" v-model="award.name" />
+        <label>时间:</label>
+        <input type="date" v-model="award.time" />
+        <label>图片链接:</label>
+        <input type="url" v-model="award.image" />
+      </div>
+    </CollapsibleSection>
+
+    <CollapsibleSection title="论文信息">
+      <div v-for="(thesis, index) in theses" :key="index" class="thesis-item">
+        <label>论文名称:</label>
+        <input type="text" v-model="thesis.name" />
+        <label>发表时间:</label>
+        <input type="date" v-model="thesis.time" />
+        <label>网站链接:</label>
+        <input type="url" v-model="thesis.website" />
+        <label>图片链接:</label>
+        <input type="url" v-model="thesis.image" />
+        <label>文件链接:</label>
+        <input type="url" v-model="thesis.file" />
+      </div>
+    </CollapsibleSection>
+
+    <CollapsibleSection title="著作信息">
+      <div v-for="(work, index) in works" :key="index" class="work-item">
+        <label>著作名称:</label>
+        <input type="text" v-model="work.name" />
+        <label>出版社:</label>
+        <input type="text" v-model="work.press" />
+        <label>出版时间:</label>
+        <input type="date" v-model="work.time" />
+        <label>图片链接:</label>
+        <input type="url" v-model="work.image" />
+        <label>文件链接:</label>
+        <input type="url" v-model="work.file" />
+      </div>
+    </CollapsibleSection>
+
+    保存按钮 -->
+</template>
+
+<script>
+import { reactive, ref, watchEffect } from 'vue'
+import { useRouter } from 'vue-router'
+import { updateTeacherById, getTeacherById } from '@/api/Teacher'
+import { useAuthStore } from '@/store/modules/auth'
+import { useTeachersStore } from '@/store/modules/teachers'
+
+export default {
+  name: 'EditProfile',
+  setup() {
+    const router = useRouter()
+    const authStore = useAuthStore()
+    const teachersStore = useTeachersStore()
+
+    const teacher = ref({
+      // name: '',
+      // email: '',
+      // phoneNumber: '',
+      // undergraduateCourse: '',
+      // graduateCourse: '',
+      // profile: '',
+      // image: '',
+      // researchField: '',
+    })
+    const token = localStorage.getItem('token')
+    const teacherId = ref(authStore.user.id)
+
+    const fetchTeacherData = async () => {
+      try {
+        await teachersStore.fetchTeacherDetails(teacherId.value) // 调用 Pinia 方法
+        teacher.value = teachersStore.currentTeacher // 从 store 获取教师信息
+        patentTotal.value = teacher.value.patent
+          ? teacher.value.patent.length
+          : 0 // 计算专利数量
+      } catch (error) {
+        console.error('获取教师信息失败:', error)
+      }
+    }
+
+    // 使用 watchEffect 来监控 teacherId 的变化并获取教师数据
+    watchEffect(async () => {
+      try {
+        const response = await getTeacherById(authStore.user.id, token)
+        teacher.value = response
+      } catch (error) {
+        console.error('获取教师信息失败:', error)
+      }
+    })
+
+    const saveProfile = async () => {
+      try {
+        await updateTeacherById(authStore.user.id, { ...teacher.value })
+        router.push({ name: 'Profile' }) // 返回个人资料页面
+      } catch (error) {
+        console.error('保存个人资料失败:', error)
+      }
+    }
+
+    watchEffect(() => {
+      if (authStore.user.id && token) {
+        fetchTeacherData()
+        // fetchAwards();
+        // fetchTheses();
+        // fetchWorks();
+      }
+    })
+
+    return {
+      teacher,
+      fetchTeacherData,
+      saveProfile,
+    }
+  },
+}
+</script>
+
+<style scoped>
+.edit-profile {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 20px;
+  background: #f9f9f9;
+  border-radius: 8px;
+  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
+}
+
+h1 {
+  text-align: center;
+  color: #333;
+  margin-bottom: 20px;
+}
+
+.basic-info {
+  display: flex;
+  align-items: center;
+  margin-bottom: 30px;
+}
+
+.profile-image {
+  width: 100px;
+  height: 100px;
+  border-radius: 50%;
+  margin-right: 20px;
+  border: 2px solid #007bff;
+}
+
+.basic-info div {
+  flex: 1;
+}
+
+label {
+  display: block;
+  font-weight: bold;
+  margin-bottom: 5px;
+  color: #555;
+}
+
+input[type='text'],
+input[type='email'],
+input[type='tel'],
+input[type='url'],
+textarea {
+  width: 100%;
+  padding: 10px;
+  margin-bottom: 15px;
+  border: 1px solid #ccc;
+  border-radius: 5px;
+  font-size: 14px;
+  transition: border-color 0.3s;
+}
+
+input[type='text']:focus,
+input[type='email']:focus,
+input[type='tel']:focus,
+input[type='url']:focus,
+textarea:focus {
+  border-color: #007bff;
+  outline: none;
+}
+
+.CollapsibleSection {
+  margin-bottom: 20px;
+  border: 1px solid #e0e0e0;
+  border-radius: 5px;
+  background: #fff;
+}
+
+.CollapsibleSection h2 {
+  cursor: pointer;
+  padding: 10px;
+  background: #f1f1f1;
+  margin: 0;
+  border-bottom: 1px solid #e0e0e0;
+  color: #333;
+}
+
+.CollapsibleSection-content {
+  padding: 10px;
+}
+
+.award-item,
+.thesis-item,
+.work-item,
+.patent-item {
+  margin-bottom: 15px;
+  padding: 10px;
+  border: 1px solid #e0e0e0;
+  border-radius: 5px;
+  background: #f9f9f9;
+}
+
+.save-button {
+  display: block;
+  width: 100%;
+  padding: 10px;
+  background: #28a745;
+  color: white;
+  border: none;
+  border-radius: 5px;
+  font-size: 16px;
+  cursor: pointer;
+  transition: background 0.3s;
+}
+
+.save-button:hover {
+  background: #218838;
+}
+</style>

+ 0 - 19
src/views/TeacherDetail.vue

@@ -134,21 +134,10 @@ export default {
       try {
         await teachersStore.fetchTeacherDetails(teacherId.value); // 调用 Pinia 方法
         teacher.value = teachersStore.currentTeacher; // 从 store 获取教师信息
-        patentTotal.value = teacher.value.patent ? teacher.value.patent.length : 0; // 计算专利数量
       } catch (error) {
         console.error('获取教师信息失败:', error);
       }
     };
-
-    const fetchAwards = async () => {
-      try {
-        const response = await getAwards(awardPage.value, 12, null, teacherId.value);
-        awards.value = response.data.records;
-        awardTotal.value = response.data.total;
-      } catch (error) {
-        console.error('获取获奖信息失败:', error);
-      }
-    };
     
     const fetchTheses = async () => {
       try {
@@ -169,12 +158,6 @@ export default {
         console.error('获取著作信息失败:', error);
       }
     };
-
-    const handleAwardPageChange = (page) => {
-      awardPage.value = page;
-      fetchAwards();
-    };
-
     const handleThesisPageChange = (page) => {
       thesisPage.value = page;
       fetchThesis();
@@ -196,7 +179,6 @@ export default {
 
     watch(teacherId, () => {
       fetchTeacherData();
-      fetchAwards();
       fetchTheses();
       fetchWorks();
     }, { immediate: true });
@@ -218,7 +200,6 @@ export default {
       expandedSections,
       authStore,
       editProfile,
-      handleAwardPageChange,
       handleThesisPageChange,
       handleWorkPageChange,
       handlePatentPageChange,