lrj
7 天以前 6d519474e44855682043d3c40db2c86a6822caca
web/src/components/JudgeFormSimple.vue
@@ -25,6 +25,28 @@
        <el-input v-model="form.phone" placeholder="请输入联系电话" />
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <div style="display: flex; align-items: center; gap: 10px;">
          <el-input
            v-model="form.password"
            type="password"
            :placeholder="isEdit ? '请输入新密码(6-20位,包含字母和数字)' : '请输入登录密码(6-20位,包含字母和数字)'"
            maxlength="20"
            @focus="handlePasswordFocus"
            @input="handlePasswordInput"
            style="flex: 1;"
          />
          <el-button
            v-if="isEdit"
            type="primary"
            size="small"
            @click="handleResetPassword"
          >
            重置密码
          </el-button>
        </div>
      </el-form-item>
      <el-form-item label="性别" prop="gender">
        <el-radio-group v-model="form.gender">
          <el-radio :value="1">男</el-radio>
@@ -144,6 +166,8 @@
// 是否为编辑模式
const isEdit = computed(() => !!props.judgeData?.id)
// 表单数据
const form = reactive<JudgeInput & { 
  avatarUrl?: string; 
@@ -160,6 +184,7 @@
  id: undefined,
  name: '',
  phone: '',
  password: '',
  gender: undefined,
  description: '',
  specialtyIds: [],
@@ -171,6 +196,9 @@
// 可选的专业标签(从后端获取)
const availableTags = ref<Tag[]>([])
// 跟踪密码是否被修改
const isPasswordModified = ref(false)
// 表单验证规则
const rules = {
  name: [
@@ -180,16 +208,41 @@
  phone: [
    { required: true, message: '请输入联系电话', trigger: 'blur' },
    { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
  ],
  password: [
    {
      validator: (rule: any, value: string, callback: any) => {
        // 编辑模式下,如果是占位符密码且未修改,则跳过验证
        if (isEdit.value && value === '••••••••' && !isPasswordModified.value) {
          callback()
          return
        }
        if (!value || value.trim() === '') {
          callback(new Error('请输入登录密码'))
        } else if (!/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*?&]{6,}$/.test(value)) {
          callback(new Error('密码至少6个字符,必须包含字母和数字'))
        } else {
          callback()
        }
      },
      trigger: 'blur'
    }
  ]
}
// 监听评委数据变化,填充表单
watch(() => props.judgeData, (data) => {
  console.log('🔍 Watch triggered, judgeData:', data)
  console.log('🔍 isEdit computed:', isEdit.value)
  nextTick(async () => {
    if (data && data.id) {
      // 编辑模式:填充表单数据
      form.id = data.id
      form.name = data.name || ''
      form.phone = data.phone || ''
      form.password = '' // 编辑模式下清空密码字段,用户需要输入新密码或点击重置密码
      isPasswordModified.value = false
      form.gender = data.gender
      form.description = data.description || ''
      form.specialtyIds = data.specialties?.map(tag => tag.id) || []
@@ -197,10 +250,7 @@
      
      // 加载评委头像/媒体(targetType=1 表示评委)
      try {
        console.log('=== 加载评委媒体 ===');
        console.log('评委ID:', data.id);
        const medias = await getMediasByTarget(MediaTargetType.JUDGE_AVATAR, parseInt(data.id))
        console.log('获取到的媒体列表:', medias);
        
        // 只取第一个图片作为头像(评委只能有一个头像)
        const firstImage = (medias || []).find((m: Media) => {
@@ -217,7 +267,6 @@
            url: firstImage.fullUrl
          };
          form.avatarUrl = firstImage.fullUrl;
          console.log('设置当前头像:', form.currentAvatar);
        } else {
          form.currentAvatar = null;
        }
@@ -235,16 +284,39 @@
  form.id = undefined
  form.name = ''
  form.phone = ''
  form.password = ''
  form.gender = undefined
  form.description = ''
  form.specialtyIds = []
  form.avatarUrl = ''
  form.avatarMediaId = undefined
  form.currentAvatar = null
  isPasswordModified.value = false
  
  nextTick(() => {
    formRef.value?.clearValidate()
  })
}
// 处理密码字段焦点事件
const handlePasswordFocus = () => {
  if (isEdit.value && form.password === '••••••••') {
    form.password = ''
  }
}
// 处理密码输入事件
const handlePasswordInput = (value: string) => {
  if (isEdit.value) {
    isPasswordModified.value = value !== '' && value !== '••••••••'
  }
}
// 处理重置密码
const handleResetPassword = () => {
  form.password = ''
  isPasswordModified.value = true
  ElMessage.success('密码已清空,请输入新密码')
}
// 处理头像上传
@@ -253,14 +325,9 @@
    return; // 没有新头像需要上传
  }
  
  console.log('=== 开始上传头像文件 ===');
  console.log('评委ID:', judgeId);
  console.log('待上传的头像:', form.currentAvatar.name);
  try {
    // 上传文件
    const uploadResult = await uploadFile(form.currentAvatar.file!);
    console.log('上传结果:', uploadResult);
    
    if (uploadResult.success) {
      // 保存媒体信息到数据库
@@ -278,7 +345,6 @@
      form.currentAvatar.uploaded = true;
      form.currentAvatar.url = uploadResult.fullUrl;
      form.avatarUrl = uploadResult.fullUrl;
      console.log('头像上传并保存成功:', form.currentAvatar.name);
    }
  } catch (error) {
    console.error('头像上传失败:', error);
@@ -299,9 +365,7 @@
    
    if (form.currentAvatar.isExisting && form.currentAvatar.id) {
      // 删除已存在的头像文件
      console.log('删除已存在的头像文件:', form.currentAvatar.id);
      const result = await deleteMedia(form.currentAvatar.id);
      console.log('删除结果:', result);
      
      if (result) {
        form.currentAvatar = null;
@@ -346,8 +410,12 @@
      majorIds: form.specialtyIds?.length ? form.specialtyIds.map(id => parseInt(id)) : undefined
    }
    // 只有在新建或密码被修改时才包含密码字段
    if (!isEdit.value || isPasswordModified.value) {
      submitData.password = form.password
    }
    const savedJudge = await JudgeApi.saveJudge(submitData)
    console.log('评委保存成功:', savedJudge);
    
    // 2. 上传新选择的头像文件
    if (savedJudge.id) {
@@ -415,7 +483,6 @@
    if (form.currentAvatar?.isExisting && form.currentAvatar.id) {
      try {
        await deleteMedia(form.currentAvatar.id);
        console.log('已删除旧头像');
      } catch (error) {
        console.warn('删除旧头像失败,继续上传新头像:', error);
      }