|
@@ -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>
|