| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -6,137 +6,179 @@
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    <div class="avatar-section">
 | 
					 | 
					 | 
					 | 
					    <div class="avatar-section">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <p class="section-title">头像</p>
 | 
					 | 
					 | 
					 | 
					      <p class="section-title">头像</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <div class="avatar-preview">
 | 
					 | 
					 | 
					 | 
					      <div class="avatar-preview">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <!-- 当前头像(从接口获取初始值) -->
 | 
					 | 
					 | 
					 | 
					        <img :src="currentAvatar" alt="当前头像" class="current-avatar">
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <img 
 | 
					 | 
					 | 
					 | 
					        <img v-if="previewAvatar" :src="previewAvatar" alt="新头像预览" class="new-avatar">
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          :src="currentAvatar" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          alt="当前头像" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          class="current-avatar"
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        >
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <!-- 新头像预览(选择文件后显示) -->
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <img 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          v-if="previewAvatar" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          :src="previewAvatar" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          alt="新头像预览" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          class="new-avatar"
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        >
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      </div>
 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <!-- 文件选择按钮 -->
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <label class="upload-btn">
 | 
					 | 
					 | 
					 | 
					      <label class="upload-btn">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        选择新头像
 | 
					 | 
					 | 
					 | 
					        选择新头像
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <input 
 | 
					 | 
					 | 
					 | 
					        <input type="file" accept="image/*" @change="handleAvatarChange" class="file-input">
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          type="file" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          accept="image/*" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          @change="handleAvatarChange" 
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          class="file-input"
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        >
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      </label>
 | 
					 | 
					 | 
					 | 
					      </label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <!-- 头像错误提示 -->
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <p v-if="errors.avatar" class="error-tip">{{ errors.avatar }}</p>
 | 
					 | 
					 | 
					 | 
					      <p v-if="errors.avatar" class="error-tip">{{ errors.avatar }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    </div>
 | 
					 | 
					 | 
					 | 
					    </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    <!-- 表单 -->
 | 
					 | 
					 | 
					 | 
					    <!-- 表单 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    <form @submit.prevent="handleSubmit" class="form">
 | 
					 | 
					 | 
					 | 
					    <form @submit.prevent="handleSubmit" class="form">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <!-- 昵称 -->
 | 
					 | 
					 | 
					 | 
					      <div class="form-row">
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <div class="form-item">
 | 
					 | 
					 | 
					 | 
					        <!-- 用户名 -->
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <label class="label">昵称</label>
 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <input
 | 
					 | 
					 | 
					 | 
					          <label class="label">用户名</label>
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          type="text"
 | 
					 | 
					 | 
					 | 
					          <input
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          v-model.trim="formData.nickname"
 | 
					 | 
					 | 
					 | 
					            type="text"
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          class="input"
 | 
					 | 
					 | 
					 | 
					            v-model.trim="formData.username"
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          :class="{ 'input-error': errors.nickname }"
 | 
					 | 
					 | 
					 | 
					            class="input"
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        >
 | 
					 | 
					 | 
					 | 
					            :class="{ 'input-error': errors.username }"
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <p v-if="errors.nickname" class="error-tip">{{ errors.nickname }}</p>
 | 
					 | 
					 | 
					 | 
					            maxlength="20"
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            placeholder="请输入用户名"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.username" class="error-tip">{{ errors.username }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <!-- 手机号 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <label class="label">手机号</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <input
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            type="text"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            v-model.trim="formData.phone"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            class="input"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            :class="{ 'input-error': errors.phone }"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            maxlength="11"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            placeholder="请输入11位手机号"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.phone" class="error-tip">{{ errors.phone }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      <div class="form-row">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <!-- 邮箱 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <label class="label">邮箱</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <input
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            type="email"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            v-model.trim="formData.email"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            class="input"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            :class="{ 'input-error': errors.email }"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            placeholder="请输入邮箱"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.email" class="error-tip">{{ errors.email }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <!-- 学号 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <label class="label">学号</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <input
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            type="text"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            v-model.trim="formData.studentId"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            class="input"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            :class="{ 'input-error': errors.studentId }"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            maxlength="20"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            placeholder="请输入学号"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.studentId" class="error-tip">{{ errors.studentId }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      <div class="form-row">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <!-- 性别 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <label class="label">性别</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <select v-model="formData.gender" class="input" :class="{ 'input-error': errors.gender }">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            <option value="0">未知</option>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            <option value="1">男</option>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            <option value="2">女</option>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          </select>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.gender" class="error-tip">{{ errors.gender }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <!-- 学院 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <div class="form-item half">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <label class="label">学院</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <input
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            type="text"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            v-model.trim="formData.college"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            class="input"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            :class="{ 'input-error': errors.college }"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            maxlength="30"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            placeholder="请输入学院"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          <p v-if="errors.college" class="error-tip">{{ errors.college }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      </div>
 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <!-- 个人简介 -->
 | 
					 | 
					 | 
					 | 
					      <!-- 个人简介 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <div class="form-item">
 | 
					 | 
					 | 
					 | 
					      <div class="form-item">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <label class="label">个人简介</label>
 | 
					 | 
					 | 
					 | 
					        <label class="label">个人简介</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <textarea
 | 
					 | 
					 | 
					 | 
					        <textarea
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          v-model.trim="formData.bio"
 | 
					 | 
					 | 
					 | 
					          v-model.trim="formData.moto"
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          rows="4"
 | 
					 | 
					 | 
					 | 
					          rows="4"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          class="textarea"
 | 
					 | 
					 | 
					 | 
					          class="textarea"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          :class="{ 'input-error': errors.bio }"
 | 
					 | 
					 | 
					 | 
					          :class="{ 'input-error': errors.moto }"
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          maxlength="100"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          placeholder="请输入个人简介(最多100字)"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ></textarea>
 | 
					 | 
					 | 
					 | 
					        ></textarea>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        <p v-if="errors.bio" class="error-tip">{{ errors.bio }}</p>
 | 
					 | 
					 | 
					 | 
					        <p v-if="errors.moto" class="error-tip">{{ errors.moto }}</p>
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      <!-- 密码 -->
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      <div class="form-item">
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <label class="label">新密码</label>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <input
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          type="password"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          v-model.trim="formData.password"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          class="input"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          :class="{ 'input-error': errors.password }"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          placeholder="如需修改请输入新密码"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        >
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        <p v-if="errors.password" class="error-tip">{{ errors.password }}</p>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      </div>
 | 
					 | 
					 | 
					 | 
					      </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <!-- 提交按钮 -->
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      <button type="submit" class="submit-btn">保存修改</button>
 | 
					 | 
					 | 
					 | 
					      <button type="submit" class="submit-btn">保存修改</button>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    </form>
 | 
					 | 
					 | 
					 | 
					    </form>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  </div>
 | 
					 | 
					 | 
					 | 
					  </div>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					</template>
 | 
					 | 
					 | 
					 | 
					</template>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					<script setup>
 | 
					 | 
					 | 
					 | 
					<script setup>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import { ref, onMounted } from 'vue';
 | 
					 | 
					 | 
					 | 
					import { ref, computed } from 'vue';
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import { useRouter } from 'vue-router';
 | 
					 | 
					 | 
					 | 
					import { useUserStore } from '@/stores/user';
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import { useUserStore } from '@/stores/user.js';  // 引入Pinia用户状态
 | 
					 | 
					 | 
					 | 
					import request from '@/utils/request';
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import request from '@/utils/request';  // 引入封装的请求模块
 | 
					 | 
					 | 
					 | 
					import { ElMessage } from 'element-plus';
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import { ElMessage } from 'element-plus';  // 使用Element Plus提示组件
 | 
					 | 
					 | 
					 | 
					import { useRouter } from 'vue-router'
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const router = useRouter();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const userStore = useUserStore();
 | 
					 | 
					 | 
					 | 
					const userStore = useUserStore();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					const userInfo = computed(() => userStore.userInfo);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 从状态管理中获取用户ID和登录状态
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const userId = ref(userStore.userInfo.userid);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const isLoggedIn = userStore.isLoggedIn;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 初始化表单数据
 | 
					 | 
					 | 
					 | 
					// 初始化表单数据
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const formData = ref({
 | 
					 | 
					 | 
					 | 
					const formData = ref({
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  nickname: '',
 | 
					 | 
					 | 
					 | 
					  username: userInfo.value.username || '',
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  bio: ''
 | 
					 | 
					 | 
					 | 
					  phone: userInfo.value.phone || '',
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  email: userInfo.value.email || '',
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  studentId: userInfo.value.studentId || '',
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  gender: userInfo.value.gender !== undefined ? String(userInfo.value.gender) : '0',
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  college: userInfo.value.college || '',
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  moto: userInfo.value.moto || '',
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  password: userInfo.value.password || ''
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					});
 | 
					 | 
					 | 
					 | 
					});
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 头像相关变量
 | 
					 | 
					 | 
					 | 
					const avatarFile = ref(null);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const avatarFile = ref(null);       // 选中的头像文件
 | 
					 | 
					 | 
					 | 
					const previewAvatar = ref('');
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const previewAvatar = ref('');      // 新头像预览 URL
 | 
					 | 
					 | 
					 | 
					const currentAvatar = ref(userInfo.value.avatar);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const currentAvatar = ref('');      // 初始头像
 | 
					 | 
					 | 
					 | 
					const errors = ref({});
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const errors = ref({});             // 错误提示
 | 
					 | 
					 | 
					 | 
					const router=useRouter();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 组件挂载时检查登录状态并获取用户信息
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					onMounted(async () => {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!isLoggedIn) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ElMessage.error('请先登录');
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    router.push({ name: 'Login' });
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  try {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 使用封装的request模块请求用户信息
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const res = await request.get(`/user/info/${userId.value}`);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (res.code === 200) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      formData.value.nickname = res.data.nickname;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      formData.value.bio = res.data.bio;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      currentAvatar.value = res.data.avatar;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      throw new Error(res.msg || '接口返回异常');
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } catch (error) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ElMessage.error(`获取用户信息失败:${error.message}`);
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					});
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 处理头像选择
 | 
					 | 
					 | 
					 | 
					// 处理头像选择
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const handleAvatarChange = (e) => {
 | 
					 | 
					 | 
					 | 
					const handleAvatarChange = (e) => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const file = e.target.files[0];
 | 
					 | 
					 | 
					 | 
					  const file = e.target.files[0];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!file) return;
 | 
					 | 
					 | 
					 | 
					  if (!file) return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 验证文件类型和大小(接口文档要求)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!file.type.startsWith('image/')) {
 | 
					 | 
					 | 
					 | 
					  if (!file.type.startsWith('image/')) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    errors.value.avatar = '请选择图片文件(jpg/png等)';
 | 
					 | 
					 | 
					 | 
					    errors.value.avatar = '请选择图片文件(jpg/png等)';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (file.size > 5 * 1024 * 1024) { // 接口限制5MB
 | 
					 | 
					 | 
					 | 
					  if (file.size > 5 * 1024 * 1024) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    errors.value.avatar = '图片大小不能超过5MB';
 | 
					 | 
					 | 
					 | 
					    errors.value.avatar = '图片大小不能超过5MB';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return;
 | 
					 | 
					 | 
					 | 
					    return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 清除错误提示
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  errors.value.avatar = null;
 | 
					 | 
					 | 
					 | 
					  errors.value.avatar = null;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 生成预览 URL
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const reader = new FileReader();
 | 
					 | 
					 | 
					 | 
					  const reader = new FileReader();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  reader.onload = (e) => previewAvatar.value = e.target.result;
 | 
					 | 
					 | 
					 | 
					  reader.onload = (e) => previewAvatar.value = e.target.result;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  reader.readAsDataURL(file);
 | 
					 | 
					 | 
					 | 
					  reader.readAsDataURL(file);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 保存文件对象(用于上传)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  avatarFile.value = file;
 | 
					 | 
					 | 
					 | 
					  avatarFile.value = file;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -145,51 +187,111 @@ const validateForm = () => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  const newErrors = {};
 | 
					 | 
					 | 
					 | 
					  const newErrors = {};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 昵称验证(接口要求:必填,≤20字符)
 | 
					 | 
					 | 
					 | 
					  // 昵称验证(接口要求:必填,≤20字符)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!formData.value.nickname) {
 | 
					 | 
					 | 
					 | 
					  if (!formData.value.username) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    newErrors.nickname = '昵称不能为空';
 | 
					 | 
					 | 
					 | 
					    newErrors.username = '用户名不能为空';
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else if (formData.value.nickname.length > 20) {
 | 
					 | 
					 | 
					 | 
					  } else if (formData.value.username.length > 20) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    newErrors.nickname = '昵称最多20字符';
 | 
					 | 
					 | 
					 | 
					    newErrors.username = '用户名最多20字符';
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 手机号
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (!formData.value.phone) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.phone = '手机号不能为空';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if (!/^\d{11}$/.test(formData.value.phone)) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.phone = '手机号格式不正确';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 邮箱
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (!formData.value.email) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.email = '邮箱不能为空';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if (!/^[\w.-]+@[\w.-]+\.\w+$/.test(formData.value.email)) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.email = '邮箱格式不正确';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  // 简介验证(接口要求:≤100字符)
 | 
					 | 
					 | 
					 | 
					  // 学号
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (formData.value.bio.length > 100) {
 | 
					 | 
					 | 
					 | 
					  if (!formData.value.studentId) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    newErrors.bio = '简介最多100字符';
 | 
					 | 
					 | 
					 | 
					    newErrors.studentId = '学号不能为空';
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if (formData.value.studentId.length > 20) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.studentId = '学号最多20字符';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 性别
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (!['0', '1', '2'].includes(formData.value.gender)) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.gender = '请选择性别';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 学院
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (!formData.value.college) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.college = '学院不能为空';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } else if (formData.value.college.length > 30) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.college = '学院最多30字符';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 简介
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (formData.value.moto && formData.value.moto.length > 100) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.moto = '简介最多100字符';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  // 密码
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  if (formData.value.password && formData.value.password.length < 6) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    newErrors.password = '密码长度不能少于6位';
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  errors.value = newErrors;
 | 
					 | 
					 | 
					 | 
					  errors.value = newErrors;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  return Object.keys(newErrors).length === 0;
 | 
					 | 
					 | 
					 | 
					  return Object.keys(newErrors).length === 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					};
 | 
					 | 
					 | 
					 | 
					};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					// 提交表单(调用接口文档中的 /user/info 接口)
 | 
					 | 
					 | 
					 | 
					// 提交表单
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					const handleSubmit = async () => {
 | 
					 | 
					 | 
					 | 
					const handleSubmit = async () => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (!validateForm()) return;
 | 
					 | 
					 | 
					 | 
					  if (!validateForm()) return;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  try {
 | 
					 | 
					 | 
					 | 
					  try {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 构建接口要求的 FormData
 | 
					 | 
					 | 
					 | 
					    let avatarUrl = userInfo.value.avatar;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const formDataToSubmit = new FormData();
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 添加头像(可选,有选择时才添加)
 | 
					 | 
					 | 
					 | 
					    // 如果选择了新头像,先上传头像
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (avatarFile.value) {
 | 
					 | 
					 | 
					 | 
					    if (avatarFile.value) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      formDataToSubmit.append('avatar', avatarFile.value);
 | 
					 | 
					 | 
					 | 
					      const formDataObj = new FormData();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      formDataObj.append('file', avatarFile.value);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      const uploadRes = await request.post('/user/info/avatar', formDataObj, {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        headers: { 'Content-Type': 'multipart/form-data' }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (uploadRes.code !== 200) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        throw new Error(uploadRes.msg || '头像上传失败');
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      avatarUrl = uploadRes.data; // 假设后端返回的就是头像URL
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      currentAvatar.value = avatarUrl;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      userInfo.value.avatar = avatarUrl; // 更新用户信息中的头像
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    // 修改用户信息
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    const updateInfoData = {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      username: formData.value.username,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      phone: formData.value.phone,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      email: formData.value.email,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      studentId: formData.value.studentId,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      avatar: userInfo.value.avatar,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      gender: Number(formData.value.gender),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      college: formData.value.college,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    const updateInfoRes = await request.post('/user/info/update', updateInfoData);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (updateInfoRes.code !== 200) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      throw new Error(updateInfoRes.msg || '修改用户信息失败');
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 添加其他字段(接口要求的 UserUpdateDTO 字段)
 | 
					 | 
					 | 
					 | 
					    Object.assign(userInfo.value, updateInfoData);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    formDataToSubmit.append('nickname', formData.value.nickname);
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    formDataToSubmit.append('bio', formData.value.bio);
 | 
					 | 
					 | 
					 | 
					    
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					    if (formData.value.password) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 调用接口文档中的 PUT /user/info 接口(使用封装的request)
 | 
					 | 
					 | 
					 | 
					      const passwordRes = await request.post('/user/info/password', null, {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    const res = await request.put(`/user/info/${userId.value}`, formDataToSubmit, {
 | 
					 | 
					 | 
					 | 
					        params: { password: formData.value.password }
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      headers: { 'Content-Type': 'multipart/form-data' }  // 必须设置
 | 
					 | 
					 | 
					 | 
					      });
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    });
 | 
					 | 
					 | 
					 | 
					      if (passwordRes.code !== 200) {
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					        throw new Error(passwordRes.msg || '修改密码失败');
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // 接口返回成功(根据文档:code=200 表示成功)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (res.code === 200) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      // 更新当前头像(从接口返回新的头像 URL)
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      if (avatarFile.value) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        currentAvatar.value = res.data.avatar;  // 假设接口返回新头像 URL
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }
 | 
					 | 
					 | 
					 | 
					      }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      ElMessage.success('修改成功!');
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } else {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      throw new Error(res.msg || '接口返回异常');
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    ElMessage.success('修改成功!');
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    router.push('/');
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } catch (error) {
 | 
					 | 
					 | 
					 | 
					  } catch (error) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ElMessage.error(`修改失败:${error.message}`);
 | 
					 | 
					 | 
					 | 
					    ElMessage.error(`修改失败:${error.message}`);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  }
 | 
					 | 
					 | 
					 | 
					  }
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -197,21 +299,22 @@ const handleSubmit = async () => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					</script>
 | 
					 | 
					 | 
					 | 
					</script>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					<style scoped>
 | 
					 | 
					 | 
					 | 
					<style scoped>
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/* 样式与原代码基本一致,仅调整无关字段的布局 */
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.change-info-container {
 | 
					 | 
					 | 
					 | 
					.change-info-container {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  max-width: 600px;
 | 
					 | 
					 | 
					 | 
					  max-width: 700px;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  margin: 2rem auto;
 | 
					 | 
					 | 
					 | 
					  margin: 2rem auto;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  padding: 2rem;
 | 
					 | 
					 | 
					 | 
					  padding: 2.5rem 2rem 2rem 2rem;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  background: #f8f9fa;
 | 
					 | 
					 | 
					 | 
					  background: #f8f9fa;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-radius: 8px;
 | 
					 | 
					 | 
					 | 
					  border-radius: 12px;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
 | 
					 | 
					 | 
					 | 
					  box-shadow: 0 4px 16px rgba(52, 152, 219, 0.08);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.title {
 | 
					 | 
					 | 
					 | 
					.title {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  color: #2c3e50;
 | 
					 | 
					 | 
					 | 
					  color: #2c3e50;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-size: 1.5rem;
 | 
					 | 
					 | 
					 | 
					  font-size: 1.7rem;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-weight: 600;
 | 
					 | 
					 | 
					 | 
					  font-weight: 700;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  margin-bottom: 2rem;
 | 
					 | 
					 | 
					 | 
					  margin-bottom: 2.2rem;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  letter-spacing: 1px;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  text-align: center;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.section-title {
 | 
					 | 
					 | 
					 | 
					.section-title {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -240,56 +343,76 @@ const handleSubmit = async () => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-radius: 50%;
 | 
					 | 
					 | 
					 | 
					  border-radius: 50%;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  object-fit: cover;
 | 
					 | 
					 | 
					 | 
					  object-fit: cover;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border: 2px solid #bdc3c7;
 | 
					 | 
					 | 
					 | 
					  border: 2px solid #bdc3c7;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  background: #fff;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.new-avatar {
 | 
					 | 
					 | 
					 | 
					.new-avatar {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-color: #3498db; /* 新头像边框用蓝色区分 */
 | 
					 | 
					 | 
					 | 
					  border-color: #3498db;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.upload-btn {
 | 
					 | 
					 | 
					 | 
					.upload-btn {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  display: inline-block;
 | 
					 | 
					 | 
					 | 
					  display: inline-block;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  padding: 0.5rem 1rem;
 | 
					 | 
					 | 
					 | 
					  padding: 0.5rem 1.2rem;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  background: #3498db;
 | 
					 | 
					 | 
					 | 
					  background: linear-gradient(90deg, #3498db 60%, #6dd5fa 100%);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  color: white;
 | 
					 | 
					 | 
					 | 
					  color: white;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  cursor: pointer;
 | 
					 | 
					 | 
					 | 
					  cursor: pointer;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-size: 0.9rem;
 | 
					 | 
					 | 
					 | 
					  font-size: 0.95rem;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  font-weight: 500;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transition: background 0.3s ease;
 | 
					 | 
					 | 
					 | 
					  transition: background 0.3s ease;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  margin-top: 0.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.upload-btn:hover {
 | 
					 | 
					 | 
					 | 
					.upload-btn:hover {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  background: #2980b9;
 | 
					 | 
					 | 
					 | 
					  background: linear-gradient(90deg, #2980b9 60%, #3498db 100%);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.file-input {
 | 
					 | 
					 | 
					 | 
					.file-input {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  display: none; /* 隐藏原生文件输入框 */
 | 
					 | 
					 | 
					 | 
					  display: none;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					.form {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  margin-top: 1.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					.form-row {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  display: flex;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  gap: 2rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  margin-bottom: 1.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.form-item {
 | 
					 | 
					 | 
					 | 
					.form-item {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  margin-bottom: 1.5rem;
 | 
					 | 
					 | 
					 | 
					  margin-bottom: 1.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  flex: 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  min-width: 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					.form-item.half {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  width: 50%;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.label {
 | 
					 | 
					 | 
					 | 
					.label {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  display: block;
 | 
					 | 
					 | 
					 | 
					  display: block;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  color: #34495e;
 | 
					 | 
					 | 
					 | 
					  color: #34495e;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-size: 0.9rem;
 | 
					 | 
					 | 
					 | 
					  font-size: 0.95rem;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-weight: 500;
 | 
					 | 
					 | 
					 | 
					  font-weight: 500;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  margin-bottom: 0.5rem;
 | 
					 | 
					 | 
					 | 
					  margin-bottom: 0.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.input, .textarea {
 | 
					 | 
					 | 
					 | 
					.input, .textarea, select.input {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  width: 100%;
 | 
					 | 
					 | 
					 | 
					  width: 100%;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  padding: 0.75rem;
 | 
					 | 
					 | 
					 | 
					  padding: 0.75rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border: 1px solid #bdc3c7;
 | 
					 | 
					 | 
					 | 
					  border: 1px solid #bdc3c7;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-size: 0.9rem;
 | 
					 | 
					 | 
					 | 
					  font-size: 0.95rem;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transition: border-color 0.3s ease;
 | 
					 | 
					 | 
					 | 
					  transition: border-color 0.3s ease;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  background: #fff;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.input:focus, .textarea:focus {
 | 
					 | 
					 | 
					 | 
					.input:focus, .textarea:focus, select.input:focus {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  outline: none;
 | 
					 | 
					 | 
					 | 
					  outline: none;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-color: #3498db;
 | 
					 | 
					 | 
					 | 
					  border-color: #3498db;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.1);
 | 
					 | 
					 | 
					 | 
					  box-shadow: 0 0 0 2px rgba(52, 152, 219, 0.08);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.input-error {
 | 
					 | 
					 | 
					 | 
					.input-error {
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -309,18 +432,20 @@ const handleSubmit = async () => {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.submit-btn {
 | 
					 | 
					 | 
					 | 
					.submit-btn {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  width: 100%;
 | 
					 | 
					 | 
					 | 
					  width: 100%;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  padding: 0.75rem;
 | 
					 | 
					 | 
					 | 
					  padding: 0.85rem;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  background: #3498db;
 | 
					 | 
					 | 
					 | 
					  background: linear-gradient(90deg, #3498db 60%, #6dd5fa 100%);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  color: white;
 | 
					 | 
					 | 
					 | 
					  color: white;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border: none;
 | 
					 | 
					 | 
					 | 
					  border: none;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
					 | 
					 | 
					 | 
					  border-radius: 4px;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-size: 0.9rem;
 | 
					 | 
					 | 
					 | 
					  font-size: 1rem;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  font-weight: 500;
 | 
					 | 
					 | 
					 | 
					  font-weight: 600;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  cursor: pointer;
 | 
					 | 
					 | 
					 | 
					  cursor: pointer;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  transition: background 0.3s ease;
 | 
					 | 
					 | 
					 | 
					  transition: background 0.3s ease;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  margin-top: 0.5rem;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  letter-spacing: 1px;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					.submit-btn:hover {
 | 
					 | 
					 | 
					 | 
					.submit-btn:hover {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  background: #2980b9;
 | 
					 | 
					 | 
					 | 
					  background: linear-gradient(90deg, #2980b9 60%, #3498db 100%);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					</style>
 | 
					 | 
					 | 
					 | 
					</style>
 |