基本功能实现
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