diff --git a/src/components.d.ts b/src/components.d.ts index fb962c0..207249a 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -5,62 +5,62 @@ // Read more: https://github.com/vuejs/core/pull/3399 export {} -declare module 'vue' { - export interface GlobalComponents { - ElAside: typeof import('element-plus/es')['ElAside'] - ElAutocomplete: typeof import('element-plus/es')['ElAutocomplete'] - ElBreadcrumb: typeof import('element-plus/es')['ElBreadcrumb'] - ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem'] - ElButton: typeof import('element-plus/es')['ElButton'] - ElCarousel: typeof import("element-plus/es")["ElCarousel"] - ElCarouselItem: typeof import("element-plus/es")["ElCarouselItem"] - ElCheckbox: typeof import('element-plus/es')['ElCheckbox'] - ElCheckboxGroup: typeof import('element-plus/es')['ElCheckboxGroup'] - ElColorPicker: typeof import("element-plus/es")["ElColorPicker"] - ElContainer: typeof import('element-plus/es')['ElContainer'] - ElDatePicker: typeof import('element-plus/es')['ElDatePicker'] - ElDialog: typeof import('element-plus/es')['ElDialog'] - ElDivider: typeof import('element-plus/es')['ElDivider'] - ElDrawer: typeof import('element-plus/es')['ElDrawer'] - ElDropdown: typeof import('element-plus/es')['ElDropdown'] - ElDropdownItem: typeof import('element-plus/es')['ElDropdownItem'] - ElDropdownMenu: typeof import('element-plus/es')['ElDropdownMenu'] - ElForm: typeof import('element-plus/es')['ElForm'] - ElFormItem: typeof import('element-plus/es')['ElFormItem'] - ElHeader: typeof import('element-plus/es')['ElHeader'] - ElIcon: typeof import('element-plus/es')['ElIcon'] - ElImage: typeof import('element-plus/es')['ElImage'] - ElInput: typeof import('element-plus/es')['ElInput'] - ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] - ElMain: typeof import('element-plus/es')['ElMain'] - ElMenu: typeof import('element-plus/es')['ElMenu'] - ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] - ElOption: typeof import('element-plus/es')['ElOption'] - ElPagination: typeof import('element-plus/es')['ElPagination'] - ElRadio: typeof import('element-plus/es')['ElRadio'] - ElRadioButton: typeof import("element-plus/es")["ElRadioButton"] - ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] - ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] - ElSelect: typeof import('element-plus/es')['ElSelect'] - ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] - ElSwitch: typeof import('element-plus/es')['ElSwitch'] - ElTable: typeof import('element-plus/es')['ElTable'] - ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] - ElTabPane: typeof import('element-plus/es')['ElTabPane'] - ElTabs: typeof import('element-plus/es')['ElTabs'] - ElTag: typeof import('element-plus/es')['ElTag'] - ElTooltip: typeof import('element-plus/es')['ElTooltip'] - ElTree: typeof import("element-plus/es")["ElTree"] - ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] - ElUpload: typeof import('element-plus/es')['ElUpload'] - IEpArrowDown: typeof import('~icons/ep/arrow-down')['default'] - IEpCircleClose: typeof import('~icons/ep/circle-close')['default'] - IEpFolderDelete: typeof import('~icons/ep/folder-delete')['default'] - IEpFullScreen: typeof import('~icons/ep/full-screen')['default'] - IEpRemove: typeof import('~icons/ep/remove')['default'] - IEpSearch: typeof import('~icons/ep/search')['default'] - IEpSwitchButton: typeof import('~icons/ep/switch-button')['default'] - RouterLink: typeof import('vue-router')['RouterLink'] - RouterView: typeof import('vue-router')['RouterView'] - } +declare module "vue" { + export interface GlobalComponents { + ElAside: typeof import("element-plus/es")["ElAside"]; + ElAutocomplete: typeof import("element-plus/es")["ElAutocomplete"]; + ElBreadcrumb: typeof import("element-plus/es")["ElBreadcrumb"]; + ElBreadcrumbItem: typeof import("element-plus/es")["ElBreadcrumbItem"]; + ElButton: typeof import("element-plus/es")["ElButton"]; + ElCarousel: typeof import("element-plus/es")["ElCarousel"]; + ElCarouselItem: typeof import("element-plus/es")["ElCarouselItem"]; + ElCheckbox: typeof import("element-plus/es")["ElCheckbox"]; + ElCheckboxGroup: typeof import("element-plus/es")["ElCheckboxGroup"]; + ElColorPicker: typeof import("element-plus/es")["ElColorPicker"]; + ElContainer: typeof import("element-plus/es")["ElContainer"]; + ElDatePicker: typeof import("element-plus/es")["ElDatePicker"]; + ElDialog: typeof import("element-plus/es")["ElDialog"]; + ElDivider: typeof import("element-plus/es")["ElDivider"]; + ElDrawer: typeof import("element-plus/es")["ElDrawer"]; + ElDropdown: typeof import("element-plus/es")["ElDropdown"]; + ElDropdownItem: typeof import("element-plus/es")["ElDropdownItem"]; + ElDropdownMenu: typeof import("element-plus/es")["ElDropdownMenu"]; + ElForm: typeof import("element-plus/es")["ElForm"]; + ElFormItem: typeof import("element-plus/es")["ElFormItem"]; + ElHeader: typeof import("element-plus/es")["ElHeader"]; + ElIcon: typeof import("element-plus/es")["ElIcon"]; + ElImage: typeof import("element-plus/es")["ElImage"]; + ElInput: typeof import("element-plus/es")["ElInput"]; + ElInputNumber: typeof import("element-plus/es")["ElInputNumber"]; + ElMain: typeof import("element-plus/es")["ElMain"]; + ElMenu: typeof import("element-plus/es")["ElMenu"]; + ElMenuItem: typeof import("element-plus/es")["ElMenuItem"]; + ElOption: typeof import("element-plus/es")["ElOption"]; + ElPagination: typeof import("element-plus/es")["ElPagination"]; + ElRadio: typeof import("element-plus/es")["ElRadio"]; + ElRadioButton: typeof import("element-plus/es")["ElRadioButton"]; + ElRadioGroup: typeof import("element-plus/es")["ElRadioGroup"]; + ElScrollbar: typeof import("element-plus/es")["ElScrollbar"]; + ElSelect: typeof import("element-plus/es")["ElSelect"]; + ElSubMenu: typeof import("element-plus/es")["ElSubMenu"]; + ElSwitch: typeof import("element-plus/es")["ElSwitch"]; + ElTable: typeof import("element-plus/es")["ElTable"]; + ElTableColumn: typeof import("element-plus/es")["ElTableColumn"]; + ElTabPane: typeof import("element-plus/es")["ElTabPane"]; + ElTabs: typeof import("element-plus/es")["ElTabs"]; + ElTag: typeof import("element-plus/es")["ElTag"]; + ElTooltip: typeof import("element-plus/es")["ElTooltip"]; + ElTree: typeof import("element-plus/es")["ElTree"]; + ElTreeSelect: typeof import("element-plus/es")["ElTreeSelect"]; + ElUpload: typeof import("element-plus/es")["ElUpload"]; + IEpArrowDown: typeof import("~icons/ep/arrow-down")["default"]; + IEpCircleClose: typeof import("~icons/ep/circle-close")["default"]; + IEpFolderDelete: typeof import("~icons/ep/folder-delete")["default"]; + IEpFullScreen: typeof import("~icons/ep/full-screen")["default"]; + IEpRemove: typeof import("~icons/ep/remove")["default"]; + IEpSearch: typeof import("~icons/ep/search")["default"]; + IEpSwitchButton: typeof import("~icons/ep/switch-button")["default"]; + RouterLink: typeof import("vue-router")["RouterLink"]; + RouterView: typeof import("vue-router")["RouterView"]; + } } diff --git a/src/components/Editor/index.vue b/src/components/Editor/index.vue index 8a9633f..473fb80 100644 --- a/src/components/Editor/index.vue +++ b/src/components/Editor/index.vue @@ -43,6 +43,7 @@ import { h } from "@/utils/url"; import { routerObj } from "./utils.js"; import { titleConfig } from "./titleConfig.js"; import { uploadVideo, uploadImg } from "@/api/modules/upload"; +import { ElNotification } from "element-plus"; //uploadImg // 字体配置 let fontSizeStyle = Quill.import("attributors/style/size"); @@ -87,13 +88,14 @@ const props = defineProps({ const editorContent = computed({ get: () => props.content, set: val => { + console.log(val, "======value=========="); emit("update:content", val); } }); //富文本ref const myQuillEditor = ref(null); //富文本值 -const oldContent = ref(""); +// const oldContent = ref(""); //富文本配置项 const options = reactive({ theme: "snow", @@ -149,16 +151,32 @@ const options = reactive({ ] } }); +// 对 imageListDb 按文件名末尾数字排序(从小到大) +const sortImageListByNumber = () => { + imageListDb.value.sort((a, b) => { + // 提取文件名中的数字(匹配末尾的 -数字 格式) + const getNumber = fileName => { + // 正则匹配:以 - 开头,后面跟数字,且在文件名末尾(\d+$ 表示数字结尾) + const match = fileName.match(/-(\d+)$/); + // 若匹配到数字则返回,否则返回 0(避免无数字的文件排序出错) + return match ? parseInt(match[1], 10) : 0; + }; + // 分别获取 a 和 b 文件名中的数字 + const numA = getNumber(a.name); + const numB = getNumber(b.name); + + // 按数字从小到大排序(numA - numB 为升序) + return numA - numB; + }); +}; // 上传前的钩子 const handleBeforeUpload = file => { const fileType = file.type; - console.log(file, "====file===="); - // 为文件添加唯一标识 file.customUid = generateUUID(); // 确保有唯一ID imageListDb.value.push(file); - + sortImageListByNumber(); // 图片和视频格式校验 const validTypes = [ "image/jpeg", @@ -177,36 +195,42 @@ const handleBeforeUpload = file => { // 校检文件大小 const isLt = file.size / 1024 / 1024 < props.fileSizeLimit; if (!isLt) { - console.log(`上传文件大小不能超过 ${props.fileSizeLimit} MB!`); - alert(`上传文件大小不能超过 ${props.fileSizeLimit} MB!`); + ElNotification({ + title: "温馨提示", + message: `上传文件大小不能超过 ${props.fileSizeLimit} MB!`, + type: "warning" + }); + + imageListDb.value = []; return false; } return true; } else { - alert(`文件格式不正确!`); + ElNotification({ + title: "温馨提示", + message: `文件格式不正确!`, + type: "warning" + }); + imageListDb.value = []; return false; } }; // 图片上传 const handleHttpUpload = async options => { - console.log(imageListDb.value.length, "==============length============"); let formData = new FormData(); formData.append("image", options.file); imageList.value.push(options.file); - try { const result = await uploadImg(formData, routerName.value, options.file.customUid); - // 假设服务器返回格式为 { imgId: 'xxx', data: { code: 0, data: { path: 'xxx' } } } const { imgId } = result; - console.log(imgId, "==========imgId from server"); if (result?.data?.code === 0) { const { data } = result?.data; // 1. 通过customUid查找对应的文件对象 - const fileItem = imageListDb.value.find(item => item.customUid === options.file.customUid); + const fileItem = imageListDb.value.find(item => item.customUid === imgId); if (fileItem) { fileItem.serverImgId = imgId; // 保存服务器返回的imgId fileItem.path = data.path; // 保存图片路径 @@ -228,8 +252,6 @@ const handleHttpUpload = async options => { imageListDb.value.forEach((item, index) => { // 获取光标位置(每次插入后光标会移动) const length = quill.getLength() - 1; // 文本末尾 - console.log(length, "=插入位置="); - quill.insertEmbed(length, "image", { url: h + item.path, id: item.serverImgId || generateUUID() @@ -252,86 +274,6 @@ const handleHttpUpload = async options => { } }; -// //上传前的钩子 -// const handleBeforeUpload = file => { -// const fileType = file.type; -// console.log(file, "====file===="); -// imageListDb.value.push(file); -// // 图片 -// if ( -// fileType == "image/jpeg" || -// fileType == "image/png" || -// fileType == "image/gif" || -// fileType == "image/jpg" || -// fileType == "image/bmp" || -// fileType == "image/webp" || -// fileType == "video/mov" || -// fileType == "video/ts" || -// fileType == "video/mp4" || -// fileType == "video/avi" -// ) { -// const fileSizeLimit = file.size; -// // 校检文件大小 -// const isLt = fileSizeLimit / 1024 / 1024 < props.fileSizeLimit; -// if (!isLt) { -// console.log(`上传文件大小不能超过 ${props.fileSizeLimit} MB!`); -// alert(`上传文件大小不能超过 ${props.fileSizeLimit} MB!`); -// return false; -// } else { -// console.log(`RIch MB!`); -// return true; -// } -// } else { -// alert(`文件格式不正确!`); -// return false; -// } -// }; -// //图片上传 -// const handleHttpUpload = async options => { -// console.log(imageListDb.value.length, "==============length============"); -// let formData = new FormData(); -// //这里要根据后端设置的name设置key值,如果name是file就传file是image就传image -// formData.append("image", options.file); -// imageList.value.push(options.file); -// try { -// const result = await uploadImg(formData, routerName.value, options.file.uid); -// const { imgId } = result; -// console.log(imgId, "==========sdsdsd"); -// if (result?.data?.code === 0) { -// const { data } = result?.data; -// //获取到imgId,将data.path匹配 -// let iLength = imageListDb.value.length; -// for (let i = 0; i < iLength; i++) { -// let item = imageListDb.value[i]; -// if (item.uid == imgId) { -// item.path = data.path; -// } -// } -// if (imageList.value.length === imageListDb.value.length) { -// console.log("走进来了"); -// let tLength = imageListDb.value.length; -// for (let j = 0; j < tLength; j++) { -// let rawMyQuillEditor = toRaw(myQuillEditor.value); -// // 获取富文本实例 -// let quill = rawMyQuillEditor.getQuill(); -// // 获取光标位置 -// let length = quill.selection.savedRange.index; -// console.log(length, "=光标length="); -// quill.insertEmbed(length, "image", { -// url: h + imageListDb.value[j].path, -// id: generateUUID() -// }); -// quill.setSelection(length + 1); -// if (j === tLength - 1) { -// imageList.value = []; -// imageListDb.value = []; -// } -// } -// } -// } -// } catch (error) {} -// }; - //视频上传 const handleVideoUpload = async evt => { if (evt.target.files.length === 0) { @@ -367,9 +309,22 @@ const initTitle = () => { tip.setAttribute("title", item.title); } }; +// 获取 Quill 实例并定义清空方法 +const clearEditor = () => { + const rawMyQuillEditor = toRaw(myQuillEditor.value); + if (rawMyQuillEditor) { + const quill = rawMyQuillEditor.getQuill(); + quill.setText(""); // 清空内容(会触发 v-model 同步) + editorContent.value = ""; // 同步更新绑定的变量 + } +}; onMounted(() => { initTitle(); - oldContent.value = props.content; + // oldContent.value = props.content; +}); +// 暴露方法给父组件 +defineExpose({ + clearEditor });