♻️ Interactive v2 #1
| @@ -28,6 +28,7 @@ | ||||
|             label="Content" | ||||
|             hint="The content supports markdown syntax" | ||||
|             v-model="data.content" | ||||
|             @paste="pasteMedia" | ||||
|           /> | ||||
|  | ||||
|           <v-expansion-panels> | ||||
| @@ -73,9 +74,7 @@ | ||||
|                 <div class="flex justify-between items-center"> | ||||
|                   <div> | ||||
|                     <p class="text-xs">This article attached</p> | ||||
|                     <p class="text-lg font-medium"> | ||||
|                       {{ data.attachments.length }} attachment(s) | ||||
|                     </p> | ||||
|                     <p class="text-lg font-medium">{{ data.attachments.length }} attachment(s)</p> | ||||
|                   </div> | ||||
|                   <v-btn size="small" icon="mdi-camera-plus" variant="text" @click="dialogs.media = true" /> | ||||
|                 </div> | ||||
| @@ -88,7 +87,7 @@ | ||||
|   </v-card> | ||||
|  | ||||
|   <planned-publish v-model:show="dialogs.plan" v-model:value="data.publishedAt" /> | ||||
|   <media v-model:show="dialogs.media" v-model:uploading="uploading" v-model:value="data.attachments" /> | ||||
|   <media ref="media" v-model:show="dialogs.media" v-model:uploading="uploading" v-model:value="data.attachments" /> | ||||
|  | ||||
|   <v-snackbar v-model="success" :timeout="3000">Your article has been published.</v-snackbar> | ||||
|   <v-snackbar v-model="uploading" :timeout="-1"> | ||||
| @@ -158,6 +157,22 @@ async function postArticle(evt: SubmitEvent) { | ||||
|   } | ||||
|   loading.value = false | ||||
| } | ||||
|  | ||||
| const media = ref<any>(null) | ||||
|  | ||||
| function pasteMedia(evt: ClipboardEvent) { | ||||
|   const files = evt.clipboardData?.files | ||||
|   if (files) { | ||||
|     Array.from(files).forEach((item) => { | ||||
|       media.value.upload(item).then((meta: any) => { | ||||
|         if (meta) { | ||||
|           data.content += `\n` | ||||
|         } | ||||
|       }) | ||||
|     }) | ||||
|     evt.preventDefault() | ||||
|   } | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style scoped> | ||||
|   | ||||
| @@ -117,3 +117,13 @@ async function postMoment(evt: SubmitEvent) { | ||||
|   loading.value = false | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style> | ||||
| .snackbar-progress { | ||||
|   margin-left: -16px; | ||||
|   margin-right: -16px; | ||||
|   margin-bottom: -14px; | ||||
|   margin-top: 12px; | ||||
|   width: calc(100% + 64px); | ||||
| } | ||||
| </style> | ||||
| @@ -22,9 +22,7 @@ | ||||
|         <v-card variant="tonal"> | ||||
|           <v-list> | ||||
|             <v-list-item v-for="item in props.value" :title="getFileName(item)"> | ||||
|               <template #subtitle> | ||||
|                 {{ getFileType(item) }} · {{ formatBytes(item.filesize) }} | ||||
|               </template> | ||||
|               <template #subtitle> {{ getFileType(item) }} · {{ formatBytes(item.filesize) }} </template> | ||||
|               <template #append> | ||||
|                 <v-btn icon="mdi-delete" size="small" variant="text" color="error" /> | ||||
|               </template> | ||||
| @@ -68,16 +66,20 @@ async function upload(file?: any) { | ||||
|     headers: { Authorization: `Bearer ${getAtk()}` }, | ||||
|     body: data | ||||
|   }) | ||||
|   let meta: any; | ||||
|   if (res.status !== 200) { | ||||
|     error.value = await res.text() | ||||
|   } else { | ||||
|     const data = await res.json() | ||||
|     emits("update:value", props.value.concat([data.info])) | ||||
|     meta = await res.json() | ||||
|     emits("update:value", props.value.concat([meta.info])) | ||||
|     picked.value = [] | ||||
|   } | ||||
|   emits("update:uploading", false) | ||||
|   return meta | ||||
| } | ||||
|  | ||||
| defineExpose({ upload }) | ||||
|  | ||||
| function getFileName(item: any) { | ||||
|   return item.filename.replace(/\.[^/.]+$/, "") | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user