lrj
1 天以前 7ad9c3c93f0cc103347ae2e2429e0122fb512e24
web/src/views/ActivityForm.vue
@@ -65,19 +65,9 @@
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="比赛地址" prop="address">
              <el-input v-model="form.address" placeholder="请输入比赛地址" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="人数" prop="playerMax">
              <el-input-number v-model="form.playerMax" :min="1" :max="9999" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="比赛地址" prop="address">
          <el-input v-model="form.address" placeholder="请输入比赛地址" />
        </el-form-item>
        <el-form-item label="比赛描述" prop="description">
          <el-input
@@ -89,7 +79,10 @@
        </el-form-item>
        <!-- 图片/视频上传 -->
        <el-divider content-position="left">图片/视频</el-divider>
        <el-divider content-position="left">
          图片/视频
          <span class="media-description">支持jpg/png/mp4,最多3个文件</span>
        </el-divider>
        
        <el-form-item label="媒体文件">
          <div class="media-upload-section">
@@ -119,7 +112,7 @@
              <!-- 添加按钮 -->
              <el-upload
                v-if="form.mediaFiles.length < 3"
                class="media-uploader"
                class="media-uploader media-uploader-left"
                :show-file-list="false"
                :before-upload="beforeMediaUpload"
                action="#"
@@ -130,7 +123,6 @@
                <div class="upload-placeholder">
                  <el-icon class="upload-icon"><Plus /></el-icon>
                  <div class="upload-text">添加图片/视频</div>
                  <div class="upload-tip">支持jpg/png/mp4,最多3个文件</div>
                </div>
              </el-upload>
            </div>
@@ -146,35 +138,33 @@
            <el-tab-pane label="比赛阶段" name="stages">
              <div class="stages-header">
                <span>比赛阶段</span>
                <el-button size="small" type="primary" @click="addStage">添加阶段</el-button>
                <div class="stages-controls">
                  <el-button size="small" type="primary" @click="addStage">添加阶段</el-button>
                </div>
              </div>
              
              <div v-if="form.stages && form.stages.length > 0" class="stages-list">
                <div v-for="(stage, index) in form.stages" :key="index" class="stage-item">
              <div v-if="form.value && form.value.stages && form.value.stages.length > 0" class="stages-list">
                <div v-for="(stage, index) in sortedFormStages" :key="index" class="stage-item">
                  <div class="stage-info">
                    <div class="stage-name">{{ stage.name || '未命名阶段' }}</div>
                    <div class="stage-header">
                      <span class="stage-order">{{ stage.sortOrder || '-' }}</span>
                      <span class="stage-name">{{ stage.name || '未命名阶段' }}</span>
                    </div>
                    <div class="stage-details">
                      <span class="detail-item">
                        <el-icon><Clock /></el-icon>
                        {{ formatDateTime(stage.matchTime) }}
                      </span>
                      <span class="detail-item">
                        <el-icon><User /></el-icon>
                        {{ stage.playerMax || 0 }} 人
                      </span>
                      <span class="detail-item">
                        <el-icon><UserFilled /></el-icon>
                        实际: {{ stage.actualPlayerCount || 0 }} 人
                      </span>
                      <el-tag :type="stage.state === 1 ? 'success' : 'info'" size="small">
                        {{ stage.state === 1 ? '进行中' : '未开始' }}
                      </el-tag>
                    </div>
                  </div>
                  <div class="stage-actions">
                    <el-button size="small" @click="editStage(stage, index)">编辑</el-button>
                    <el-button size="small" @click="editStage(stage, getOriginalStageIndex(stage))">编辑</el-button>
                    <el-button size="small" @click="closeStage(stage)" v-if="stage.state === 1">关闭</el-button>
                    <el-button size="small" type="danger" @click="removeStage(index)">删除</el-button>
                    <el-button size="small" type="danger" @click="removeStage(getOriginalStageIndex(stage))">删除</el-button>
                  </div>
                </div>
              </div>
@@ -203,9 +193,8 @@
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="180" align="center">
                <el-table-column label="操作" width="100" align="center">
                  <template #default="{ row, $index }">
                    <el-button size="small" @click="editJudge(row, $index)">编辑</el-button>
                    <el-button size="small" type="danger" @click="removeJudge($index)">删除</el-button>
                  </template>
                </el-table-column>
@@ -214,37 +203,7 @@
              <el-empty v-if="!form.judges || form.judges.length === 0" description="暂无评委" />
            </el-tab-pane>
            <!-- 学员列表 -->
            <el-tab-pane label="学员列表" name="students">
              <div class="students-header">
                <span>学员列表</span>
              </div>
              <el-table :data="form.students" style="width: 100%" border>
                <el-table-column label="学员名称" prop="name" />
                <el-table-column label="最后参与的比赛阶段" width="200">
                  <template #default="{ row }">
                    {{ getLastStage(row) }}
                  </template>
                </el-table-column>
                <el-table-column label="操作" width="250" align="center">
                  <template #default="{ row, $index }">
                    <el-button size="small" @click="viewStudent(row, $index)">查看</el-button>
                    <el-button size="small" type="primary" @click="rateStudent(row, $index)">评分</el-button>
                    <el-button size="small" @click="commentStudent(row, $index)">点评</el-button>
                    <el-button
                      size="small"
                      :type="row.isAdvanced ? 'success' : 'warning'"
                      @click="toggleAdvancement(row, $index)"
                    >
                      {{ row.isAdvanced ? '已晋级' : '晋级' }}
                    </el-button>
                  </template>
                </el-table-column>
              </el-table>
              <el-empty v-if="!form.students || form.students.length === 0" description="暂无学员" />
            </el-tab-pane>
          </el-tabs>
        </div>
@@ -274,6 +233,26 @@
          <el-input v-model="currentStage.name" placeholder="请输入阶段名称" maxlength="30" />
        </el-form-item>
        
        <el-form-item label="比赛阶段顺序" prop="sortOrder">
          <el-select v-model="currentStage.sortOrder" placeholder="请选择阶段顺序" style="width: 100%">
            <el-option label="1" :value="1" />
            <el-option label="2" :value="2" />
            <el-option label="3" :value="3" />
            <el-option label="4" :value="4" />
            <el-option label="5" :value="5" />
          </el-select>
        </el-form-item>
        <el-form-item label="学员人数" prop="playerMax">
          <el-input-number
            v-model="currentStage.playerMax"
            :min="1"
            :max="1000"
            placeholder="请输入学员人数"
            style="width: 100%"
          />
        </el-form-item>
        <el-form-item label="评分模板">
          <el-select v-model="currentStage.ratingSchemeId" placeholder="继承比赛模板" style="width: 100%">
            <el-option label="继承比赛模板" :value="null" />
@@ -299,10 +278,6 @@
        
        <el-form-item label="阶段地址">
          <el-input v-model="currentStage.address" placeholder="请输入阶段地址" />
        </el-form-item>
        <el-form-item label="人数">
          <el-input-number v-model="currentStage.playerMax" :min="1" :max="9999" style="width: 100%" />
        </el-form-item>
        
        <el-form-item label="阶段描述">
@@ -347,14 +322,16 @@
        
        <!-- 阶段选择 -->
        <div style="margin-bottom: 16px;">
          <el-form-item label="添加到阶段:" label-width="100px">
            <el-select v-model="selectedStageOption" style="width: 100%;" @change="handleStageChange">
              <el-option label="所有阶段" value="all" />
          <el-form-item label="负责阶段:" label-width="100px">
            <!-- 调试信息 -->
            <el-select v-model="selectedStageOptions" multiple style="width: 100%;" placeholder="请选择负责的阶段">
              <!-- 使用计算属性 -->
              <el-option 
                v-for="stage in form.stages"
                :key="stage.id"
                :label="stage.name"
                :value="stage.id ? stage.id.toString() : ''"
                v-for="option in stageOptions"
                :key="option.value"
                :label="option.label"
                :value="option.value"
              />
            </el-select>
          </el-form-item>
@@ -419,7 +396,7 @@
          <el-select v-model="currentStudent.lastStageId" placeholder="请选择阶段" style="width: 100%">
            <el-option label="无" :value="null" />
            <el-option 
              v-for="stage in form.stages"
              v-for="stage in (form.value?.stages || [])"
              :key="stage.id" 
              :label="stage.name" 
              :value="stage.id"
@@ -439,7 +416,7 @@
</template>
<script setup>
import { ref, onMounted, computed } from 'vue'
import { ref, onMounted, computed, nextTick } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, VideoPlay, Clock, User, UserFilled, Search } from '@element-plus/icons-vue'
@@ -462,6 +439,9 @@
// Tab相关
const activeTab = ref('stages')
// 阶段数量选择
const selectedStageCount = ref(1)
// 阶段编辑弹窗相关
const stageDialogVisible = ref(false)
const currentStageIndex = ref(-1)
@@ -472,7 +452,6 @@
  matchTime: '',
  address: '',
  ratingSchemeId: null,
  playerMax: null,
  state: 1,
  actualPlayerCount: 0
})
@@ -490,7 +469,7 @@
// 评委选择相关
const allJudges = ref([])
const judgeSearchText = ref('')
const selectedStageOption = ref('all')
const selectedStageOptions = ref([])
const selectedJudges = ref([])
const judgeLoading = ref(false)
@@ -524,7 +503,7 @@
  matchTime: '',
  address: '',
  ratingSchemeId: null,
  playerMax: 100,
  playerMax: null,
  state: 1,
  stages: [],
  judges: [],
@@ -534,6 +513,31 @@
// 计算属性
const isEdit = computed(() => !!route.params.id)
// 按sortOrder排序的阶段列表
const sortedFormStages = computed(() => {
  if (!form.value.stages) return []
  return [...form.value.stages].sort((a, b) => {
    const orderA = a.sortOrder || 999
    const orderB = b.sortOrder || 999
    return orderA - orderB
  })
})
// 用于下拉框的阶段选项
const stageOptions = computed(() => {
  if (!form.value?.stages) {
    return []
  }
  return form.value.stages
    .filter(stage => stage && stage.id != null)
    .map(stage => ({
      label: stage.name,
      value: stage.id.toString(),
      stage: stage
    }))
})
// 表单验证规则
const rules = {
@@ -553,6 +557,10 @@
  name: [
    { required: true, message: '请输入阶段名称', trigger: 'blur' },
    { max: 30, message: '阶段名称不能超过30个字符', trigger: 'blur' }
  ],
  playerMax: [
    { required: true, message: '请输入学员人数', trigger: 'blur' },
    { type: 'number', min: 1, max: 1000, message: '学员人数必须在1-1000之间', trigger: 'blur' }
  ]
}
@@ -573,7 +581,6 @@
    judgeLoading.value = true
    const judges = await getAllJudges()
    allJudges.value = judges || []
    console.log('加载评委列表成功:', allJudges.value.length, '个评委')
  } catch (error) {
    console.error('加载评委列表失败:', error)
    ElMessage.error('加载评委列表失败: ' + error.message)
@@ -590,6 +597,7 @@
  try {
    loading.value = true
    const activity = await getActivity(route.params.id)
    if (activity) {
      form.value = {
        id: activity.id,
@@ -599,7 +607,7 @@
        matchTime: activity.matchTime || '',
        address: activity.address || '',
        ratingSchemeId: activity.ratingSchemeId,
        playerMax: activity.playerMax || 100,
        playerMax: activity.playerMax,
        state: activity.state,
        stages: activity.stages || [],
        judges: activity.judges || [],
@@ -609,12 +617,8 @@
      // 加载并回填已上传媒体:targetType=2 假设为“活动”,如不同请调整
      try {
        const medias = await getMediasByTarget(MediaTargetType.ACTIVITY, parseInt(activity.id))
        console.log('=== 加载活动媒体调试信息 ===')
        console.log('活动ID:', activity.id)
        console.log('获取到的媒体数据:', medias)
        
        form.value.mediaFiles = (medias || []).map(m => {
          console.log('处理媒体文件:', m)
          const isImage = (m.mediaType === 1) || (m.fileExt && ['jpg','jpeg','png','gif','webp'].includes(m.fileExt.toLowerCase()))
          const isVideo = (m.mediaType === 2) || (m.fileExt && ['mp4','mov','m4v','avi','mkv'].includes(m.fileExt.toLowerCase()))
          const mediaItem = {
@@ -625,13 +629,14 @@
            uploaded: true, // 标记为已上传,不需要重新上传
            file: null // 已保存的文件没有file对象
          }
          console.log('转换后的媒体项:', mediaItem)
          return mediaItem
        })
        console.log('最终的mediaFiles:', form.value.mediaFiles)
      } catch (e) {
        console.error('加载活动媒体失败:', e)
      }
      // 设置阶段数量选择器的值
      selectedStageCount.value = (form.value && form.value.stages) ? form.value.stages.length || 1 : 1
    }
  } catch (error) {
    console.error('加载比赛数据失败:', error)
@@ -642,6 +647,47 @@
}
// 阶段管理
// 阶段数量变化处理
const onStageCountChange = (count) => {
  if (!count || !form.value || !form.value.stages) return
  // 如果当前阶段数量少于选择的数量,自动添加阶段
  while (form.value.stages.length < count) {
    const stageIndex = form.value.stages.length + 1
    form.value.stages.push({
      id: null,
      name: getDefaultStageName(stageIndex),
      description: '',
      matchTime: '',
      address: form.value.address || '',
      ratingSchemeId: form.value.ratingSchemeId,
      sortOrder: stageIndex,
      state: 1,
      actualPlayerCount: 0
    })
  }
  // 如果当前阶段数量多于选择的数量,删除多余的阶段
  if (form.value.stages.length > count) {
    form.value.stages = form.value.stages.slice(0, count)
  }
  ElMessage.success(`已设置为${count}个阶段`)
}
// 获取默认阶段名称 - 使用更灵活的命名方式,避免硬编码特定阶段名称
const getDefaultStageName = (index) => {
  // 提供一些常用的阶段名称建议,但不强制使用
  const suggestedNames = ['', '第一阶段', '第二阶段', '第三阶段', '第四阶段', '第五阶段']
  return suggestedNames[index] || `第${index}阶段`
}
// 获取阶段在原始数组中的索引
const getOriginalStageIndex = (stage) => {
  if (!form.value || !form.value.stages) return -1
  return form.value.stages.findIndex(s => s === stage)
}
const addStage = () => {
  currentStageIndex.value = -1
  resetStageForm()
@@ -655,6 +701,8 @@
}
const removeStage = async (index) => {
  if (!form.value || !form.value.stages) return
  try {
    await ElMessageBox.confirm('确定要删除这个阶段吗?', '提示', {
      confirmButtonText: '确定',
@@ -662,6 +710,15 @@
      type: 'warning'
    })
    form.value.stages.splice(index, 1)
    // 重新排序sortOrder
    form.value.stages.forEach((stage, idx) => {
      stage.sortOrder = idx + 1
    })
    // 更新选择的阶段数量
    selectedStageCount.value = form.value.stages.length
    ElMessage.success('删除成功')
  } catch {
    // 用户取消删除
@@ -683,12 +740,16 @@
}
const saveStage = async () => {
  if (!form.value || !form.value.stages) return
  try {
    await stageFormRef.value.validate()
    
    if (currentStageIndex.value === -1) {
      // 新增阶段
      form.value.stages.push({ ...currentStage.value })
      // 新增阶段 - 设置正确的sortOrder
      const newStage = { ...currentStage.value }
      newStage.sortOrder = form.value.stages.length + 1
      form.value.stages.push(newStage)
    } else {
      // 编辑阶段
      form.value.stages[currentStageIndex.value] = { ...currentStage.value }
@@ -710,6 +771,7 @@
    address: '',
    ratingSchemeId: null,
    playerMax: null,
    sortOrder: null, // 将在saveStage中设置正确的值
    state: 1,
    actualPlayerCount: 0
  }
@@ -742,6 +804,11 @@
}
const removeJudge = async (index) => {
  if (!form.value || !form.value.judges) {
    ElMessage.error('表单数据未初始化')
    return
  }
  try {
    await ElMessageBox.confirm('确定要删除这个评委吗?', '提示', {
      confirmButtonText: '确定',
@@ -756,26 +823,40 @@
}
const getJudgeStages = (judge) => {
  if (!judge.stageIds || !form.value.stages) return []
  return form.value.stages.filter(stage => judge.stageIds.includes(stage.id))
  if (!judge.stageIds || !form.value || !form.value.stages) return []
  const stages = []
  // 检查比赛阶段
  judge.stageIds.forEach(stageId => {
    // 处理实际阶段ID
    const stage = form.value.stages.find(s => s.id === stageId)
    if (stage) {
      stages.push({
        id: stage.id,
        name: stage.name
      })
    }
  })
  return stages
}
const resetJudgeDialog = () => {
  judgeSearchText.value = ''
  selectedStageOption.value = 'all'
  // 清空阶段选择
  selectedStageOptions.value = []
  selectedJudges.value = []
}
const handleJudgeSearch = (value) => {
  console.log('搜索评委:', value)
  // 搜索评委
}
const handleStageChange = (value) => {
  console.log('选择阶段:', value)
}
const handleJudgeSelectionChange = (value) => {
  console.log('选择评委:', value)
  // 选择评委
}
const toggleSelectAll = () => {
@@ -797,6 +878,17 @@
    return
  }
  
  if (!form.value || !form.value.judges) {
    ElMessage.error('表单数据未初始化')
    return
  }
  // 如果有阶段但没有选择阶段,则提示
  if (form.value && form.value.stages && form.value.stages.length > 0 && selectedStageOptions.value.length === 0) {
    ElMessage.warning('请选择至少一个负责阶段')
    return
  }
  let addedCount = 0
  
  selectedJudges.value.forEach(judgeId => {
@@ -805,29 +897,35 @@
      // 检查是否已经存在
      const existingJudge = form.value.judges.find(j => j.id === judgeId)
      if (existingJudge) {
        // 更新现有评委的阶段
        if (selectedStageOption.value === 'all') {
          existingJudge.stageIds = form.value.stages.map(s => s.id).filter(id => id != null)
        } else {
          const stageId = parseInt(selectedStageOption.value)
          if (!existingJudge.stageIds.includes(stageId)) {
            existingJudge.stageIds.push(stageId)
          }
        // 更新现有评委的阶段,合并新选择的阶段
        if (selectedStageOptions.value.length > 0) {
          selectedStageOptions.value.forEach(stageId => {
            const stageIdInt = parseInt(stageId)
            if (!existingJudge.stageIds.includes(stageIdInt)) {
              existingJudge.stageIds.push(stageIdInt)
            }
          })
        }
      } else {
        // 添加新评委
        // 添加新评委,包含所有选择的阶段
        const stageIds = selectedStageOptions.value.length > 0
          ? selectedStageOptions.value.map(id => parseInt(id))
          : []
        const newJudge = {
          id: judge.id,
          name: judge.name,
          stageIds: selectedStageOption.value === 'all'
            ? form.value.stages.map(s => s.id).filter(id => id != null)
            : [parseInt(selectedStageOption.value)]
          stageIds: stageIds
        }
        form.value.judges.push(newJudge)
        addedCount++
      }
    }
  })
  // 清空选择
  selectedJudges.value = []
  selectedStageOptions.value = []
  
  judgeDialogVisible.value = false
  ElMessage.success(`成功添加 ${addedCount} 个评委`)
@@ -882,7 +980,7 @@
}
const getLastStage = (student) => {
  if (!student.lastStageId || !form.value.stages) return '无'
  if (!student.lastStageId || !form.value || !form.value.stages) return '无'
  const stage = form.value.stages.find(s => s.id === student.lastStageId)
  return stage ? stage.name : '无'
}
@@ -927,13 +1025,17 @@
    uploaded: false // 标记为未上传
  }
  
  form.value.mediaFiles.push(mediaFile)
  ElMessage.success('文件已选择,点击更新按钮时将上传')
  if (form.value && form.value.mediaFiles) {
    form.value.mediaFiles.push(mediaFile)
    ElMessage.success('文件已选择,点击更新按钮时将上传')
  }
  
  return false // 阻止el-upload的默认上传
}
const beforeMediaUpload = (file) => {
  if (!form.value || !form.value.mediaFiles) return false
  if (form.value.mediaFiles.length >= 3) {
    ElMessage.error('最多只能上传3个文件!')
    return false
@@ -998,6 +1100,8 @@
// 处理媒体文件上传
const handleMediaUpload = async (activityId) => {
  if (!form.value || !form.value.mediaFiles) return
  try {
    for (const mediaFile of form.value.mediaFiles) {
      // 跳过已经有 id 的媒体文件(已保存的)
@@ -1016,10 +1120,8 @@
      }
      
      try {
        console.log('开始上传文件:', mediaFile.name)
        // 1. 上传文件到服务器
        const uploadResult = await uploadFile(mediaFile.file)
        console.log('文件上传成功:', uploadResult)
        
        // 2. 保存媒体信息到数据库
        const mediaInput = {
@@ -1031,11 +1133,7 @@
          targetType: MediaTargetType.ACTIVITY, // 活动
          targetId: parseInt(activityId) // 转换为数字类型
        }
        console.log('准备保存媒体信息:', mediaInput)
        console.log('活动ID:', activityId)
        const savedMedia = await saveMedia(mediaInput)
        console.log(`媒体文件 ${mediaFile.name} 上传并保存成功:`, savedMedia)
        
        // 更新媒体文件信息
        mediaFile.id = savedMedia.id
@@ -1059,6 +1157,8 @@
// 提交表单
const handleSubmit = async () => {
  if (submitting.value) return
  if (!form.value) return
  try {
    await formRef.value.validate()
    
@@ -1066,8 +1166,6 @@
    
    // 准备保存数据,只包含后端支持的字段
    const saveData = {
      id: form.value.id,
      pid: form.value.pid || 0,
      name: form.value.name,
      description: form.value.description,
      signupDeadline: form.value.signupDeadline,
@@ -1076,21 +1174,41 @@
      ratingSchemeId: form.value.ratingSchemeId,
      playerMax: form.value.playerMax,
      state: form.value.state || 1,
      stages: form.value.stages ? form.value.stages.map(stage => ({
        id: stage.id,
        name: stage.name,
        description: stage.description,
        matchTime: stage.matchTime,
        address: stage.address,
        ratingSchemeId: stage.ratingSchemeId,
        playerMax: stage.playerMax,
        state: stage.state || 1
      })) : [],
      judges: form.value.judges ? form.value.judges.map(judge => ({
      stages: form.value.stages ? form.value.stages.map(stage => {
        const stageData = {
          name: stage.name,
          description: stage.description,
          matchTime: stage.matchTime,
          address: stage.address,
          playerMax: stage.playerMax,
          sortOrder: stage.sortOrder,
          state: stage.state || 1
        }
        // 只在有有效ID时才添加id字段
        if (stage.id) {
          stageData.id = stage.id
        }
        // 只在有有效ratingSchemeId时才添加该字段
        if (stage.ratingSchemeId) {
          stageData.ratingSchemeId = stage.ratingSchemeId
        }
        return stageData
      }) : [],
      judges: form.value.judges ? form.value.judges.filter(judge => judge.id && judge.name).map(judge => ({
        judgeId: judge.id,
        judgeName: judge.name,
        stageIds: judge.stageIds || []
      })) : []
    }
    // 如果是编辑模式,添加id字段
    if (isEdit.value && form.value.id) {
      saveData.id = form.value.id
    }
    // 如果有pid,添加pid字段
    if (form.value.pid) {
      saveData.pid = form.value.pid
    }
    
    const result = await saveActivity(saveData)
@@ -1134,6 +1252,11 @@
  await loadRatingSchemes()
  await loadAllJudges()
  await loadActivity()
  // 如果是新建模式且没有阶段,自动创建一个阶段
  if (!isEdit.value && form.value && form.value.stages && form.value.stages.length === 0) {
    onStageCountChange(1)
  }
})
</script>
@@ -1169,7 +1292,7 @@
.stage-header {
  display: flex;
  justify-content: space-between;
  justify-content: flex-start;
  align-items: center;
}
@@ -1271,11 +1394,32 @@
  flex: 1;
}
.stage-header {
  display: flex;
  align-items: center;
  margin-bottom: 8px;
}
.stage-order {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  background-color: #409eff;
  color: white;
  border-radius: 50%;
  font-size: 12px;
  font-weight: 600;
  flex-shrink: 0;
}
.stage-name {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
  margin-bottom: 8px;
  margin: 0;
  margin-left: 4px;
}
.stage-details {
@@ -1487,4 +1631,24 @@
  flex: 1;
  padding-left: 8px;
}
/* 媒体描述文本样式 */
.media-description {
  font-size: 12px;
  color: #909399;
  font-weight: normal;
  margin-left: 8px;
}
/* 媒体上传按钮 */
.media-uploader-left {
  margin-left: 16px;
}
.media-container {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  flex-wrap: wrap;
}
</style>