From 389c73d834ad710c1398581314cb96787078b954 Mon Sep 17 00:00:00 2001 From: dhb52 <dhb52@126.com> Date: Sat, 15 Apr 2023 15:59:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20MP=E6=B6=88=E6=81=AF=E7=AE=A1?= =?UTF-8?q?=E7=90=86-=E6=8B=86=E5=88=86=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/mp/material/components/Upload.vue | 70 +++ .../mp/material/components/UploadVideo.vue | 127 ++++++ .../mp/material/components/VideoTable.vue | 61 +++ .../mp/material/components/VoiceTable.vue | 53 +++ .../mp/material/components/Waterfall.vue | 83 ++++ src/views/mp/material/components/upload.ts | 73 +++ src/views/mp/material/index.vue | 424 ++---------------- 7 files changed, 507 insertions(+), 384 deletions(-) create mode 100644 src/views/mp/material/components/Upload.vue create mode 100644 src/views/mp/material/components/UploadVideo.vue create mode 100644 src/views/mp/material/components/VideoTable.vue create mode 100644 src/views/mp/material/components/VoiceTable.vue create mode 100644 src/views/mp/material/components/Waterfall.vue create mode 100644 src/views/mp/material/components/upload.ts diff --git a/src/views/mp/material/components/Upload.vue b/src/views/mp/material/components/Upload.vue new file mode 100644 index 00000000..541dbc20 --- /dev/null +++ b/src/views/mp/material/components/Upload.vue @@ -0,0 +1,70 @@ +<template> + <el-upload + :action="UPLOAD_URL" + :headers="HEADERS" + multiple + :limit="1" + :file-list="fileList" + :data="uploadData" + :on-progress="() => (uploading = true)" + :before-upload="beforeUpload" + :on-success="handleUploadSuccess" + > + <el-button type="primary" plain :loading="uploading" :disabled="uploading"> + {{ uploading ? '正在上传' : '点击上传' }} + </el-button> + <template #tip> + <span class="el-upload__tip" style="margin-left: 5px"> + <slot></slot> + </span> + </template> + </el-upload> +</template> + +<script setup lang="ts"> +import type { UploadProps, UploadUserFile } from 'element-plus' +import { + HEADERS, + UPLOAD_URL, + UploadData, + MaterialType, + beforeImageUpload, + beforeVoiceUpload +} from './upload' + +const message = useMessage() + +const props = defineProps<{ type: boolean }>() + +const fileList = ref<UploadUserFile[]>([]) +const emit = defineEmits<{ + (e: 'uploaded', v: void) +}>() + +const uploadData: UploadData = reactive({ + type: MaterialType.Image, + title: '', + introduction: '' +}) +const uploading = ref(false) + +const beforeUpload = props.type == MaterialType.Image ? beforeImageUpload : beforeVoiceUpload + +const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { + if (res.code !== 0) { + message.alertError('上传出错:' + res.msg) + return false + } + + // 清空上传时的各种数据 + fileList.value = [] + uploadData.title = '' + uploadData.introduction = '' + + message.notifySuccess('上传成功') + uploading.value = false + emit('uploaded') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/UploadVideo.vue b/src/views/mp/material/components/UploadVideo.vue new file mode 100644 index 00000000..5da7d980 --- /dev/null +++ b/src/views/mp/material/components/UploadVideo.vue @@ -0,0 +1,127 @@ +<template> + <el-dialog title="新建视频" v-model="showDialog" width="600px" destroy-on-close> + <el-upload + :action="UPLOAD_URL" + :headers="HEADERS" + multiple + :limit="1" + :file-list="fileList" + :data="uploadData" + :before-upload="beforeVideoUpload" + :on-progress="() => (uploading = true)" + :on-success="handleUploadSuccess" + ref="uploadVideoRef" + :auto-upload="false" + class="mb-5" + > + <template #trigger> + <el-button type="primary" plain>选择视频</el-button> + </template> + <span class="el-upload__tip" style="margin-left: 10px" + >格式支持 MP4,文件大小不超过 10MB</span + > + </el-upload> + <el-divider /> + <el-form :model="uploadData" :rules="uploadRules" ref="uploadFormRef" v-loading="uploading"> + <el-form-item label="标题" prop="title"> + <el-input + v-model="uploadData.title" + placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" + /> + </el-form-item> + <el-form-item label="描述" prop="introduction"> + <el-input + :rows="3" + type="textarea" + v-model="uploadData.introduction" + placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" + /> + </el-form-item> + </el-form> + <template #footer> + <el-button @click="showDialog = false">取 消</el-button> + <el-button type="primary" @click="submitVideo" :loading="uploading" :disabled="uploading" + >提 交</el-button + > + </template> + </el-dialog> +</template> + +<script setup lang="ts"> +import type { + FormInstance, + FormRules, + UploadInstance, + UploadProps, + UploadUserFile +} from 'element-plus' +import { HEADERS, UploadData, UPLOAD_URL, beforeVideoUpload, MaterialType } from './upload' + +const message = useMessage() + +const uploadRules: FormRules = { + title: [{ required: true, message: '请输入标题', trigger: 'blur' }], + introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }] +} + +const props = defineProps({ + modelValue: { + type: Boolean, + default: false + } +}) +const emit = defineEmits<{ + (e: 'update:modelValue', v: boolean) + (e: 'uploaded', v: void) +}>() + +const showDialog = computed({ + get() { + return props.modelValue + }, + set(val) { + emit('update:modelValue', val) + } +}) + +const uploading = ref(false) + +const fileList = ref<UploadUserFile[]>([]) + +const uploadData: UploadData = reactive({ + type: MaterialType.Video, + title: '', + introduction: '' +}) + +const uploadFormRef = ref<FormInstance>() +const uploadVideoRef = ref<UploadInstance>() + +const submitVideo = () => { + uploadFormRef.value?.validate((valid) => { + if (!valid) { + return false + } + uploadVideoRef.value?.submit() + }) +} + +const handleUploadSuccess: UploadProps['onSuccess'] = (res: any) => { + uploading.value = false + if (res.code !== 0) { + message.error('上传出错:' + res.msg) + return false + } + + // 清空上传时的各种数据 + fileList.value = [] + uploadData.title = '' + uploadData.introduction = '' + + showDialog.value = false + message.notifySuccess('上传成功') + emit('uploaded') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/VideoTable.vue b/src/views/mp/material/components/VideoTable.vue new file mode 100644 index 00000000..3bd2fe00 --- /dev/null +++ b/src/views/mp/material/components/VideoTable.vue @@ -0,0 +1,61 @@ +<template> + <el-table :data="props.list" stripe border v-loading="props.loading" style="margin-top: 10px"> + <el-table-column label="编号" align="center" prop="mediaId" /> + <el-table-column label="文件名" align="center" prop="name" /> + <el-table-column label="标题" align="center" prop="title" /> + <el-table-column label="介绍" align="center" prop="introduction" /> + <el-table-column label="视频" align="center"> + <template #default="scope"> + <WxVideoPlayer v-if="scope.row.url" :url="scope.row.url" /> + </template> + </el-table-column> + <el-table-column + label="上传时间" + align="center" + :formatter="dateFormatter" + prop="createTime" + width="180" + > + <template #default="scope"> + <span>{{ scope.row.createTime }}</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" fixed="right"> + <template #default="scope"> + <el-button type="primary" link @click="handleDownload(scope.row.url)"> + <Icon icon="ep:download" />下载 + </el-button> + <el-button + type="primary" + link + @click="emit('delete', scope.row.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" />删除 + </el-button> + </template> + </el-table-column> + </el-table> +</template> + +<script setup lang="ts"> +import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue' +import { dateFormatter } from '@/utils/formatTime' + +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) + (e: 'download', v: string) +}>() + +// 下载文件 +const handleDownload = (url: string) => { + window.open(url, '_blank') +} +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/VoiceTable.vue b/src/views/mp/material/components/VoiceTable.vue new file mode 100644 index 00000000..44bd01da --- /dev/null +++ b/src/views/mp/material/components/VoiceTable.vue @@ -0,0 +1,53 @@ +<template> + <el-table :data="props.list" stripe border v-loading="props.loading" style="margin-top: 10px"> + <el-table-column label="编号" align="center" prop="mediaId" /> + <el-table-column label="文件名" align="center" prop="name" /> + <el-table-column label="语音" align="center"> + <template #default="scope"> + <WxVoicePlayer v-if="scope.row.url" :url="scope.row.url" /> + </template> + </el-table-column> + <el-table-column + label="上传时间" + align="center" + prop="createTime" + :formatter="dateFormatter" + width="180" + > + <template #default="scope"> + <span>{{ scope.row.createTime }}</span> + </template> + </el-table-column> + <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-button type="primary" link @click="emit('delete', scope.row.id)"> + <Icon icon="ep:download" />下载 + </el-button> + <el-button + type="primary" + link + @click="emit('delete', scope.row.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" />删除 + </el-button> + </template> + </el-table-column> + </el-table> +</template> + +<script setup lang="ts"> +import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue' +import { dateFormatter } from '@/utils/formatTime' + +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) +}>() +</script> + +<style scoped></style> diff --git a/src/views/mp/material/components/Waterfall.vue b/src/views/mp/material/components/Waterfall.vue new file mode 100644 index 00000000..118fc7bd --- /dev/null +++ b/src/views/mp/material/components/Waterfall.vue @@ -0,0 +1,83 @@ +<template> + <div class="waterfall" v-loading="props.loading"> + <div class="waterfall-item" v-for="item in props.list" :key="item.id"> + <a target="_blank" :href="item.url"> + <img class="material-img" :src="item.url" /> + <div class="item-name">{{ item.name }}</div> + </a> + <el-row justify="center"> + <el-button + type="danger" + circle + @click="emit('delete', item.id)" + v-hasPermi="['mp:material:delete']" + > + <Icon icon="ep:delete" /> + </el-button> + </el-row> + </div> + </div> +</template> + +<script setup lang="ts"> +const props = defineProps<{ + list: any[] + loading: boolean +}>() + +const emit = defineEmits<{ + (e: 'delete', v: number) +}>() +</script> + +<style lang="scss" scoped> +/*瀑布流样式*/ +.waterfall { + width: 100%; + column-gap: 10px; + column-count: 5; + margin-top: 10px; + /* 芋道源码:增加 10px,避免顶着上面 */ +} + +.waterfall-item { + padding: 10px; + margin-bottom: 10px; + break-inside: avoid; + border: 1px solid #eaeaea; +} + +.material-img { + width: 100%; +} + +p { + line-height: 30px; +} + +@media (min-width: 992px) and (max-width: 1300px) { + .waterfall { + column-count: 3; + } + + p { + color: red; + } +} + +@media (min-width: 768px) and (max-width: 991px) { + .waterfall { + column-count: 2; + } + + p { + color: orange; + } +} + +@media (max-width: 767px) { + .waterfall { + column-count: 1; + } +} +</style> diff --git a/src/views/mp/material/components/upload.ts b/src/views/mp/material/components/upload.ts new file mode 100644 index 00000000..37441f5b --- /dev/null +++ b/src/views/mp/material/components/upload.ts @@ -0,0 +1,73 @@ +import type { UploadProps, UploadRawFile } from 'element-plus' +import { getAccessToken } from '@/utils/auth' + +const message = useMessage() + +const HEADERS = { Authorization: 'Bearer ' + getAccessToken() } +const UPLOAD_URL = 'http://127.0.0.1:8000/upload/' //import.meta.env.VITE_BASE_URL + '/admin-api/mp/material/upload-permanent' + +enum MaterialType { + Image = 'image', + Voice = 'voice', + Video = 'video' +} + +interface UploadData { + type: MaterialType + title: string + introduction: string +} + +const beforeUpload = (rawFile: UploadRawFile, materialType: MaterialType): boolean => { + let allowTypes: string[] = [] + let maxSizeMB = 0 + let name = '' + + switch (materialType) { + case MaterialType.Image: + allowTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'] + maxSizeMB = 2 + name = '图片' + break + case MaterialType.Voice: + allowTypes = ['audio/mp3', 'audio/mpeg', 'audio/wma', 'audio/wav', 'audio/amr'] + maxSizeMB = 2 + name = '图片' + break + case MaterialType.Video: + allowTypes = ['video/mp4'] + maxSizeMB = 10 + name = '视频' + } + + if (!allowTypes.includes(rawFile.type)) { + message.error(`上传${name}格式不对!`) + return false + } + + if (rawFile.size / 1024 / 1024 > maxSizeMB) { + message.error(`上传${name}大小不能超过${maxSizeMB}M!`) + return false + } + + return true +} + +const beforeImageUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Image) + +const beforeVoiceUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Voice) + +const beforeVideoUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => + beforeUpload(rawFile, MaterialType.Video) + +export { + HEADERS, + UPLOAD_URL, + MaterialType, + UploadData, + beforeImageUpload, + beforeVoiceUpload, + beforeVideoUpload +} diff --git a/src/views/mp/material/index.vue b/src/views/mp/material/index.vue index c6d8055d..dd54cf19 100644 --- a/src/views/mp/material/index.vue +++ b/src/views/mp/material/index.vue @@ -12,47 +12,18 @@ <ContentWrap> <el-tabs v-model="type" @tab-change="onTabChange"> <!-- tab 1:图片 --> - <el-tab-pane name="image"> + <el-tab-pane :name="MaterialType.Image"> <template #label> <span> <Icon icon="ep:picture" />图片 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :before-upload="beforeImageUpload" - :on-success="handleUploadSuccess" - > - <el-button type="primary" plain>点击上传</el-button> - <template #tip> - <span class="el-upload__tip" style="margin-left: 5px"> - 支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M - </span> - </template> - </el-upload> - </div> - <div class="waterfall" v-loading="loading"> - <div class="waterfall-item" v-for="item in list" :key="item.id"> - <a target="_blank" :href="item.url"> - <img class="material-img" :src="item.url" /> - <div class="item-name">{{ item.name }}</div> - </a> - <el-row justify="center"> - <el-button - type="danger" - circle - @click="handleDelete(item)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" /> - </el-button> - </el-row> - </div> - </div> + <Upload + v-hasPermi="['mp:material:upload-permanent']" + :type="MaterialType.Image" + @uploaded="getList" + > + 支持 bmp/png/jpeg/jpg/gif 格式,大小不超过 2M + </Upload> + <Waterfall :loading="loading" :list="list" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -63,67 +34,20 @@ </el-tab-pane> <!-- tab 2:语音 --> - <el-tab-pane name="voice"> + <el-tab-pane :name="MaterialType.Voice"> <template #label> <span> <Icon icon="ep:microphone" />语音 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :on-success="handleUploadSuccess" - :before-upload="beforeVoiceUpload" - > - <el-button type="primary" plain>点击上传</el-button> - <template #tip> - <span class="el-upload__tip" style="margin-left: 5px"> - 格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s - </span> - </template> - </el-upload> - </div> + <Upload + v-hasPermi="['mp:material:upload-permanent']" + :type="MaterialType.Voice" + @uploaded="getList" + > + 格式支持 mp3/wma/wav/amr,文件大小不超过 2M,播放长度不超过 60s + </Upload> <!-- 列表 --> - <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px"> - <el-table-column label="编号" align="center" prop="mediaId" /> - <el-table-column label="文件名" align="center" prop="name" /> - <el-table-column label="语音" align="center"> - <template #default="scope"> - <WxVoicePlayer v-if="scope.row.url" :url="scope.row.url" /> - </template> - </el-table-column> - <el-table-column - label="上传时间" - align="center" - prop="createTime" - :formatter="dateFormatter" - width="180" - > - <template #default="scope"> - <span>{{ scope.row.createTime }}</span> - </template> - </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-button type="primary" link plain @click="handleDownload(scope.row)"> - <Icon icon="ep:download" />下载 - </el-button> - <el-button - type="primary" - link - plain - @click="handleDelete(scope.row)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" />删除 - </el-button> - </template> - </el-table-column> - </el-table> + <VoiceTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -134,105 +58,22 @@ </el-tab-pane> <!-- tab 3:视频 --> - <el-tab-pane name="video"> + <el-tab-pane :name="MaterialType.Video"> <template #label> <span> <Icon icon="ep:video-play" /> 视频 </span> </template> - <div class="add_but" v-hasPermi="['mp:material:upload-permanent']"> - <el-button type="primary" plain @click="handleAddVideo">新建视频</el-button> - </div> - <!-- 新建视频的弹窗 --> - <el-dialog - title="新建视频" - v-model="dialogVideoVisible" - width="600px" - v-loading="addMaterialLoading" + <el-button + v-hasPermi="['mp:material:upload-permanent']" + type="primary" + plain + @click="showCreateVideo = true" + >新建视频</el-button > - <el-upload - :action="uploadUrl" - :headers="headers" - multiple - :limit="1" - :file-list="fileList" - :data="uploadData" - :before-upload="beforeVideoUpload" - :on-success="handleUploadSuccess" - ref="uploadVideoRef" - :auto-upload="false" - > - <template #trigger> - <el-button size="small" type="primary">选择视频</el-button> - </template> - <span class="el-upload__tip" style="margin-left: 10px" - >格式支持 MP4,文件大小不超过 10MB</span - > - </el-upload> - <el-form :model="uploadData" :rules="uploadRules" ref="uploadFormRef" label-width="80px"> - <el-row> - <el-form-item label="标题" prop="title"> - <el-input - v-model="uploadData.title" - placeholder="标题将展示在相关播放页面,建议填写清晰、准确、生动的标题" - /> - </el-form-item> - </el-row> - <el-row> - <el-form-item label="描述" prop="introduction"> - <el-input - :rows="3" - type="textarea" - v-model="uploadData.introduction" - placeholder="介绍语将展示在相关播放页面,建议填写简洁明确、有信息量的内容" - /> - </el-form-item> - </el-row> - </el-form> - <template #footer> - <el-button @click="cancelVideo">取 消</el-button> - <el-button type="primary" @click="submitVideo">提 交</el-button> - </template> - </el-dialog> + <!-- 新建视频的弹窗 --> + <UploadVideo v-model="showCreateVideo" /> <!-- 列表 --> - <el-table :data="list" stripe border v-loading="loading" style="margin-top: 10px"> - <el-table-column label="编号" align="center" prop="mediaId" /> - <el-table-column label="文件名" align="center" prop="name" /> - <el-table-column label="标题" align="center" prop="title" /> - <el-table-column label="介绍" align="center" prop="introduction" /> - <el-table-column label="视频" align="center"> - <template #default="scope"> - <WxVideoPlayer v-if="scope.row.url" :url="scope.row.url" /> - </template> - </el-table-column> - <el-table-column - label="上传时间" - align="center" - :formatter="dateFormatter" - prop="createTime" - width="180" - > - <template #default="scope"> - <span>{{ scope.row.createTime }}</span> - </template> - </el-table-column> - <el-table-column label="操作" align="center" fixed="right"> - <template #default="scope"> - <el-button type="primary" link plain @click="handleDownload(scope.row)"> - <Icon icon="ep:download" />下载 - </el-button> - <el-button - type="primary" - link - size="small" - plain - @click="handleDelete(scope.row)" - v-hasPermi="['mp:material:delete']" - > - <Icon icon="ep:delete" />删除 - </el-button> - </template> - </el-table-column> - </el-table> + <VideoTable :list="list" :loading="loading" @delete="handleDelete" /> <!-- 分页组件 --> <Pagination :total="total" @@ -246,39 +87,19 @@ </template> <script lang="ts" setup name="MpMaterial"> -import WxVoicePlayer from '@/views/mp/components/wx-voice-play/main.vue' -import WxVideoPlayer from '@/views/mp/components/wx-video-play/main.vue' import WxAccountSelect from '@/views/mp/components/wx-account-select/main.vue' +import Waterfall from './components/Waterfall.vue' +import VoiceTable from './components/VoiceTable.vue' +import VideoTable from './components/VideoTable.vue' +import Upload from './components/Upload.vue' +import UploadVideo from './components/UploadVideo.vue' +import { MaterialType } from './components/upload' import * as MpMaterialApi from '@/api/mp/material' -import * as authUtil from '@/utils/auth' -import { dateFormatter } from '@/utils/formatTime' -import type { - FormInstance, - FormRules, - TabPaneName, - UploadInstance, - UploadProps, - UploadRawFile, - UploadUserFile -} from 'element-plus' - -const BASE_URL = import.meta.env.VITE_BASE_URL -const uploadUrl = BASE_URL + '/admin-api/mp/material/upload-permanent' -const headers = { Authorization: 'Bearer ' + authUtil.getAccessToken() } const message = useMessage() -const uploadFormRef = ref<FormInstance>() -const uploadVideoRef = ref<UploadInstance>() - -const uploadRules: FormRules = { - title: [{ required: true, message: '请输入标题', trigger: 'blur' }], - introduction: [{ required: true, message: '请输入描述', trigger: 'blur' }] -} - // 素材类型 -type MaterialType = 'image' | 'voice' | 'video' -const type = ref<MaterialType>('image') +const type = ref<MaterialType>(MaterialType.Image) const loading = ref(false) // 遮罩层 const list = ref<any[]>([]) // 总条数 const total = ref(0) // 数据列表 @@ -296,22 +117,8 @@ const queryParams: QueryParams = reactive({ permanent: true }) -const fileList = ref<UploadUserFile[]>([]) - -interface UploadData { - type: MaterialType - title: string - introduction: string -} -const uploadData: UploadData = reactive({ - type: 'image', - title: '', - introduction: '' -}) - // === 视频上传,独有变量 === -const dialogVideoVisible = ref(false) -const addMaterialLoading = ref(false) +const showCreateVideo = ref(false) /** 侦听公众号变化 **/ const onAccountChanged = (id?: number) => { @@ -341,10 +148,7 @@ const handleQuery = () => { getList() } -const onTabChange = (tabName: TabPaneName) => { - // 设置 type - uploadData.type = tabName as MaterialType - +const onTabChange = () => { // 提前情况数据,避免tab切换后显示垃圾数据 list.value = [] total.value = 0 @@ -353,160 +157,12 @@ const onTabChange = (tabName: TabPaneName) => { handleQuery() } -// ======================== 文件上传 ======================== -const beforeUpload = (rawFile: UploadRawFile, category: 'image' | 'audio' | 'video'): boolean => { - let allowTypes: string[] = [] - let maxSizeMB = 0 - let name = '' - - switch (category) { - case 'image': - allowTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/bmp', 'image/jpg'] - maxSizeMB = 2 - name = '图片' - break - case 'audio': - allowTypes = ['audio/mp3', 'audio/mpeg', 'audio/wma', 'audio/wav', 'audio/amr'] - maxSizeMB = 2 - name = '图片' - break - case 'video': - allowTypes = ['video/mp4'] - maxSizeMB = 10 - name = '视频' - } - - if (!allowTypes.includes(rawFile.type)) { - message.error(`上传${name}格式不对!`) - return false - } - // 校验大小 - if (rawFile.size / 1024 / 1024 > maxSizeMB) { - message.error(`上传${name}大小不能超过${maxSizeMB}M!`) - return false - } - loading.value = true - return true -} - -const beforeImageUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'image') - -const beforeVoiceUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'audio') - -const beforeVideoUpload: UploadProps['beforeUpload'] = (rawFile: UploadRawFile) => - beforeUpload(rawFile, 'video') - -const handleUploadSuccess: UploadProps['onSuccess'] = (response: any) => { - loading.value = false - addMaterialLoading.value = false - if (response.code !== 0) { - message.error('上传出错:' + response.msg) - return false - } - - // 清空上传时的各种数据 - dialogVideoVisible.value = false - fileList.value = [] - uploadData.title = '' - uploadData.introduction = '' - - // 加载数据 - getList() -} - -// 下载文件 -const handleDownload = (row: any) => { - window.open(row.url, '_blank') -} - -// 提交 video 新建的表单 -const submitVideo = () => { - uploadFormRef.value?.validate((valid) => { - if (!valid) { - return false - } - uploadVideoRef.value?.submit() - }) -} - -// 弹出 video 新建的表单 -const handleAddVideo = () => { - resetVideo() - dialogVideoVisible.value = true -} - -/** 取消按钮 */ -const cancelVideo = () => { - dialogVideoVisible.value = false - resetVideo() -} - -/** 表单重置 */ -const resetVideo = () => { - fileList.value = [] - uploadData.title = '' - uploadData.introduction = '' - uploadFormRef.value?.resetFields() -} - // ======================== 其它操作 ======================== -const handleDelete = async (item: any) => { +const handleDelete = async (id: number) => { await message.confirm('此操作将永久删除该文件, 是否继续?') - await MpMaterialApi.deletePermanentMaterial(item.id) + await MpMaterialApi.deletePermanentMaterial(id) message.alertSuccess('删除成功') } </script> -<style lang="scss" scoped> -/*瀑布流样式*/ -.waterfall { - width: 100%; - column-gap: 10px; - column-count: 5; - margin-top: 10px; - /* 芋道源码:增加 10px,避免顶着上面 */ -} - -.waterfall-item { - padding: 10px; - margin-bottom: 10px; - break-inside: avoid; - border: 1px solid #eaeaea; -} - -.material-img { - width: 100%; -} - -p { - line-height: 30px; -} - -@media (min-width: 992px) and (max-width: 1300px) { - .waterfall { - column-count: 3; - } - - p { - color: red; - } -} - -@media (min-width: 768px) and (max-width: 991px) { - .waterfall { - column-count: 2; - } - - p { - color: orange; - } -} - -@media (max-width: 767px) { - .waterfall { - column-count: 1; - } -} -</style> +<style lang="scss" scoped></style>