基本功能实现

Change-Id: I4fb8dfa2eed093c13d7c1e4304c4b4d012512ba9
diff --git a/src/views/torrent/UploadView.vue b/src/views/torrent/UploadView.vue
new file mode 100644
index 0000000..d99b446
--- /dev/null
+++ b/src/views/torrent/UploadView.vue
@@ -0,0 +1,506 @@
+<template>
+  <div class="upload-page">
+    <div class="page-header">
+      <h1>上传种子</h1>
+      <p class="page-description">分享你的资源,为社区做贡献</p>
+    </div>
+
+    <div class="upload-form">
+      <el-form
+        ref="uploadFormRef"
+        :model="uploadForm"
+        :rules="formRules"
+        label-width="120px"
+        size="large"
+      >
+        <!-- 种子文件上传 -->
+        <el-form-item label="种子文件" prop="torrentFile" required>
+          <el-upload
+            ref="torrentUploadRef"
+            :auto-upload="false"
+            :limit="1"
+            accept=".torrent"
+            :on-change="handleTorrentChange"
+            :on-remove="handleTorrentRemove"
+            :before-upload="beforeTorrentUpload"
+            drag
+            class="torrent-upload"
+          >
+            <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
+            <div class="el-upload__text">
+              将 .torrent 文件拖到此处,或<em>点击上传</em>
+            </div>
+            <template #tip>
+              <div class="el-upload__tip">
+                只能上传 .torrent 文件,且不超过 10MB
+              </div>
+            </template>
+          </el-upload>
+        </el-form-item>
+
+        <!-- 基本信息 -->
+        <el-form-item label="资源标题" prop="title" required>
+          <el-input
+            v-model="uploadForm.title"
+            placeholder="请输入资源标题"
+            maxlength="200"
+            show-word-limit
+          />
+        </el-form-item>
+
+        <el-form-item label="资源分类" prop="category" required>
+          <el-select v-model="uploadForm.category" placeholder="请选择分类">
+            <el-option label="电影" value="movie" />
+            <el-option label="电视剧" value="tv" />
+            <el-option label="音乐" value="music" />
+            <el-option label="软件" value="software" />
+            <el-option label="游戏" value="game" />
+            <el-option label="电子书" value="ebook" />
+            <el-option label="其他" value="other" />
+          </el-select>
+        </el-form-item>
+
+        <el-form-item label="子分类" prop="subcategory">
+          <el-select v-model="uploadForm.subcategory" placeholder="请选择子分类">
+            <el-option
+              v-for="sub in getSubcategories(uploadForm.category)"
+              :key="sub.value"
+              :label="sub.label"
+              :value="sub.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <!-- 详细描述 -->
+        <el-form-item label="资源描述" prop="description">
+          <el-input
+            v-model="uploadForm.description"
+            type="textarea"
+            :rows="6"
+            placeholder="请详细描述资源内容,包括格式、质量、语言等信息"
+            maxlength="2000"
+            show-word-limit
+          />
+        </el-form-item>
+
+        <!-- 标签 -->
+        <el-form-item label="标签">
+          <div class="tags-input">
+            <el-tag
+              v-for="tag in uploadForm.tags"
+              :key="tag"
+              closable
+              @close="removeTag(tag)"
+              class="tag-item"
+            >
+              {{ tag }}
+            </el-tag>
+            <el-input
+              v-if="tagInputVisible"
+              ref="tagInputRef"
+              v-model="tagInputValue"
+              size="small"
+              @keyup.enter="addTag"
+              @blur="addTag"
+              class="tag-input"
+            />
+            <el-button
+              v-else
+              size="small"
+              @click="showTagInput"
+              class="add-tag-btn"
+            >
+              + 添加标签
+            </el-button>
+          </div>
+        </el-form-item>
+
+        <!-- 封面图片 -->
+        <el-form-item label="封面图片">
+          <el-upload
+            ref="imageUploadRef"
+            :auto-upload="false"
+            :limit="1"
+            accept="image/*"
+            :on-change="handleImageChange"
+            :on-remove="handleImageRemove"
+            list-type="picture-card"
+            class="image-upload"
+          >
+            <el-icon><Plus /></el-icon>
+            <template #tip>
+              <div class="el-upload__tip">
+                支持 JPG、PNG 格式,建议尺寸 300x400,不超过 5MB
+              </div>
+            </template>
+          </el-upload>
+        </el-form-item>
+
+        <!-- 高级选项 -->
+        <el-form-item>
+          <el-collapse>
+            <el-collapse-item title="高级选项" name="advanced">
+              <el-form-item label="免费时间">
+                <el-select v-model="uploadForm.freeTime" placeholder="选择免费时间">
+                  <el-option label="永久免费" value="forever" />
+                  <el-option label="24小时" value="24h" />
+                  <el-option label="48小时" value="48h" />
+                  <el-option label="7天" value="7d" />
+                  <el-option label="30天" value="30d" />
+                </el-select>
+              </el-form-item>
+
+              <el-form-item label="匿名上传">
+                <el-switch v-model="uploadForm.anonymous" />
+                <span class="form-tip">开启后将不显示上传者信息</span>
+              </el-form-item>
+
+              <el-form-item label="允许HR">
+                <el-switch v-model="uploadForm.allowHR" />
+                <span class="form-tip">允许此种子参与HR考核</span>
+              </el-form-item>
+            </el-collapse-item>
+          </el-collapse>
+        </el-form-item>
+
+        <!-- 提交按钮 -->
+        <el-form-item>
+          <div class="submit-buttons">
+            <el-button @click="resetForm">重置</el-button>
+            <el-button type="primary" @click="submitForm" :loading="uploading">
+              {{ uploading ? '上传中...' : '提交种子' }}
+            </el-button>
+          </div>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script>
+import { ref, reactive, nextTick } from 'vue'
+import { useRouter } from 'vue-router'
+import { ElMessage } from 'element-plus'
+import {
+  UploadFilled,
+  Plus
+} from '@element-plus/icons-vue'
+
+export default {
+  name: 'UploadView',
+  setup() {
+    const router = useRouter()
+    const uploadFormRef = ref(null)
+    const torrentUploadRef = ref(null)
+    const imageUploadRef = ref(null)
+    const tagInputRef = ref(null)
+    
+    const uploading = ref(false)
+    const tagInputVisible = ref(false)
+    const tagInputValue = ref('')
+    
+    const uploadForm = reactive({
+      torrentFile: null,
+      title: '',
+      category: '',
+      subcategory: '',
+      description: '',
+      tags: [],
+      coverImage: null,
+      freeTime: '',
+      anonymous: false,
+      allowHR: true
+    })
+    
+    const formRules = {
+      title: [
+        { required: true, message: '请输入资源标题', trigger: 'blur' },
+        { min: 5, max: 200, message: '标题长度在 5 到 200 个字符', trigger: 'blur' }
+      ],
+      category: [
+        { required: true, message: '请选择资源分类', trigger: 'change' }
+      ],
+      description: [
+        { min: 10, max: 2000, message: '描述长度在 10 到 2000 个字符', trigger: 'blur' }
+      ]
+    }
+    
+    const subcategories = {
+      movie: [
+        { label: '动作片', value: 'action' },
+        { label: '喜剧片', value: 'comedy' },
+        { label: '科幻片', value: 'scifi' },
+        { label: '恐怖片', value: 'horror' },
+        { label: '剧情片', value: 'drama' }
+      ],
+      tv: [
+        { label: '美剧', value: 'us' },
+        { label: '国产剧', value: 'cn' },
+        { label: '日韩剧', value: 'asia' },
+        { label: '英剧', value: 'uk' },
+        { label: '纪录片', value: 'documentary' }
+      ],
+      music: [
+        { label: '流行音乐', value: 'pop' },
+        { label: '古典音乐', value: 'classical' },
+        { label: '摇滚音乐', value: 'rock' },
+        { label: '电子音乐', value: 'electronic' },
+        { label: '其他', value: 'other' }
+      ],
+      software: [
+        { label: '操作系统', value: 'os' },
+        { label: '办公软件', value: 'office' },
+        { label: '开发工具', value: 'dev' },
+        { label: '设计软件', value: 'design' },
+        { label: '其他', value: 'other' }
+      ],
+      game: [
+        { label: 'PC游戏', value: 'pc' },
+        { label: '主机游戏', value: 'console' },
+        { label: '手机游戏', value: 'mobile' },
+        { label: '其他', value: 'other' }
+      ]
+    }
+    
+    const getSubcategories = (category) => {
+      return subcategories[category] || []
+    }
+    
+    const handleTorrentChange = (file) => {
+      uploadForm.torrentFile = file.raw
+      // 这里可以解析torrent文件获取基本信息
+      parseTorrentFile(file.raw)
+    }
+    
+    const handleTorrentRemove = () => {
+      uploadForm.torrentFile = null
+    }
+    
+    const beforeTorrentUpload = (file) => {
+      const isTorrent = file.type === 'application/x-bittorrent' || file.name.endsWith('.torrent')
+      const isLt10M = file.size / 1024 / 1024 < 10
+      
+      if (!isTorrent) {
+        ElMessage.error('只能上传 .torrent 文件!')
+        return false
+      }
+      if (!isLt10M) {
+        ElMessage.error('种子文件大小不能超过 10MB!')
+        return false
+      }
+      return true
+    }
+    
+    const parseTorrentFile = (file) => {
+      // 这里应该实现torrent文件解析
+      // 可以使用 parse-torrent 库
+      console.log('解析种子文件:', file.name)
+      
+      // 模拟解析结果自动填入表单
+      if (!uploadForm.title) {
+        uploadForm.title = file.name.replace('.torrent', '')
+      }
+    }
+    
+    const handleImageChange = (file) => {
+      uploadForm.coverImage = file.raw
+    }
+    
+    const handleImageRemove = () => {
+      uploadForm.coverImage = null
+    }
+    
+    const showTagInput = () => {
+      tagInputVisible.value = true
+      nextTick(() => {
+        tagInputRef.value?.focus()
+      })
+    }
+    
+    const addTag = () => {
+      const tag = tagInputValue.value.trim()
+      if (tag && !uploadForm.tags.includes(tag)) {
+        uploadForm.tags.push(tag)
+      }
+      tagInputVisible.value = false
+      tagInputValue.value = ''
+    }
+    
+    const removeTag = (tag) => {
+      const index = uploadForm.tags.indexOf(tag)
+      if (index > -1) {
+        uploadForm.tags.splice(index, 1)
+      }
+    }
+    
+    const submitForm = async () => {
+      if (!uploadForm.torrentFile) {
+        ElMessage.error('请上传种子文件')
+        return
+      }
+      
+      try {
+        await uploadFormRef.value?.validate()
+        
+        uploading.value = true
+        
+        // 模拟上传过程
+        await new Promise(resolve => setTimeout(resolve, 2000))
+        
+        ElMessage.success('种子上传成功!')
+        router.push('/torrents')
+        
+      } catch (error) {
+        console.error('表单验证失败:', error)
+      } finally {
+        uploading.value = false
+      }
+    }
+    
+    const resetForm = () => {
+      uploadFormRef.value?.resetFields()
+      uploadForm.torrentFile = null
+      uploadForm.coverImage = null
+      uploadForm.tags = []
+      torrentUploadRef.value?.clearFiles()
+      imageUploadRef.value?.clearFiles()
+    }
+    
+    return {
+      uploadFormRef,
+      torrentUploadRef,
+      imageUploadRef,
+      tagInputRef,
+      uploading,
+      tagInputVisible,
+      tagInputValue,
+      uploadForm,
+      formRules,
+      getSubcategories,
+      handleTorrentChange,
+      handleTorrentRemove,
+      beforeTorrentUpload,
+      handleImageChange,
+      handleImageRemove,
+      showTagInput,
+      addTag,
+      removeTag,
+      submitForm,
+      resetForm,
+      UploadFilled,
+      Plus
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.upload-page {
+  max-width: 800px;
+  margin: 0 auto;
+  padding: 24px;
+}
+
+.page-header {
+  text-align: center;
+  margin-bottom: 32px;
+  
+  h1 {
+    font-size: 28px;
+    font-weight: 600;
+    color: #2c3e50;
+    margin: 0 0 8px 0;
+  }
+  
+  .page-description {
+    font-size: 16px;
+    color: #7f8c8d;
+    margin: 0;
+  }
+}
+
+.upload-form {
+  background: #fff;
+  border-radius: 12px;
+  padding: 32px;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+  
+  .torrent-upload {
+    width: 100%;
+    
+    :deep(.el-upload-dragger) {
+      width: 100%;
+      height: 180px;
+      border: 2px dashed #d9d9d9;
+      border-radius: 8px;
+      
+      &:hover {
+        border-color: #409eff;
+      }
+    }
+  }
+  
+  .tags-input {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+    align-items: center;
+    
+    .tag-item {
+      margin: 0;
+    }
+    
+    .tag-input {
+      width: 100px;
+    }
+    
+    .add-tag-btn {
+      border: 1px dashed #d9d9d9;
+      color: #999;
+      
+      &:hover {
+        border-color: #409eff;
+        color: #409eff;
+      }
+    }
+  }
+  
+  .image-upload {
+    :deep(.el-upload--picture-card) {
+      width: 148px;
+      height: 148px;
+    }
+  }
+  
+  .form-tip {
+    margin-left: 8px;
+    font-size: 12px;
+    color: #909399;
+  }
+  
+  .submit-buttons {
+    display: flex;
+    gap: 16px;
+    justify-content: center;
+    margin-top: 24px;
+  }
+}
+
+@media (max-width: 768px) {
+  .upload-page {
+    padding: 16px;
+  }
+  
+  .upload-form {
+    padding: 24px 16px;
+  }
+  
+  .submit-buttons {
+    flex-direction: column;
+    
+    .el-button {
+      width: 100%;
+    }
+  }
+}
+</style>
\ No newline at end of file