|
|
@@ -349,6 +349,10 @@
|
|
|
<span v-if="props.unsubmittedStudents.length > 0" @click.stop="viewUnsubmittedStudents()">{{
|
|
|
lang.ssViewSubmitStatus2 }}</span>
|
|
|
</div>
|
|
|
+ <div class="downloadBtn" @click.stop="downloadAll" :class="{ disabled: downloadLoading }" v-if="props.roleType == 1">
|
|
|
+ <IconDownload />
|
|
|
+ <span>{{ downloadLoading ? lang.ssDownloadLoading : lang.ssBatchDownload }}</span>
|
|
|
+ </div>
|
|
|
<div class="c_t15_content" v-show="!lookWorkData">
|
|
|
<div class="c_t15_c_item" v-for="item in processedWorkArray" :key="item.id"
|
|
|
@click.stop="item.content && item.content.fileList.length > 0 ? lookWork(item.id) : ''">
|
|
|
@@ -863,6 +867,9 @@ const echartsArea1 = ref<any>(null)
|
|
|
// 查看的作业详细id
|
|
|
const lookWorkDetail = ref<string>('')
|
|
|
|
|
|
+// 下载加载状态
|
|
|
+const downloadLoading = ref(false)
|
|
|
+
|
|
|
// 查看作业详细的数据
|
|
|
const lookWorkData = computed(() => {
|
|
|
let _result = null
|
|
|
@@ -2289,6 +2296,63 @@ watch(
|
|
|
)
|
|
|
|
|
|
|
|
|
+// 批量下载
|
|
|
+const downloadAll = async () => {
|
|
|
+ if (!processedWorkArray.value || processedWorkArray.value.length === 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (downloadLoading.value) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 设置加载状态
|
|
|
+ downloadLoading.value = true
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 动态导入 JSZip
|
|
|
+ const JSZip = (await import('jszip')).default
|
|
|
+ const { saveAs } = await import('file-saver')
|
|
|
+
|
|
|
+ const zip = new JSZip()
|
|
|
+
|
|
|
+ // 遍历所有学生
|
|
|
+ for (const student of processedWorkArray.value) {
|
|
|
+ if (!student.content || !student.content.fileList || student.content.fileList.length === 0) {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ // 遍历学生的所有照片
|
|
|
+ for (let i = 0; i < student.content.fileList.length; i++) {
|
|
|
+ const file = student.content.fileList[i]
|
|
|
+ const fileName = student.content.fileList.length > 1
|
|
|
+ ? `${student.name}${String(i + 1).padStart(2, '0')}.jpg`
|
|
|
+ : `${student.name}.jpg`
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取图片数据
|
|
|
+ const response = await fetch(file.url)
|
|
|
+ const blob = await response.blob()
|
|
|
+ zip.file(fileName, blob)
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ console.error(`下载 ${fileName} 失败:`, error)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 生成压缩包并下载
|
|
|
+ const content = await zip.generateAsync({ type: 'blob' })
|
|
|
+ saveAs(content, `${lang.ssBatchDownload}.zip`)
|
|
|
+ }
|
|
|
+ catch (error) {
|
|
|
+ console.error('批量下载失败:', error)
|
|
|
+ }
|
|
|
+ finally {
|
|
|
+ // 重置加载状态
|
|
|
+ downloadLoading.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
// 组件卸载时清理ECharts实例
|
|
|
@@ -3381,4 +3445,20 @@ onUnmounted(() => {
|
|
|
min-width: 65px;
|
|
|
justify-content: center;
|
|
|
}
|
|
|
+
|
|
|
+.downloadBtn{
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 5px;
|
|
|
+ font-weight: 300;
|
|
|
+ font-size: 14px;
|
|
|
+ color: rgba(0, 0, 0, 0.7);
|
|
|
+ cursor: pointer;
|
|
|
+ margin-left: auto;
|
|
|
+ border-radius: 5px;
|
|
|
+ border: solid 1px rgba(252, 207, 0, .7);
|
|
|
+ padding: .5rem 0.6rem;
|
|
|
+ min-width: 65px;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
</style>
|