index.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <template>
  2. <view class="roadmap-page">
  3. <view class="section-card">
  4. <text class="section-title">路演材料上传</text>
  5. <text class="card-desc">上传您小组的路演陈述材料</text>
  6. <view class="form-item">
  7. <text class="form-label">路演主题陈述</text>
  8. <textarea class="form-textarea" v-model="proposition" placeholder="请描述您小组的路演主题..." :maxlength="1000" />
  9. </view>
  10. <view class="form-item">
  11. <text class="form-label">附件材料</text>
  12. <button class="upload-btn" @click="chooseFile">选择文件/图片</button>
  13. <image v-if="fileUrl" :src="fileUrl" class="preview-img" mode="aspectFit" />
  14. <text v-if="fileName" class="file-name">{{ fileName }}</text>
  15. </view>
  16. <button class="submit-btn" @click="handleSubmit" :loading="loading" :disabled="loading || !proposition">提交路演材料</button>
  17. </view>
  18. </view>
  19. </template>
  20. <script>
  21. import { uploadRoadmap, uploadFile } from '@/utils/api.js'
  22. import { guardPage } from '@/utils/guard.js'
  23. export default {
  24. data() {
  25. return {
  26. proposition: '',
  27. fileUrl: '',
  28. fileName: '',
  29. filePath: '',
  30. loading: false
  31. }
  32. },
  33. methods: {
  34. chooseFile() {
  35. var self = this
  36. uni.chooseImage({
  37. count: 1,
  38. sizeType: ['compressed'],
  39. sourceType: ['album', 'camera'],
  40. success: function(res) {
  41. self.filePath = res.tempFilePaths[0]
  42. self.fileName = res.tempFilePaths[0].split('/').pop()
  43. self.fileUrl = res.tempFilePaths[0]
  44. }
  45. })
  46. },
  47. handleSubmit() {
  48. if (!guardPage()) return
  49. if (!this.proposition.trim()) {
  50. uni.showToast({ title: '请输入路演主题', icon: 'none' })
  51. return
  52. }
  53. if (this.loading) return
  54. this.loading = true
  55. var self = this
  56. var doSubmit = function(files) {
  57. return uploadRoadmap({ proposition: self.proposition, files: files })
  58. }
  59. var p = this.filePath ? uploadFile(this.filePath).then(function(r) { return r.data.url }) : Promise.resolve(null)
  60. p.then(function(url) {
  61. return doSubmit(url)
  62. }).then(function() {
  63. uni.showToast({ title: '提交成功', icon: 'success' })
  64. setTimeout(function() { uni.navigateBack() }, 800)
  65. }).catch(function(err) {
  66. uni.showToast({ title: (err && err.message) || '提交失败', icon: 'none' })
  67. }).finally(function() {
  68. self.loading = false
  69. })
  70. }
  71. }
  72. }
  73. </script>
  74. <style scoped>
  75. .roadmap-page { min-height: 100vh; background: #F5F5F5; padding: 32rpx; }
  76. .section-card { background: #FFF; border-radius: 16rpx; padding: 32rpx; }
  77. .section-title { display: block; font-size: 32rpx; font-weight: 700; color: #1E293B; margin-bottom: 12rpx; border-left: 8rpx solid #F97316; padding-left: 16rpx; }
  78. .card-desc { display: block; font-size: 26rpx; color: #64748B; margin-bottom: 32rpx; }
  79. .form-item { margin-bottom: 28rpx; }
  80. .form-label { display: block; font-size: 28rpx; color: #1E293B; font-weight: 500; margin-bottom: 12rpx; }
  81. .form-textarea { width: 100%; min-height: 240rpx; border: 2rpx solid #E2E8F0; border-radius: 8rpx; padding: 20rpx; font-size: 28rpx; color: #1E293B; background: #F8FAFC; }
  82. .upload-btn { width: 100%; height: 72rpx; line-height: 72rpx; background: #FFF7ED; color: #F97316; font-size: 28rpx; border: 2rpx dashed #F97316; border-radius: 8rpx; margin-bottom: 16rpx; }
  83. .preview-img { width: 100%; height: 250rpx; border-radius: 8rpx; margin-bottom: 12rpx; }
  84. .file-name { font-size: 24rpx; color: #64748B; }
  85. .submit-btn { width: 100%; height: 88rpx; line-height: 88rpx; background: #F97316; color: #FFF; font-size: 30rpx; font-weight: 600; border-radius: 44rpx; border: none; margin-top: 16rpx; }
  86. .submit-btn:active { opacity: 0.85; }
  87. </style>