index.vue 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. <template>
  2. <view class="upload-page">
  3. <view class="section-card">
  4. <text class="section-title">成果上传</text>
  5. <view class="form-item">
  6. <text class="form-label">账本类型</text>
  7. <picker :range="bookTypes" range-key="label" @change="onBookTypeChange">
  8. <view class="picker-display">{{ selectedBookType.label }} ▼</view>
  9. </picker>
  10. </view>
  11. <view class="form-item">
  12. <text class="form-label">上传类型</text>
  13. <radio-group @change="onTypeChange">
  14. <label class="radio-item"><radio value="deep" :checked="uploadForm.type === 'deep'" color="#F97316" />深度分析</label>
  15. <label class="radio-item"><radio value="taught" :checked="uploadForm.type === 'taught'" color="#F97316" />教学成果</label>
  16. </radio-group>
  17. </view>
  18. <view class="form-item">
  19. <label class="check-item">
  20. <checkbox :checked="uploadForm.desensitized" @tap="uploadForm.desensitized = !uploadForm.desensitized" color="#F97316" />
  21. <text>我已确认数据已脱敏处理</text>
  22. </label>
  23. </view>
  24. <button class="upload-btn" @click="chooseImage">选择截图</button>
  25. <image v-if="uploadImage" :src="uploadImage" class="preview-img" mode="aspectFit" />
  26. <button class="submit-btn" @click="handleUpload" :loading="loading" :disabled="!uploadForm.desensitized || !uploadImage || loading">提交</button>
  27. </view>
  28. <view class="section-card">
  29. <text class="section-title">我的上传记录</text>
  30. <view v-if="submissions.length === 0" class="empty-text">暂无记录</view>
  31. <view class="sub-item" v-for="(s, idx) in submissions" :key="idx">
  32. <view class="sub-header">
  33. <text class="sub-type">{{ bookLabel(s.bookType) }} · {{ s.type === 'deep' ? '深度分析' : '教学成果' }}</text>
  34. <text class="sub-status">{{ s.status }}</text>
  35. </view>
  36. <image v-if="s.image" :src="s.image" class="sub-thumb" mode="aspectFill" />
  37. </view>
  38. </view>
  39. </view>
  40. </template>
  41. <script>
  42. import { uploadSubmission, getMySubmissions, uploadFile } from '@/utils/api.js'
  43. import { guardPage } from '@/utils/guard.js'
  44. export default {
  45. data() {
  46. return {
  47. bookTypes: [
  48. { value: 'wealth', label: '财富账' },
  49. { value: 'health', label: '健康账' },
  50. { value: 'growth', label: '成长账' }
  51. ],
  52. uploadForm: {
  53. bookType: 'wealth',
  54. type: 'deep',
  55. desensitized: false,
  56. sampleFlag: 0
  57. },
  58. uploadImage: '',
  59. loading: false,
  60. submissions: []
  61. }
  62. },
  63. computed: {
  64. selectedBookType() {
  65. return this.bookTypes.find(b => b.value === this.uploadForm.bookType) || this.bookTypes[0]
  66. }
  67. },
  68. onShow() {
  69. if (!guardPage()) return
  70. this.loadSubmissions()
  71. },
  72. methods: {
  73. loadSubmissions() {
  74. var self = this
  75. getMySubmissions().then(function(resp) {
  76. self.submissions = resp.data || []
  77. }).catch(function() {})
  78. },
  79. onBookTypeChange(e) {
  80. this.uploadForm.bookType = this.bookTypes[e.detail.value].value
  81. },
  82. onTypeChange(e) {
  83. this.uploadForm.type = e.detail.value
  84. },
  85. chooseImage() {
  86. var self = this
  87. uni.chooseImage({
  88. count: 1,
  89. sizeType: ['compressed'],
  90. sourceType: ['album', 'camera'],
  91. success: function(res) {
  92. self.uploadImage = res.tempFilePaths[0]
  93. }
  94. })
  95. },
  96. handleUpload() {
  97. if (!this.uploadForm.desensitized) {
  98. uni.showToast({ title: '请先确认已脱敏', icon: 'none' })
  99. return
  100. }
  101. if (!this.uploadImage || this.loading) return
  102. this.loading = true
  103. var self = this
  104. uploadFile(this.uploadImage).then(function(resp) {
  105. var url = resp.data.url
  106. return uploadSubmission({
  107. bookType: self.uploadForm.bookType,
  108. type: self.uploadForm.type,
  109. image: url,
  110. files: null,
  111. sampleFlag: 0,
  112. desensitized: 1
  113. })
  114. }).then(function() {
  115. uni.showToast({ title: '上传成功', icon: 'success' })
  116. self.uploadImage = ''
  117. self.loadSubmissions()
  118. }).catch(function(err) {
  119. uni.showToast({ title: (err && err.message) || '上传失败', icon: 'none' })
  120. }).finally(function() {
  121. self.loading = false
  122. })
  123. },
  124. bookLabel(type) {
  125. var map = { wealth: '财富账', health: '健康账', growth: '成长账' }
  126. return map[type] || type
  127. }
  128. }
  129. }
  130. </script>
  131. <style scoped>
  132. .upload-page { min-height: 100vh; background: #F5F5F5; padding: 24rpx 32rpx; }
  133. .section-card { background: #FFF; border-radius: 16rpx; padding: 32rpx; margin-bottom: 24rpx; }
  134. .section-title { display: block; font-size: 32rpx; font-weight: 700; color: #1E293B; margin-bottom: 24rpx; border-left: 8rpx solid #F97316; padding-left: 16rpx; }
  135. .form-item { margin-bottom: 24rpx; }
  136. .form-label { display: block; font-size: 28rpx; color: #1E293B; font-weight: 500; margin-bottom: 12rpx; }
  137. .picker-display { height: 72rpx; line-height: 72rpx; border: 2rpx solid #E2E8F0; border-radius: 8rpx; padding: 0 20rpx; font-size: 28rpx; color: #1E293B; background: #F8FAFC; }
  138. .radio-item, .check-item { display: flex; align-items: center; font-size: 28rpx; color: #1E293B; margin-bottom: 12rpx; }
  139. .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; }
  140. .preview-img { width: 100%; height: 300rpx; border-radius: 8rpx; margin-bottom: 16rpx; }
  141. .submit-btn { width: 100%; height: 80rpx; line-height: 80rpx; background: #F97316; color: #FFF; font-size: 28rpx; font-weight: 500; border-radius: 40rpx; border: none; }
  142. .submit-btn:active { opacity: 0.85; }
  143. .empty-text { font-size: 26rpx; color: #94A3B8; text-align: center; padding: 24rpx 0; }
  144. .sub-item { border-bottom: 1rpx solid #F1F5F9; padding: 20rpx 0; }
  145. .sub-header { display: flex; justify-content: space-between; align-items: center; }
  146. .sub-type { font-size: 28rpx; color: #1E293B; font-weight: 500; }
  147. .sub-status { font-size: 24rpx; color: #F97316; }
  148. .sub-thumb { width: 120rpx; height: 120rpx; border-radius: 8rpx; margin-top: 12rpx; }
  149. </style>