|
|
@@ -29,6 +29,7 @@
|
|
|
<div class="table-header">
|
|
|
<div class="header-button-lf">
|
|
|
<el-button type="primary" icon="Plus" @click="openDialog()">新增素材</el-button>
|
|
|
+ <el-button type="success" icon="Upload" @click="openUploadDialog()">上传文件</el-button>
|
|
|
</div>
|
|
|
<div class="header-button-ri">
|
|
|
<el-button :icon="Refresh" circle @click="refresh" />
|
|
|
@@ -130,15 +131,64 @@
|
|
|
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">确定</el-button>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
+
|
|
|
+ <!-- 上传弹窗 -->
|
|
|
+ <el-dialog v-model="uploadDialogVisible" title="上传文件" width="600px" center destroy-on-close>
|
|
|
+ <el-form ref="uploadFormRef" :model="uploadForm" :rules="uploadFormRules" label-width="100px">
|
|
|
+ <el-form-item label="分组" prop="group_id">
|
|
|
+ <el-select v-model="uploadForm.group_id" placeholder="请选择分组" style="width: 100%">
|
|
|
+ <el-option v-for="item in groupOptions" :key="item.id" :label="item.name" :value="item.id" />
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="上传文件" prop="file">
|
|
|
+ <el-upload
|
|
|
+ ref="uploadRef"
|
|
|
+ class="upload-area"
|
|
|
+ drag
|
|
|
+ action="#"
|
|
|
+ :auto-upload="false"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :on-remove="handleFileRemove"
|
|
|
+ :limit="1"
|
|
|
+ :file-list="fileList"
|
|
|
+ accept="image/*,video/*,audio/*,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
|
|
|
+ >
|
|
|
+ <el-icon class="el-icon--upload"><upload-filled /></el-icon>
|
|
|
+ <div class="el-upload__text">
|
|
|
+ 拖拽文件到此处 或 <em>点击上传</em>
|
|
|
+ </div>
|
|
|
+ <template #tip>
|
|
|
+ <div class="el-upload__tip">
|
|
|
+ 支持图片、视频、音频、文档等格式,单个文件不超过50MB
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="预览" v-if="uploadPreviewUrl">
|
|
|
+ <el-image
|
|
|
+ v-if="uploadForm.type === 'image'"
|
|
|
+ :src="uploadPreviewUrl"
|
|
|
+ style="max-width: 200px; max-height: 200px"
|
|
|
+ fit="contain"
|
|
|
+ />
|
|
|
+ <span v-else>{{ uploadForm.name }}</span>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <el-button @click="uploadDialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" :loading="uploadLoading" @click="handleUpload">上传并保存</el-button>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
import { ref, reactive, onMounted } from "vue";
|
|
|
import dayjs from "dayjs";
|
|
|
-import { Refresh } from "@element-plus/icons-vue";
|
|
|
+import { Refresh, UploadFilled } from "@element-plus/icons-vue";
|
|
|
import { ElNotification, ElMessageBox } from "element-plus";
|
|
|
import Pagination from "@/components/Pangination/Pagination.vue";
|
|
|
import { getMaterialList, createMaterial, updateMaterial, deleteMaterial, getMaterialGroupList } from "@/api/modules/daytask.js";
|
|
|
+import { uploadImg } from "@/api/modules/upload.js";
|
|
|
|
|
|
const searchForm = ref({ group_id: null, name: null, type: null });
|
|
|
const tableData = ref([]);
|
|
|
@@ -323,6 +373,119 @@ const handleDelete = async (row) => {
|
|
|
}
|
|
|
}
|
|
|
};
|
|
|
+
|
|
|
+// ==================== 上传相关 ====================
|
|
|
+const uploadDialogVisible = ref(false);
|
|
|
+const uploadLoading = ref(false);
|
|
|
+const uploadRef = ref(null);
|
|
|
+const uploadFormRef = ref(null);
|
|
|
+const fileList = ref([]);
|
|
|
+const uploadPreviewUrl = ref("");
|
|
|
+const uploadForm = ref({
|
|
|
+ group_id: null,
|
|
|
+ name: "",
|
|
|
+ type: "image",
|
|
|
+ file: null,
|
|
|
+ size: 0
|
|
|
+});
|
|
|
+const uploadFormRules = ref({
|
|
|
+ group_id: [{ required: true, message: "请选择分组", trigger: "change" }]
|
|
|
+});
|
|
|
+
|
|
|
+const openUploadDialog = () => {
|
|
|
+ uploadForm.value = {
|
|
|
+ group_id: null,
|
|
|
+ name: "",
|
|
|
+ type: "image",
|
|
|
+ file: null,
|
|
|
+ size: 0
|
|
|
+ };
|
|
|
+ fileList.value = [];
|
|
|
+ uploadPreviewUrl.value = "";
|
|
|
+ uploadDialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+const getFileType = (file) => {
|
|
|
+ const mimeType = file.type || "";
|
|
|
+ if (mimeType.startsWith("image/")) return "image";
|
|
|
+ if (mimeType.startsWith("video/")) return "video";
|
|
|
+ if (mimeType.startsWith("audio/")) return "audio";
|
|
|
+ return "document";
|
|
|
+};
|
|
|
+
|
|
|
+const handleFileChange = (file) => {
|
|
|
+ uploadForm.value.file = file.raw;
|
|
|
+ uploadForm.value.name = file.name;
|
|
|
+ uploadForm.value.size = file.size;
|
|
|
+ uploadForm.value.type = getFileType(file.raw);
|
|
|
+
|
|
|
+ // 如果是图片,生成预览
|
|
|
+ if (uploadForm.value.type === "image") {
|
|
|
+ uploadPreviewUrl.value = URL.createObjectURL(file.raw);
|
|
|
+ } else {
|
|
|
+ uploadPreviewUrl.value = "";
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const handleFileRemove = () => {
|
|
|
+ uploadForm.value.file = null;
|
|
|
+ uploadForm.value.name = "";
|
|
|
+ uploadForm.value.size = 0;
|
|
|
+ uploadPreviewUrl.value = "";
|
|
|
+};
|
|
|
+
|
|
|
+const handleUpload = async () => {
|
|
|
+ if (!uploadFormRef.value) return;
|
|
|
+
|
|
|
+ await uploadFormRef.value.validate(async (valid) => {
|
|
|
+ if (!valid) return;
|
|
|
+
|
|
|
+ if (!uploadForm.value.file) {
|
|
|
+ ElNotification.warning("请选择要上传的文件");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ uploadLoading.value = true;
|
|
|
+ try {
|
|
|
+ // 1. 上传文件到 MinIO
|
|
|
+ const formData = new FormData();
|
|
|
+ formData.append("file", uploadForm.value.file);
|
|
|
+
|
|
|
+ const uploadRes = await uploadImg(formData);
|
|
|
+ if (uploadRes.code !== 200) {
|
|
|
+ ElNotification.error(uploadRes.msg || "文件上传失败");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const fileUrl = uploadRes.data.path;
|
|
|
+
|
|
|
+ // 2. 创建素材记录
|
|
|
+ const materialData = {
|
|
|
+ group_id: uploadForm.value.group_id,
|
|
|
+ name: uploadForm.value.name,
|
|
|
+ type: uploadForm.value.type,
|
|
|
+ url: fileUrl,
|
|
|
+ size: uploadForm.value.size,
|
|
|
+ status: 1,
|
|
|
+ sort: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ const createRes = await createMaterial(materialData);
|
|
|
+ if (createRes.code === 200) {
|
|
|
+ ElNotification.success("上传成功");
|
|
|
+ uploadDialogVisible.value = false;
|
|
|
+ getList();
|
|
|
+ } else {
|
|
|
+ ElNotification.error(createRes.msg || "保存素材失败");
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.error("上传失败", error);
|
|
|
+ ElNotification.error("上传失败");
|
|
|
+ } finally {
|
|
|
+ uploadLoading.value = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
@@ -330,4 +493,16 @@ const handleDelete = async (row) => {
|
|
|
display: inline-block;
|
|
|
vertical-align: middle;
|
|
|
}
|
|
|
+
|
|
|
+.upload-area {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-area :deep(.el-upload) {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+
|
|
|
+.upload-area :deep(.el-upload-dragger) {
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
</style>
|