feat: restore postcreate.js
This commit is contained in:
@@ -20,4 +20,8 @@ export const mediaService = {
|
||||
uploadedSuccess(data) {
|
||||
return httpClient.post('/admin/uploads/post-uploaded-action', data);
|
||||
},
|
||||
|
||||
getMediaPreviewUrl(id) {
|
||||
return `${httpClient.defaults.baseURL}/admin/medias/${id}`;
|
||||
},
|
||||
};
|
||||
@@ -30,7 +30,6 @@ const post = reactive({
|
||||
selectedMedia: [],
|
||||
medias: [],
|
||||
status: 0,
|
||||
head_image: null, // Add head image field
|
||||
});
|
||||
|
||||
// Validation state
|
||||
@@ -38,8 +37,7 @@ const errors = reactive({
|
||||
title: '',
|
||||
introduction: '',
|
||||
selectedMedia: '',
|
||||
discount: '',
|
||||
head_image: '', // Add head image error field
|
||||
discount: ''
|
||||
});
|
||||
|
||||
// Media selection dialog state
|
||||
@@ -48,7 +46,6 @@ const selectedMediaItems = ref([]);
|
||||
const mediaLoading = ref(false);
|
||||
const mediaGlobalFilter = ref('');
|
||||
const mediaItems = ref([]);
|
||||
const isHeadImageSelection = ref(false); // Track if we're selecting head image
|
||||
|
||||
// Add pagination state for media dialog
|
||||
const mediaFirst = ref(0);
|
||||
@@ -66,18 +63,8 @@ const statusOptions = [
|
||||
{ label: '草稿', value: 0 }
|
||||
];
|
||||
|
||||
// Open media selection dialog for head image
|
||||
const openHeadImageDialog = () => {
|
||||
isHeadImageSelection.value = true;
|
||||
mediaDialogVisible.value = true;
|
||||
mediaCurrentPage.value = 1;
|
||||
mediaFirst.value = 0;
|
||||
loadMediaItems();
|
||||
};
|
||||
|
||||
// Open media selection dialog
|
||||
const openMediaDialog = () => {
|
||||
isHeadImageSelection.value = false;
|
||||
mediaDialogVisible.value = true;
|
||||
mediaCurrentPage.value = 1;
|
||||
mediaFirst.value = 0;
|
||||
@@ -112,16 +99,10 @@ const onMediaPage = (event) => {
|
||||
|
||||
// Confirm media selection
|
||||
const confirmMediaSelection = () => {
|
||||
if (isHeadImageSelection.value) {
|
||||
if (selectedMediaItems.value.length) {
|
||||
post.head_image = selectedMediaItems.value[0];
|
||||
errors.head_image = '';
|
||||
}
|
||||
} else if (selectedMediaItems.value.length) {
|
||||
post.selectedMedia = [...selectedMediaItems.value];
|
||||
errors.selectedMedia = '';
|
||||
}
|
||||
selectedMediaItems.value = [];
|
||||
mediaDialogVisible.value = false;
|
||||
};
|
||||
|
||||
@@ -138,11 +119,6 @@ const removeMedia = (media) => {
|
||||
}
|
||||
};
|
||||
|
||||
// Remove head image
|
||||
const removeHeadImage = () => {
|
||||
post.head_image = null;
|
||||
};
|
||||
|
||||
// Save the post
|
||||
const savePost = async () => {
|
||||
// Reset errors
|
||||
@@ -173,19 +149,13 @@ const savePost = async () => {
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!post.head_image) {
|
||||
errors.head_image = '请选择封面图片';
|
||||
valid = false;
|
||||
}
|
||||
|
||||
if (!valid) {
|
||||
toast.add({ severity: 'error', summary: '表单错误', detail: '请检查表单中的错误并修正', life: 3000 });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
post.medias = post.selectedMedia.map(media => media.id);
|
||||
post.head_image_id = post.head_image.id; // Add head image ID to submission
|
||||
post.medias = post.selectedMedia.map(media => media.id)
|
||||
const resp = await postService.createPost(post);
|
||||
console.log(resp)
|
||||
|
||||
@@ -259,34 +229,6 @@ const formatFileSize = (bytes) => {
|
||||
|
||||
<div>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Head Image -->
|
||||
<div class="col-span-2">
|
||||
<label class="block text-sm font-medium text-gray-700 mb-1">封面图片</label>
|
||||
<div class="p-4 border border-gray-200 rounded-md">
|
||||
<div v-if="!post.head_image" class="flex justify-center items-center flex-col space-y-3 py-6">
|
||||
<i class="pi pi-image text-gray-400 text-5xl!"></i>
|
||||
<p class="text-gray-500">请选择封面图片</p>
|
||||
<Button label="选择图片" icon="pi pi-plus" @click="openHeadImageDialog" outlined />
|
||||
<small v-if="errors.head_image" class="text-red-500">{{ errors.head_image }}</small>
|
||||
</div>
|
||||
<div v-else class="relative">
|
||||
<div class="flex items-center">
|
||||
<img :src="post.head_image.thumbnailUrl" class="w-32 h-32 object-cover rounded mr-4"
|
||||
:alt="post.head_image.name">
|
||||
<div class="flex flex-col">
|
||||
<span class="font-medium">{{ post.head_image.name }}</span>
|
||||
<div class="flex gap-2 mt-2">
|
||||
<Button label="更换图片" icon="pi pi-sync" @click="openHeadImageDialog" outlined
|
||||
size="small" />
|
||||
<Button label="移除" icon="pi pi-times" severity="danger" outlined size="small"
|
||||
@click="removeHeadImage" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<div class="col-span-2">
|
||||
<label for="title" class="block text-sm font-medium text-gray-700 mb-1">标题</label>
|
||||
@@ -374,15 +316,15 @@ const formatFileSize = (bytes) => {
|
||||
</div>
|
||||
|
||||
<!-- Media Selection Dialog -->
|
||||
<Dialog v-model:visible="mediaDialogVisible" :header="isHeadImageSelection ? '选择封面图片' : '选择媒体'" :modal="true"
|
||||
:dismissableMask="true" :closable="true" :style="{ width: '80vw' }" :breakpoints="{ '960px': '90vw' }">
|
||||
<Dialog v-model:visible="mediaDialogVisible" header="选择媒体" :modal="true" :dismissableMask="true" :closable="true"
|
||||
:style="{ width: '80vw' }" :breakpoints="{ '960px': '90vw' }">
|
||||
<div class="mb-4">
|
||||
<InputText v-model="mediaGlobalFilter" placeholder="搜索媒体..." class="w-full" />
|
||||
</div>
|
||||
|
||||
<DataTable v-model:selection="selectedMediaItems" :value="mediaItems" :loading="mediaLoading" dataKey="id"
|
||||
:paginator="true" v-model:first="mediaFirst" v-model:rows="mediaRows" :totalRecords="mediaTotalRecords"
|
||||
@page="onMediaPage" :selectionMode="isHeadImageSelection ? 'single' : 'multiple'"
|
||||
@page="onMediaPage" selectionMode="multiple"
|
||||
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport"
|
||||
:rows-per-page-options="[10, 25, 50]" currentPageReportTemplate="第 {first} 到 {last} 条,共 {totalRecords} 条"
|
||||
:lazy="true" :showCurrentPageReport="true">
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import axios from 'axios';
|
||||
|
||||
// Create axios instance with default config
|
||||
@@ -13,10 +12,6 @@ const client = axios.create({
|
||||
// Request interceptor
|
||||
client.interceptors.request.use(
|
||||
config => {
|
||||
const authStore = useAuthStore();
|
||||
if (authStore.isAuthenticated && authStore.token) {
|
||||
config.headers.Authorization = `Bearer ${authStore.token}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
error => {
|
||||
|
||||
Reference in New Issue
Block a user