瀏覽代碼

fix:1.解决图片上传的问题,

suwenjiang 3 月之前
父節點
當前提交
048e8a75f4
共有 3 個文件被更改,包括 183 次插入115 次删除
  1. 6 1
      src/components/CreateNote/Form.vue
  2. 83 45
      src/components/CreateNote/HeaderBanner.vue
  3. 94 69
      src/pages/note-create/index.client.vue

+ 6 - 1
src/components/CreateNote/Form.vue

@@ -66,6 +66,7 @@
     ></van-field>
 
     <van-field
+      is-link
       v-model="endPlace"
       :label-width="labelWidth"
       clearable
@@ -227,4 +228,8 @@ async function getTravelModeOptions() {
 }
 </script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+::v-deep .van-picker__confirm {
+  color: #fd9a00;
+}
+</style>

+ 83 - 45
src/components/CreateNote/HeaderBanner.vue

@@ -29,23 +29,27 @@
       </div>
     </div>
 
-    <!-- <van-dialog title="图片剪裁" v-model:show="cropperDialogVisible" width="375"> -->
-    <!-- <div class="h-full w-full"> -->
-    <!-- <img ref="cropperRef" :src="cropperImageBase64" alt="" /> -->
-    <!-- <vueCropper
-          ref="cropperRef"
-          :img="cropperImageBase64"
-          autoCrop
-          :outputSize="1"
-          centerBox
-          fixed
-          fixedBox
-          original
-          :full="true"
-          :fixedNumber="[3.2, 1]"
-        ></vueCropper> -->
-    <!-- </div> -->
-    <!-- <template #footer>
+    <!-- <van-dialog title="图片剪裁" v-model:show="cropperDialogVisible">
+    
+      <vueCropper
+        ref="cropperRef"
+        :img="cropperImageBase64"
+        :autoCrop="true"
+        high
+        info
+        canMove
+        autoCropWidth="80%"
+        :outputSize="1"
+        centerBox
+        fixed
+        mode
+        fixedBox
+        original
+        :full="true"
+        :fixedNumber="[3.2, 1]"
+      ></vueCropper>
+
+      <template #footer>
         <div class="flex items-center justify-center space-x-20 pt-10 pb-10">
           <van-button
             round
@@ -66,8 +70,8 @@
             确认
           </van-button>
         </div>
-      </template> -->
-    <!-- </van-dialog> -->
+      </template>
+    </van-dialog> -->
   </div>
 </template>
 
@@ -79,12 +83,12 @@ import image from '~/assets/img/note-create/image.svg'
 // import 'vue-cropper/dist/index.css'
 
 const bannerUrl = defineModel('bannerUrl')
-
 const { open, onChange } = useFileDialog({
   accept: '.png,.png,.jpeg,.JPG,Png '
 })
 
 // const cropperImageBase64 = ref('')
+// const cropperDialogVisible = ref(false)
 
 function handleSelectImage() {
   open()
@@ -92,38 +96,72 @@ function handleSelectImage() {
 
 onChange(async (files) => {
   if (!files.length) return
-  const reader = new FileReader()
-  reader.readAsDataURL(files[0])
-  reader.onload = () => {
-    bannerUrl.value = reader.result
-    handleCropperOk(files[0])
-  }
-})
+  const formData = new FormData()
 
-// const cropperRef = ref(null)
-// const cropperDialogVisible = ref(false)
-const loading = ref(false)
+  formData.append('uploadFile', files[0])
+  formData.append('asImage', true)
+  formData.append('fieldName', 'travelNotesBanner')
+  const maxSize = 5 * 1024 * 1024 // 10 MB
+  if (files[0].size > maxSize) showToast('上传图片过大,请重新上传')
 
-async function handleCropperOk(data) {
   try {
-    loading.value = true
-    // 此处需上传图片,保存URL
-    const formData = new FormData()
-
-    formData.append('uploadFile', data)
-    formData.append('asImage', true)
-    formData.append('fieldName', 'travelNotesBanner')
-    const res = await request('/admin/app/tourismProjectTravelNotesWrite/upload', {
+    showLoadingToast({
+      message: '图片上传中...'
+    })
+    const { data } = await request('/admin/app/tourismProjectTravelNotesWrite/upload', {
       method: 'post',
       body: formData
     })
-    const url = res.data.fileUrl
-    loading.value = true
-    bannerUrl.value = url
-  } finally {
-    loading.value = false
+
+    bannerUrl.value = data.fileUrl
+    closeToast()
+  } catch (error) {
+    closeToast()
+    showToast('图片上传失败')
+    console.log('图片上传失败')
   }
-}
+})
+
+// onChange((files) => {
+//   if (!files.length) return
+//   const reader = new FileReader()
+//   reader.readAsDataURL(files[0])
+//   console.log(files[0], '111')
+
+//   reader.onload = () => {
+//     cropperDialogVisible.value = true
+//     console.log(reader.result, '1111')
+
+//     cropperImageBase64.value = reader.result
+//   }
+// })
+
+// const cropperRef = ref(null)
+// const loading = ref(false)
+
+// async function handleCropperOk() {
+//   cropperRef.value?.getCropBlob(async (data) => {
+//     try {
+//       loading.value = true
+//       // 此处需上传图片,保存URL
+//       const formData = new FormData()
+//       formData.append('uploadFile', data)
+//       formData.append('asImage', true)
+//       formData.append('fieldName', 'travelNotesBanner')
+//       console.log(data, '1232')
+
+//       // const res = await request('/admin/app/tourismProjectTravelNotesWrite/upload', {
+//       //   method: 'post',
+//       //   body: formData
+//       // })
+//       // const url = res.data.fileUrl
+//       // bannerUrl.value = url
+//       // cropperDialogVisible.value = false
+//     } finally {
+//       loading.value = false
+//     }
+//   })
+// }
 </script>
 
 <style lang="scss" scoped></style>

+ 94 - 69
src/pages/note-create/index.client.vue

@@ -33,10 +33,22 @@
         <h1 class="text-sm font-bold">编辑游记文章</h1>
       </div>
 
-      <VueDraggable v-model="noteJson.travelNotesContent" :options="dragOptions">
+      <!-- draggable="img"  :scroll="true"
+        
+        :scroll-sensitivity="100"
+        bubble-scroll delay="1000" :scroll-sensitivity="100"   -->
+      <VueDraggable
+        :scroll="true"
+        :handle="'.drag'"
+        v-model="noteJson.travelNotesContent"
+        :options="dragOptions"
+      >
         <template v-for="(item, index) in noteJson.travelNotesContent" :key="item.tmpId">
           <div v-if="item.type === defaultSectionTitle.type" class="h-50 mb-12 box-border">
-            <van-cell-group class="border h-full focus:border-[#FF9300]" inset>
+            <van-cell-group
+              class="border flex h-full focus:border-[#FF9300] active:shadow-[_0px_6px_4px_0px_rgba(0,0,0,0.25)]"
+              inset
+            >
               <van-field
                 v-model="item.content"
                 rows="1"
@@ -50,13 +62,19 @@
                 @update:model-value="handleInsertOrEditTitle"
               >
                 <template #extra>
-                  <div class="w-16 h-16 z-0">
-                    <img
-                      @click="handleDeleteTitle(index)"
-                      class="w-full h-full"
-                      src="~/assets/img/note-create/delete.svg"
-                      alt=""
-                    />
+                  <div class="flex">
+                    <div class="drag flex mr-10">
+                      <img class="w-16 h-16" src="~/assets/img/note-create/drag.svg" alt="" />
+                      <span class="text-sm text-black-3">拖拽</span>
+                    </div>
+                    <div class="w-16 h-16 z-0">
+                      <img
+                        @click="handleDeleteTitle(index)"
+                        class="w-full h-full"
+                        src="~/assets/img/note-create/delete.svg"
+                        alt=""
+                      />
+                    </div>
                   </div>
                 </template>
               </van-field>
@@ -67,7 +85,6 @@
             v-else-if="item.type === defaultSectionContent.type"
             class="h-100 mb-12 relative box-border"
           >
-            <!-- focus:outline-none focus:caret-[#FF9300] active:border-[#FF9300]  focus:border-[#FF9300]-->
             <van-cell-group
               class="border h-full active:shadow-[_0px_6px_4px_0px_rgba(0,0,0,0.25)]"
               inset
@@ -86,13 +103,19 @@
                 @update:model-value="handleInsertOrEditTitle"
               >
                 <template #extra>
-                  <div class="w-16 h-16 z-0">
-                    <img
-                      @click="handleDeleteTitle(index)"
-                      class="w-full h-full"
-                      src="../../assets/img/note-create/delete.svg"
-                      alt=""
-                    />
+                  <div class="flex">
+                    <div class="drag flex mr-10">
+                      <img class="w-16 h-16" src="~/assets/img/note-create/drag.svg" alt="" />
+                      <span class="text-sm text-black-3">拖拽</span>
+                    </div>
+                    <div class="w-16 h-16 z-0">
+                      <img
+                        @click="handleDeleteTitle(index)"
+                        class="w-full h-full"
+                        src="../../assets/img/note-create/delete.svg"
+                        alt=""
+                      />
+                    </div>
                   </div>
                 </template>
               </van-field>
@@ -102,20 +125,25 @@
           <div v-else-if="item.type === defaultSectionImage.type" class="relative box-border mb-12">
             <template v-if="item.content">
               <div>
-                <van-cell-group class="border h-full" inset>
+                <van-cell-group
+                  class="border h-full active:shadow-[_0px_6px_4px_0px_rgba(0,0,0,0.25)]"
+                  inset
+                >
                   <div v-if="item.content">
                     <img :src="item.content" alt="Uploaded Image" />
                   </div>
                 </van-cell-group>
                 <div
-                  class="w-110 rounded-xl box-border px-10 h-20 flex justify-between items-center h-16 absolute top-12 right-26 z-100 bg-[#fff]/[0.5]"
+                  class="w-150 rounded-xl box-border px-10 h-20 flex justify-between items-center h-16 absolute top-12 right-26 z-100 bg-[#fff]/[0.5]"
                 >
-                  <span
-                    @click="handleSaveCover(item)"
-                    class="text-sm pr-7 border-r-[1px] border-[#F3F3F3] text-black-3"
-                  >
+                  <span @click="handleSaveCover(item)" class="text-sm text-black-3">
                     设为封面图
                   </span>
+                  <div class="drag flex border-r-[1px] border-[#F3F3F3] pr-7">
+                    <img class="w-16 h-16" src="~/assets/img/note-create/drag.svg" alt="" />
+                    <span class="text-sm text-black-3">拖拽</span>
+                  </div>
+
                   <div class="w-16 h-16 inline-block">
                     <img
                       @click="handleDeleteImage(index)"
@@ -130,10 +158,10 @@
             <!-- 没有图片的样式 -->
             <template v-else>
               <div class="h-200">
-                <van-cell-group class="border h-full" inset>
-                  <!-- <div v-if="itemsImage">
-                    <img ref="cropperRef" class="w-full h-full" :src="itemsImage" alt="" />
-                  </div> v-else -->
+                <van-cell-group
+                  class="border h-full active:shadow-[_0px_6px_4px_0px_rgba(0,0,0,0.25)]"
+                  inset
+                >
                   <div class="w-full h-full flex justify-center items-center">
                     <button
                       @click="handleSelectImage(index)"
@@ -149,15 +177,20 @@
                 </van-cell-group>
 
                 <div
-                  class="w-86 flex justify-between items-center h-16 absolute top-10 right-26 z-100"
+                  class="w-136 flex justify-between items-center h-16 absolute top-10 right-26 z-100"
                 >
                   <span @click="showToast('请上传图片')" class="text-sm text-black-3">
                     设为封面图
                   </span>
+                  <div class="drag flex pr-7">
+                    <img class="w-16 h-16" src="~/assets/img/note-create/drag.svg" alt="" />
+                    <span class="text-sm text-black-3">拖拽</span>
+                  </div>
+
                   <div class="w-16 h-16 inline-block">
                     <img
                       @click="handleDeleteImage(index)"
-                      class="w-full h-full"
+                      class="w-full h-full drag"
                       src="~/assets/img/note-create/delete.svg"
                       alt=""
                     />
@@ -399,8 +432,8 @@ import upload from '~/assets/img/note-create/upload.svg'
 import draft from '~/assets/img/note-create/draft.svg'
 // import { cloneDeep } from 'lodash-es'
 import { VueDraggable } from 'vue-draggable-plus'
-import { nanoid } from 'nanoid'
 
+import { nanoid } from 'nanoid'
 
 const dragOptions = {
   disabled: false, // 是否禁用拖拽
@@ -507,7 +540,6 @@ async function getNoteDetail() {
 }
 
 /************ 插入段落标题逻辑 ********** */
-
 const insertTilteOptions = reactive({
   show: false,
   content: null,
@@ -549,52 +581,46 @@ function handleDeleteTitle(index) {
 
 /******************插入正文相关逻辑*******************/
 
-const imageLoading = ref(false)
-
 // 单个点击上传图片的事件
 const handleSelectImage = (index) => {
   handleInsertOrEditTitleIndex(index)
   open()
 }
 
-onChange((files) => {
+onChange(async (files) => {
   if (!files.length) return
-  const reader = new FileReader()
-  reader.readAsDataURL(files[0])
-  reader.onload = () => {
-    if (noteJson.travelNotesContent[editIndex.value].type == 'image') {
-      noteJson.travelNotesContent[editIndex.value].content = reader.result
+  console.log(files[0], '222')
+
+  const formData = new FormData()
+  formData.append('uploadFile', files[0])
+  formData.append('asImage', true)
+  formData.append('fieldName', 'travelNotesBanner')
+  const maxSize = 5 * 1024 * 1024 // 10 MB
+  if (files[0].size > maxSize) {
+    showToast('上传图片过大,请重新上传')
+    return
+  } else {
+    try {
+      showLoadingToast({
+        message: '图片上传中...'
+      })
+
+      const { data } = await request('/admin/app/tourismProjectTravelNotesWrite/upload', {
+        method: 'post',
+        body: formData
+      })
+      const url = data.fileUrl
+      if (noteJson.travelNotesContent[editIndex.value].type == 'image') {
+        noteJson.travelNotesContent[editIndex.value].content = url
+        closeToast()
+      }
+    } catch (error) {
+      closeToast()
+      showToast('图片上传失败')
     }
-
-    handleCropperOk(files[0])
   }
 })
 
-async function handleCropperOk(data) {
-  console.log(data, '12222')
-  try {
-    // imageLoading.value = true
-    // 此处需上传图片,保存URL
-    const formData = new FormData()
-    formData.append('uploadFile', data)
-    formData.append('asImage', true)
-    formData.append('fieldName', 'travelNotesBanner')
-
-    console.log(formData, 'formData')
-
-    const res = await request('/admin/app/tourismProjectTravelNotesWrite/upload', {
-      method: 'post',
-      body: formData
-    })
-    const url = res.data.fileUrl
-    if (noteJson.travelNotesContent[editIndex.value].type == 'image') {
-      noteJson.travelNotesContent[editIndex.value].content = url
-    }
-  } finally {
-    // imageLoading.value = false
-  }
-}
-
 /******************插入图片逻辑*******************/
 
 function handleDeleteImage(index) {
@@ -622,11 +648,10 @@ function handleSaveCover(item) {
 async function handleSaveDraft() {
   noteJson.endPlace = noteJson?.endPlaceId
   delete noteJson.endPlaceId
-
-  
   try {
     await request('/website/tourism/publishTravelNotes/saveDraft', {
       method: 'post',
+
       body: {
         ...noteJson,
         id: id?.value
@@ -709,7 +734,7 @@ async function requestPublish() {
 
     noteJson.endPlace = noteJson.endPlaceId
     delete noteJson.endPlaceId
-   
+
     await request('/website/tourism/publishTravelNotes/publishDraft', {
       method: 'post',
       body: {