This commit is contained in:
162
miniprogram/src/pages/competition/project.tsx
Normal file
162
miniprogram/src/pages/competition/project.tsx
Normal file
@@ -0,0 +1,162 @@
|
||||
import { View, Text, Button, Image, Input, Textarea } from '@tarojs/components'
|
||||
import Taro, { useLoad } from '@tarojs/taro'
|
||||
import { useState } from 'react'
|
||||
import { getProjectDetail, createProject, updateProject, uploadProjectFile, submitProject, uploadMedia } from '../../api'
|
||||
import './project.scss'
|
||||
|
||||
export default function ProjectEdit() {
|
||||
const [project, setProject] = useState<any>({
|
||||
title: '',
|
||||
description: '',
|
||||
team_info: '',
|
||||
files: []
|
||||
})
|
||||
const [competitionId, setCompetitionId] = useState<string>('')
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [isEdit, setIsEdit] = useState(false)
|
||||
|
||||
useLoad((options) => {
|
||||
const { id, competitionId } = options
|
||||
if (id) {
|
||||
setIsEdit(true)
|
||||
fetchProject(id)
|
||||
} else if (competitionId) {
|
||||
setCompetitionId(competitionId)
|
||||
}
|
||||
})
|
||||
|
||||
const fetchProject = async (id) => {
|
||||
setLoading(true)
|
||||
try {
|
||||
const res = await getProjectDetail(id)
|
||||
setProject(res)
|
||||
setCompetitionId(res.competition)
|
||||
} catch (e) {
|
||||
Taro.showToast({ title: '加载项目失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInput = (key, value) => {
|
||||
setProject(prev => ({ ...prev, [key]: value }))
|
||||
}
|
||||
|
||||
const handleUploadCover = async () => {
|
||||
try {
|
||||
const { tempFilePaths } = await Taro.chooseImage({ count: 1 })
|
||||
if (!tempFilePaths.length) return
|
||||
|
||||
Taro.showLoading({ title: '上传中...' })
|
||||
|
||||
const res = await uploadMedia(tempFilePaths[0], 'image')
|
||||
handleInput('cover_image_url', res.file) // 假设返回 { file: 'url...' }
|
||||
|
||||
Taro.hideLoading()
|
||||
} catch (e) {
|
||||
Taro.hideLoading()
|
||||
Taro.showToast({ title: '上传失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
|
||||
const handleSave = async (submit = false) => {
|
||||
if (!project.title) {
|
||||
Taro.showToast({ title: '请输入项目标题', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
setLoading(true)
|
||||
try {
|
||||
const data = {
|
||||
competition: competitionId,
|
||||
title: project.title,
|
||||
description: project.description,
|
||||
team_info: project.team_info,
|
||||
cover_image_url: project.cover_image_url
|
||||
}
|
||||
|
||||
let res
|
||||
if (isEdit) {
|
||||
res = await updateProject(project.id, data)
|
||||
} else {
|
||||
res = await createProject(data)
|
||||
}
|
||||
|
||||
if (submit) {
|
||||
await submitProject(res.id)
|
||||
Taro.showToast({ title: '提交成功', icon: 'success' })
|
||||
setTimeout(() => Taro.navigateBack(), 1500)
|
||||
} else {
|
||||
Taro.showToast({ title: '保存成功', icon: 'success' })
|
||||
if (!isEdit) {
|
||||
// 创建变编辑
|
||||
setIsEdit(true)
|
||||
setProject(res)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Taro.showToast({ title: e.message || '操作失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (loading && !project.id && isEdit) return <View className='loading'>加载中...</View>
|
||||
|
||||
return (
|
||||
<View className='project-edit'>
|
||||
<View className='form-item'>
|
||||
<Text className='label'>项目标题</Text>
|
||||
<Input
|
||||
className='input'
|
||||
placeholder='请输入项目标题'
|
||||
value={project.title}
|
||||
onInput={e => handleInput('title', e.detail.value)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View className='form-item'>
|
||||
<Text className='label'>封面图</Text>
|
||||
<View className='upload-box' onClick={handleUploadCover}>
|
||||
{project.cover_image_url || project.display_cover_image ? (
|
||||
<Image
|
||||
className='preview'
|
||||
mode='aspectFill'
|
||||
src={project.cover_image_url || project.display_cover_image}
|
||||
/>
|
||||
) : (
|
||||
<Text className='placeholder'>点击上传封面</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='form-item'>
|
||||
<Text className='label'>项目介绍</Text>
|
||||
<Textarea
|
||||
className='textarea'
|
||||
placeholder='请输入项目详细介绍'
|
||||
value={project.description}
|
||||
onInput={e => handleInput('description', e.detail.value)}
|
||||
maxlength={2000}
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View className='form-item'>
|
||||
<Text className='label'>团队介绍</Text>
|
||||
<Textarea
|
||||
className='textarea small'
|
||||
placeholder='请输入团队成员信息'
|
||||
value={project.team_info}
|
||||
onInput={e => handleInput('team_info', e.detail.value)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* 附件列表略,暂不支持上传非图片附件 */}
|
||||
|
||||
<View className='footer-btns'>
|
||||
<Button className='btn save' onClick={() => handleSave(false)}>保存草稿</Button>
|
||||
<Button className='btn submit' onClick={() => handleSave(true)}>提交作品</Button>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user