feat(checkin): 添加编辑打卡时合并附件类型的功能
在编辑打卡记录时,合并attachment_type和file_type数组以适配前后打卡类型不一致的情况
Showing
1 changed file
with
36 additions
and
87 deletions
| ... | @@ -20,15 +20,9 @@ | ... | @@ -20,15 +20,9 @@ |
| 20 | <div class="section-content"> | 20 | <div class="section-content"> |
| 21 | <!-- 文本输入区域 --> | 21 | <!-- 文本输入区域 --> |
| 22 | <div class="text-input-area"> | 22 | <div class="text-input-area"> |
| 23 | - <van-field | 23 | + <van-field v-model="message" rows="6" autosize type="textarea" |
| 24 | - v-model="message" | ||
| 25 | - rows="6" | ||
| 26 | - autosize | ||
| 27 | - type="textarea" | ||
| 28 | :placeholder="activeType === 'text' ? '请输入打卡留言,至少需要10个字符' : '请输入打卡留言(可选)'" | 24 | :placeholder="activeType === 'text' ? '请输入打卡留言,至少需要10个字符' : '请输入打卡留言(可选)'" |
| 29 | - :maxlength="activeType === 'text' ? 500 : 200" | 25 | + :maxlength="activeType === 'text' ? 500 : 200" show-word-limit /> |
| 30 | - show-word-limit | ||
| 31 | - /> | ||
| 32 | </div> | 26 | </div> |
| 33 | 27 | ||
| 34 | <!-- 打卡类型选项卡 --> | 28 | <!-- 打卡类型选项卡 --> |
| ... | @@ -36,19 +30,12 @@ | ... | @@ -36,19 +30,12 @@ |
| 36 | <div class="tabs-header"> | 30 | <div class="tabs-header"> |
| 37 | <div class="tab-title">选择打卡类型</div> | 31 | <div class="tab-title">选择打卡类型</div> |
| 38 | <div class="tabs-nav"> | 32 | <div class="tabs-nav"> |
| 39 | - <div | 33 | + <div v-for="option in attachmentTypeOptions" :key="option.key" |
| 40 | - v-for="option in attachmentTypeOptions" | 34 | + @click="!isEditMode ? switchType(option.key) : null" :class="['tab-item', { |
| 41 | - :key="option.key" | ||
| 42 | - @click="!isEditMode ? switchType(option.key) : null" | ||
| 43 | - :class="['tab-item', { | ||
| 44 | active: activeType === option.key, | 35 | active: activeType === option.key, |
| 45 | disabled: isEditMode && activeType !== option.key | 36 | disabled: isEditMode && activeType !== option.key |
| 46 | - }]" | 37 | + }]"> |
| 47 | - > | 38 | + <van-icon :name="getIconName(option.key)" size="1.2rem" /> |
| 48 | - <van-icon | ||
| 49 | - :name="getIconName(option.key)" | ||
| 50 | - size="1.2rem" | ||
| 51 | - /> | ||
| 52 | <span class="tab-text">{{ option.value }}</span> | 39 | <span class="tab-text">{{ option.value }}</span> |
| 53 | </div> | 40 | </div> |
| 54 | </div> | 41 | </div> |
| ... | @@ -56,19 +43,10 @@ | ... | @@ -56,19 +43,10 @@ |
| 56 | 43 | ||
| 57 | <!-- 文件上传区域 --> | 44 | <!-- 文件上传区域 --> |
| 58 | <div v-if="activeType !== 'text'" class="upload-area"> | 45 | <div v-if="activeType !== 'text'" class="upload-area"> |
| 59 | - <van-uploader | 46 | + <van-uploader v-model="fileList" :max-count="maxCount" :max-size="20 * 1024 * 1024" |
| 60 | - v-model="fileList" | 47 | + :before-read="beforeRead" :after-read="afterRead" @delete="onDelete" |
| 61 | - :max-count="maxCount" | 48 | + @click-preview="onClickPreview" multiple :accept="getAcceptType()" result-type="file" |
| 62 | - :max-size="20 * 1024 * 1024" | 49 | + :deletable="false" /> |
| 63 | - :before-read="beforeRead" | ||
| 64 | - :after-read="afterRead" | ||
| 65 | - @delete="onDelete" | ||
| 66 | - @click-preview="onClickPreview" | ||
| 67 | - multiple | ||
| 68 | - :accept="getAcceptType()" | ||
| 69 | - result-type="file" | ||
| 70 | - :deletable="false" | ||
| 71 | - /> | ||
| 72 | 50 | ||
| 73 | <!-- 文件列表显示 --> | 51 | <!-- 文件列表显示 --> |
| 74 | <div v-if="fileList.length > 0" class="file-list"> | 52 | <div v-if="fileList.length > 0" class="file-list"> |
| ... | @@ -78,12 +56,7 @@ | ... | @@ -78,12 +56,7 @@ |
| 78 | <span class="file-name">{{ item.name || item.file?.name }}</span> | 56 | <span class="file-name">{{ item.name || item.file?.name }}</span> |
| 79 | <span class="file-status" :class="item.status">{{ item.message }}</span> | 57 | <span class="file-status" :class="item.status">{{ item.message }}</span> |
| 80 | </div> | 58 | </div> |
| 81 | - <van-icon | 59 | + <van-icon name="clear" size="1rem" @click="delItem(item)" class="delete-icon" /> |
| 82 | - name="clear" | ||
| 83 | - size="1rem" | ||
| 84 | - @click="delItem(item)" | ||
| 85 | - class="delete-icon" | ||
| 86 | - /> | ||
| 87 | </div> | 60 | </div> |
| 88 | </div> | 61 | </div> |
| 89 | 62 | ||
| ... | @@ -98,14 +71,8 @@ | ... | @@ -98,14 +71,8 @@ |
| 98 | 71 | ||
| 99 | <!-- 提交按钮 --> | 72 | <!-- 提交按钮 --> |
| 100 | <div v-if="!taskDetail.is_finish || route.query.status === 'edit'" class="submit-area"> | 73 | <div v-if="!taskDetail.is_finish || route.query.status === 'edit'" class="submit-area"> |
| 101 | - <van-button | 74 | + <van-button type="primary" block size="large" :loading="uploading" :disabled="!canSubmit" |
| 102 | - type="primary" | 75 | + @click="onSubmit"> |
| 103 | - block | ||
| 104 | - size="large" | ||
| 105 | - :loading="uploading" | ||
| 106 | - :disabled="!canSubmit" | ||
| 107 | - @click="onSubmit" | ||
| 108 | - > | ||
| 109 | {{ route.query.status === 'edit' ? '保存修改' : '提交打卡' }} | 76 | {{ route.query.status === 'edit' ? '保存修改' : '提交打卡' }} |
| 110 | </van-button> | 77 | </van-button> |
| 111 | </div> | 78 | </div> |
| ... | @@ -119,41 +86,24 @@ | ... | @@ -119,41 +86,24 @@ |
| 119 | </van-overlay> | 86 | </van-overlay> |
| 120 | 87 | ||
| 121 | <!-- 音频播放器弹窗 --> | 88 | <!-- 音频播放器弹窗 --> |
| 122 | - <van-popup | 89 | + <van-popup v-model:show="audioShow" position="bottom" round closeable :style="{ height: '60%', width: '100%' }"> |
| 123 | - v-model:show="audioShow" | ||
| 124 | - position="bottom" | ||
| 125 | - round | ||
| 126 | - closeable | ||
| 127 | - :style="{ height: '60%', width: '100%' }" | ||
| 128 | - > | ||
| 129 | <div class="p-4"> | 90 | <div class="p-4"> |
| 130 | <h3 class="text-lg font-medium mb-4 text-center">{{ audioTitle }}</h3> | 91 | <h3 class="text-lg font-medium mb-4 text-center">{{ audioTitle }}</h3> |
| 131 | - <AudioPlayer | 92 | + <AudioPlayer v-if="audioShow && audioUrl" :songs="[{ title: audioTitle, url: audioUrl }]" |
| 132 | - v-if="audioShow && audioUrl" | 93 | + class="w-full" /> |
| 133 | - :songs="[{ title: audioTitle, url: audioUrl }]" | ||
| 134 | - class="w-full" | ||
| 135 | - /> | ||
| 136 | </div> | 94 | </div> |
| 137 | </van-popup> | 95 | </van-popup> |
| 138 | 96 | ||
| 139 | <!-- 视频播放器弹窗 --> | 97 | <!-- 视频播放器弹窗 --> |
| 140 | - <van-popup | 98 | + <van-popup v-model:show="videoShow" position="center" round closeable |
| 141 | - v-model:show="videoShow" | 99 | + :style="{ width: '95%', maxHeight: '80vh' }" @close="stopVideoPlay"> |
| 142 | - position="center" | ||
| 143 | - round | ||
| 144 | - closeable | ||
| 145 | - :style="{ width: '95%', maxHeight: '80vh' }" | ||
| 146 | - @close="stopVideoPlay" | ||
| 147 | - > | ||
| 148 | <div class="p-4"> | 100 | <div class="p-4"> |
| 149 | <h3 class="text-lg font-medium mb-4 text-center">视频预览</h3> | 101 | <h3 class="text-lg font-medium mb-4 text-center">视频预览</h3> |
| 150 | <div class="relative w-full bg-black rounded-lg overflow-hidden" style="aspect-ratio: 16/9;"> | 102 | <div class="relative w-full bg-black rounded-lg overflow-hidden" style="aspect-ratio: 16/9;"> |
| 151 | <!-- 视频封面 --> | 103 | <!-- 视频封面 --> |
| 152 | - <div | 104 | + <div v-show="!isVideoPlaying" |
| 153 | - v-show="!isVideoPlaying" | ||
| 154 | class="absolute inset-0 flex items-center justify-center cursor-pointer" | 105 | class="absolute inset-0 flex items-center justify-center cursor-pointer" |
| 155 | - @click="startVideoPlay" | 106 | + @click="startVideoPlay"> |
| 156 | - > | ||
| 157 | <img :src="videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png'" | 107 | <img :src="videoCover || 'https://cdn.ipadbiz.cn/mlaj/images/cover_video_2.png'" |
| 158 | :alt="videoTitle" class="w-full h-full object-cover" /> | 108 | :alt="videoTitle" class="w-full h-full object-cover" /> |
| 159 | <div class="absolute inset-0 flex items-center justify-center bg-black/20"> | 109 | <div class="absolute inset-0 flex items-center justify-center bg-black/20"> |
| ... | @@ -164,34 +114,23 @@ | ... | @@ -164,34 +114,23 @@ |
| 164 | </div> | 114 | </div> |
| 165 | </div> | 115 | </div> |
| 166 | <!-- 视频播放器 --> | 116 | <!-- 视频播放器 --> |
| 167 | - <VideoPlayer | 117 | + <VideoPlayer v-show="isVideoPlaying" ref="videoPlayerRef" :video-url="videoUrl" |
| 168 | - v-show="isVideoPlaying" | 118 | + :video-id="videoTitle" :autoplay="false" class="w-full h-full" @play="handleVideoPlay" |
| 169 | - ref="videoPlayerRef" | 119 | + @pause="handleVideoPause" /> |
| 170 | - :video-url="videoUrl" | ||
| 171 | - :video-id="videoTitle" | ||
| 172 | - :autoplay="false" | ||
| 173 | - class="w-full h-full" | ||
| 174 | - @play="handleVideoPlay" | ||
| 175 | - @pause="handleVideoPause" | ||
| 176 | - /> | ||
| 177 | </div> | 120 | </div> |
| 178 | </div> | 121 | </div> |
| 179 | </van-popup> | 122 | </van-popup> |
| 180 | 123 | ||
| 181 | <!-- 图片预览弹窗 --> | 124 | <!-- 图片预览弹窗 --> |
| 182 | - <van-image-preview | 125 | + <van-image-preview v-model:show="imageShow" :images="imageList" :start-position="imageIndex" |
| 183 | - v-model:show="imageShow" | 126 | + :show-index="true" /> |
| 184 | - :images="imageList" | ||
| 185 | - :start-position="imageIndex" | ||
| 186 | - :show-index="true" | ||
| 187 | - /> | ||
| 188 | </div> | 127 | </div> |
| 189 | </template> | 128 | </template> |
| 190 | 129 | ||
| 191 | <script setup> | 130 | <script setup> |
| 192 | import { ref, computed, onMounted, nextTick } from 'vue' | 131 | import { ref, computed, onMounted, nextTick } from 'vue' |
| 193 | import { useRoute, useRouter } from 'vue-router' | 132 | import { useRoute, useRouter } from 'vue-router' |
| 194 | -import { getTaskDetailAPI } from "@/api/checkin" | 133 | +import { getTaskDetailAPI, getUploadTaskInfoAPI } from "@/api/checkin" |
| 195 | import { getTeacherFindSettingsAPI } from '@/api/teacher' | 134 | import { getTeacherFindSettingsAPI } from '@/api/teacher' |
| 196 | import { useTitle } from '@vueuse/core' | 135 | import { useTitle } from '@vueuse/core' |
| 197 | import { useCheckin } from '@/composables/useCheckin' | 136 | import { useCheckin } from '@/composables/useCheckin' |
| ... | @@ -325,6 +264,16 @@ const getTaskDetail = async (month) => { | ... | @@ -325,6 +264,16 @@ const getTaskDetail = async (month) => { |
| 325 | 'video': '视频' | 264 | 'video': '视频' |
| 326 | } | 265 | } |
| 327 | 266 | ||
| 267 | + // attachment_type 和 file_type 合并成一个数组 合并以后的数组,就是学员编辑的时候,可以使用的类型 | ||
| 268 | + // 主要是适配先前打卡类型和后期打卡类型不一致的情况 | ||
| 269 | + if (route.query.status === 'edit') { | ||
| 270 | + const info = await getUploadTaskInfoAPI({ i: route.query.post_id }); | ||
| 271 | + if (info.code) { | ||
| 272 | + // 合并 attachment_type 和 file_type 数组, 里面数据需要去重复 | ||
| 273 | + data.attachment_type = [...new Set([...data.attachment_type, info.data.file_type])]; | ||
| 274 | + } | ||
| 275 | + } | ||
| 276 | + | ||
| 328 | // 如果是数组格式,转换为对象格式 | 277 | // 如果是数组格式,转换为对象格式 |
| 329 | if (Array.isArray(data.attachment_type)) { | 278 | if (Array.isArray(data.attachment_type)) { |
| 330 | attachmentTypeOptions.value = data.attachment_type.map(key => ({ | 279 | attachmentTypeOptions.value = data.attachment_type.map(key => ({ | ... | ... |
-
Please register or login to post a comment