Procházet zdrojové kódy

1、课程的图片、ppt、视频上传加入进度条和控制

liyanbo před 7 měsíci
rodič
revize
942cd72296

+ 34 - 2
src/components/UploadFile/src/UploadFile.vue

@@ -72,11 +72,13 @@ import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from
 import { isString } from '@/utils/is'
 import { useUpload } from '@/components/UploadFile/src/useUpload'
 import { UploadFile } from 'element-plus/es/components/upload/src/upload'
+// 导入axios请求实例
+import request from '@/config/axios'
 
 defineOptions({ name: 'UploadFile' })
 
 const message = useMessage() // 消息弹窗
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'upload-progress', 'upload-start', 'upload-complete'])
 
 const props = defineProps({
   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
@@ -96,7 +98,37 @@ const uploadList = ref<UploadUserFile[]>([])
 const fileList = ref<UploadUserFile[]>([])
 const uploadNumber = ref<number>(0)
 
-const { uploadUrl, httpRequest } = useUpload(props.directory)
+const { uploadUrl } = useUpload(props.directory)
+
+// 自定义httpRequest方法,用于替代useUpload提供的方法
+const httpRequest: UploadProps['httpRequest'] = async (options) => {
+  try {
+    // 触发上传开始事件
+    emit('upload-start')
+
+    const formData = new FormData()
+    formData.append('file', options.file as File)
+
+    // 使用axios的upload方法,并传入onProgress回调
+    const res = await request.upload({
+      url: uploadUrl,
+      data: formData,
+      onProgress: (progress: number) => {
+        // 触发上传进度事件
+        emit('upload-progress', progress)
+      }
+    })
+
+    // 调用成功回调
+    options.onSuccess(res)
+  } catch (error) {
+    // 调用失败回调
+    options.onError(error)
+  } finally {
+    // 触发上传完成事件
+    emit('upload-complete')
+  }
+}
 
 // 文件上传之前判断
 const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {

+ 34 - 3
src/components/UploadFile/src/UploadImgs.vue

@@ -47,11 +47,13 @@ import { ElNotification } from 'element-plus'
 import { createImageViewer } from '@/components/ImageViewer'
 
 import { propTypes } from '@/utils/propTypes'
-import { useUpload } from '@/components/UploadFile/src/useUpload'
+import { useUpload } from '@/components/UploadFile/src/useUpload'// 导入axios请求实例
+import request from '@/config/axios'
 
 defineOptions({ name: 'UploadImgs' })
 
 const message = useMessage() // 消息弹窗
+const emit = defineEmits(['update:modelValue', 'upload-progress', 'upload-start', 'upload-complete'])
 // 查看图片
 const imagePreview = (imgUrl: string) => {
   createImageViewer({
@@ -85,11 +87,41 @@ const props = defineProps({
   directory: propTypes.string.def(undefined) // 上传目录 ==> 非必传(默认为 undefined)
 })
 
-const { uploadUrl, httpRequest } = useUpload(props.directory)
+const { uploadUrl } = useUpload(props.directory)
 
 const fileList = ref<UploadUserFile[]>([])
 const uploadNumber = ref<number>(0)
 const uploadList = ref<UploadUserFile[]>([])
+
+// 自定义httpRequest方法,用于替代useUpload提供的方法
+const httpRequest: UploadProps['httpRequest'] = async (options) => {
+  try {
+    // 触发上传开始事件
+    emit('upload-start')
+
+    const formData = new FormData()
+    formData.append('file', options.file as File)
+
+    // 使用axios的upload方法,并传入onProgress回调
+    const res = await request.upload({
+      url: uploadUrl,
+      data: formData,
+      onProgress: (progress: number) => {
+        // 触发上传进度事件
+        emit('upload-progress', progress)
+      }
+    })
+
+    // 调用成功回调
+    options.onSuccess(res)
+  } catch (error) {
+    // 调用失败回调
+    options.onError(error)
+  } finally {
+    // 触发上传完成事件
+    emit('upload-complete')
+  }
+}
 /**
  * @description 文件上传之前判断
  * @param rawFile 上传的文件
@@ -118,7 +150,6 @@ interface UploadEmits {
   (e: 'update:modelValue', value: string[]): void
 }
 
-const emit = defineEmits<UploadEmits>()
 const uploadSuccess: UploadProps['onSuccess'] = (res: any): void => {
   message.success('上传成功')
   // 删除自身

+ 34 - 2
src/components/UploadFile/src/UploadMusic.vue

@@ -72,11 +72,13 @@ import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from
 import { isString } from '@/utils/is'
 import { useUpload } from '@/components/UploadFile/src/useUpload'
 import { UploadFile } from 'element-plus/es/components/upload/src/upload'
+// 导入axios请求实例
+import request from '@/config/axios'
 
 defineOptions({ name: 'UploadFile' })
 
 const message = useMessage() // 消息弹窗
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'upload-progress', 'upload-start', 'upload-complete'])
 
 const props = defineProps({
   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
@@ -97,7 +99,37 @@ const uploadList = ref<UploadUserFile[]>([])
 const fileList = ref<UploadUserFile[]>([])
 const uploadNumber = ref<number>(0)
 
-const { uploadUrl, httpRequest } = useUpload(props.directory)
+const { uploadUrl } = useUpload(props.directory)
+
+// 自定义httpRequest方法,用于替代useUpload提供的方法
+const httpRequest: UploadProps['httpRequest'] = async (options) => {
+  try {
+    // 触发上传开始事件
+    emit('upload-start')
+
+    const formData = new FormData()
+    formData.append('file', options.file as File)
+
+    // 使用axios的upload方法,并传入onProgress回调
+    const res = await request.upload({
+      url: uploadUrl,
+      data: formData,
+      onProgress: (progress: number) => {
+        // 触发上传进度事件
+        emit('upload-progress', progress)
+      }
+    })
+
+    // 调用成功回调
+    options.onSuccess(res)
+  } catch (error) {
+    // 调用失败回调
+    options.onError(error)
+  } finally {
+    // 触发上传完成事件
+    emit('upload-complete')
+  }
+}
 
 // 视频上传之前判断
 const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {

+ 34 - 3
src/components/UploadFile/src/UploadVideo.vue

@@ -72,11 +72,12 @@ import type { UploadInstance, UploadProps, UploadRawFile, UploadUserFile } from
 import { isString } from '@/utils/is'
 import { useUpload } from '@/components/UploadFile/src/useUpload'
 import { UploadFile } from 'element-plus/es/components/upload/src/upload'
-
+// 导入axios请求实例
+import request from '@/config/axios'
 defineOptions({ name: 'UploadFile' })
 
 const message = useMessage() // 消息弹窗
-const emit = defineEmits(['update:modelValue'])
+const emit = defineEmits(['update:modelValue', 'upload-progress', 'upload-start', 'upload-complete'])
 
 const props = defineProps({
   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
@@ -97,7 +98,37 @@ const uploadList = ref<UploadUserFile[]>([])
 const fileList = ref<UploadUserFile[]>([])
 const uploadNumber = ref<number>(0)
 
-const { uploadUrl, httpRequest } = useUpload(props.directory)
+const { uploadUrl } = useUpload(props.directory)
+
+// 自定义httpRequest方法,用于替代useUpload提供的方法
+const httpRequest: UploadProps['httpRequest'] = async (options) => {
+  try {
+    // 触发上传开始事件
+    emit('upload-start')
+
+    const formData = new FormData()
+    formData.append('file', options.file as File)
+
+    // 使用axios的upload方法,并传入onProgress回调
+    const res = await request.upload({
+      url: uploadUrl,
+      data: formData,
+      onProgress: (progress: number) => {
+        // 触发上传进度事件
+        emit('upload-progress', progress)
+      }
+    })
+
+    // 调用成功回调
+    options.onSuccess(res)
+  } catch (error) {
+    // 调用失败回调
+    options.onError(error)
+  } finally {
+    // 触发上传完成事件
+    emit('upload-complete')
+  }
+}
 
 // 视频上传之前判断
 const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {

+ 6 - 2
src/views/ai/video/index/components/videoImage/index.vue

@@ -72,7 +72,7 @@
       <el-text tag="b">视频时长</el-text>
     </div>
     <div class="duration">
-      <el-slider v-model="duration" show-input :min="2" :max="5" :step="1" />
+      <el-slider v-model="duration" show-input :min="3" :max="5" :step="1" />
     </div>
   </div>
   <div class="btns">
@@ -132,7 +132,7 @@ const handleGenerateVideo = async () => {
       platform: otherPlatform.value,
       modelId: modelId.value, // 模型
       prompt: prompt.value, // 提示词
-      promptImage: "https://learn-ai.com.cn/admin-api/infra/file/29/get/20250914/33dbe291bd38b5db518434342be5d35c9a6c14c5c99c755ddfaf13ffe02e77d3_1757845073064.jpg", // 参考视频
+      promptImage: promptImage.value, // 参考视频
       width: width.value, // 视频宽度
       height: height.value, // 视频高度
       resolution: resolution.value, // 分辨率
@@ -209,6 +209,10 @@ defineExpose({ settingValues })
   }
 }
 
+.duration{
+  margin-left: 15px;
+}
+
 .btns {
   display: flex;
   justify-content: center;

+ 49 - 5
src/views/bjdx/course/CourseForm.vue

@@ -41,21 +41,43 @@
       </el-form-item>
 
       <el-form-item v-if="formData.courseContentType === 'image'" label="课程图片集" prop="coursePath">
-        <UploadImgs v-model="formData.courseImagePath" />
+        <UploadImgs v-model="formData.courseImagePath"
+                    @upload-progress="handleUploadProgress"
+                    @upload-start="handleUploadStart"
+                    @upload-complete="handleUploadComplete"/>
       </el-form-item>
 
       <el-form-item v-if="formData.courseContentType === 'music'" label="课程音频" prop="coursePath">
-        <UploadMusic v-model="formData.courseMusicPath" />
+        <UploadMusic v-model="formData.courseMusicPath"
+                     @upload-progress="handleUploadProgress"
+                     @upload-start="handleUploadStart"
+                     @upload-complete="handleUploadComplete"/>
       </el-form-item>
 
       <el-form-item v-if="formData.courseContentType === 'video'" label="课程视频" prop="coursePath">
-        <UploadVideo v-model="formData.courseVideoPath" />
+        <UploadVideo
+          v-model="formData.courseVideoPath"
+          @upload-progress="handleUploadProgress"
+          @upload-start="handleUploadStart"
+          @upload-complete="handleUploadComplete"
+        />
       </el-form-item>
 
       <el-form-item v-if="formData.courseContentType === 'ppt'" label="课程PPT" prop="courseFilePath">
-        <UploadFile v-model="formData.courseFilePath" :fileType="['ppt','pptx']" :fileSize="50"/>
+        <UploadFile v-model="formData.courseFilePath" :fileType="['ppt','pptx']" :fileSize="50"
+                    @upload-progress="handleUploadProgress"
+                    @upload-start="handleUploadStart"
+                    @upload-complete="handleUploadComplete"/>
       </el-form-item>
 
+      <!-- 上传进度条 -->
+
+      <el-form-item>
+        <div v-if="isUploading" class="uploadProgress">
+          <el-progress :percentage="uploadProgress" />
+          <div class="text-xs text-gray-500 text-right mt-1">{{ uploadProgress }}% 已上传</div>
+        </div>
+      </el-form-item>
       <!--            <el-form-item label="课程大小" prop="courseSize">-->
       <!--              <el-input-number v-model="formData.courseSize" :min="1" :step="1" step-strictly>-->
       <!--                <template #suffix><span>MB</span></template>-->
@@ -241,7 +263,7 @@
       </el-form-item>
     </el-form>
     <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading || isUploading">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
@@ -296,6 +318,10 @@ const formData = ref({
   tenantId: undefined,
 })
 
+// 添加上传进度相关的状态
+const uploadProgress = ref(0)
+const isUploading = ref(false)
+
 const formRules = reactive({
   courseType: [{ required: true, message: '课程类型不能为空', trigger: 'blur' }],
   courseName: [{ required: true, message: '课程名称不能为空', trigger: 'blur' }],
@@ -363,6 +389,21 @@ const submitForm = async () => {
   }
 }
 
+// 添加处理上传进度的方法
+const handleUploadProgress = (progress: number) => {
+  uploadProgress.value = progress
+}
+
+const handleUploadStart = () => {
+  isUploading.value = true
+  uploadProgress.value = 0
+}
+
+const handleUploadComplete = () => {
+  isUploading.value = false
+  uploadProgress.value = 100
+}
+
 /** 重置表单 */
 const resetForm = () => {
   formData.value = {
@@ -423,4 +464,7 @@ const getCourseTypeTree = async () => {
   vertical-align: middle;
   margin-left: 4px;
 }
+.uploadProgress{
+  width: 50%;
+}
 </style>