218 lines
6.3 KiB
Vue
218 lines
6.3 KiB
Vue
<script setup lang="ts">
|
||
import { CloseOutline } from '@vicons/ionicons5'
|
||
import { FolderPlus, Image, ImagePlus } from 'lucide-vue-next'
|
||
import { useMessage } from 'naive-ui'
|
||
import { computed, ref } from 'vue'
|
||
import { uploadImagesInBatches } from '../utils/uploadImg.ts'
|
||
|
||
const props = defineProps<Props>()
|
||
|
||
const emit = defineEmits(['success'])
|
||
|
||
const userStore = useUserStore()
|
||
|
||
interface Props {
|
||
communityId: number | string
|
||
tenantId: number | string
|
||
}
|
||
|
||
const message = useMessage()
|
||
|
||
// 表单数据
|
||
const formData = ref({
|
||
content: '',
|
||
fileUrl: '',
|
||
fileName: '',
|
||
imageUrl: '',
|
||
})
|
||
|
||
// 图片上传相关
|
||
const fileUrl = ref<string[]>([])
|
||
const fileName = ref<string[]>([])
|
||
const imageUrl = ref<string[]>([])
|
||
const loading = ref(false)
|
||
|
||
// 表单ref
|
||
const formRef = ref()
|
||
|
||
// 处理发布提问
|
||
async function handlePublish() {
|
||
try {
|
||
await formRef.value?.validate()
|
||
loading.value = true
|
||
|
||
const params = {
|
||
...formData.value,
|
||
communityId: props.communityId,
|
||
tenantId: props.tenantId,
|
||
fileUrl: fileUrl.value.join(','),
|
||
fileName: fileName.value.join(','),
|
||
imageUrl: imageUrl.value.join(','),
|
||
}
|
||
|
||
const res = await request.post('/publish/publish', params)
|
||
if (res.code === 200) {
|
||
message.success('发布成功')
|
||
// 重置表单
|
||
formData.value = {
|
||
content: '',
|
||
fileUrl: '',
|
||
fileName: '',
|
||
imageUrl: '',
|
||
}
|
||
fileUrl.value = []
|
||
fileName.value = []
|
||
imageUrl.value = [] // 清空图片URL列表
|
||
emit('success') // 触发成功事件
|
||
}
|
||
}
|
||
catch (error) {
|
||
console.error(error)
|
||
}
|
||
finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
// 当前上传类型
|
||
const currentUploadType = ref<string | null>(null)
|
||
|
||
const acceptTypes = computed(() => {
|
||
return currentUploadType.value === 'img'
|
||
? 'image/*'
|
||
: 'application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-powerpoint,application/vnd.openxmlformats-officedocument.presentationml.presentation,text/plain,application/zip'
|
||
})
|
||
|
||
// 图片上传input
|
||
const pictureInput = ref<HTMLInputElement | null>(null)
|
||
function handlePictureInput(type: string) {
|
||
currentUploadType.value = type
|
||
nextTick(() => {
|
||
pictureInput.value?.click()
|
||
})
|
||
}
|
||
// 处理图片上传
|
||
async function handlePictureChange(event: Event) {
|
||
const files = (event.target as HTMLInputElement).files
|
||
if (!files || files.length === 0)
|
||
return message.error('请选择有效的文件')
|
||
|
||
try {
|
||
const fileList = Array.from(files)
|
||
const isImageUpload = currentUploadType.value === 'img'
|
||
|
||
// 根据上传类型验证文件
|
||
const validFiles = fileList.filter(file =>
|
||
isImageUpload ? file.type.startsWith('image/') : !file.type.startsWith('image/'),
|
||
)
|
||
|
||
if (validFiles.length === 0)
|
||
return message.error(`请选择${isImageUpload ? '图片' : '文档'}文件`)
|
||
|
||
const uploadResults = await uploadImagesInBatches(validFiles)
|
||
|
||
// 处理上传结果
|
||
if (isImageUpload) {
|
||
imageUrl.value.push(...uploadResults.map((item: any) => item.url))
|
||
}
|
||
else {
|
||
fileUrl.value.push(...uploadResults.map((item: any) => item.url))
|
||
fileName.value.push(...uploadResults.map((item: any) => item.fileName))
|
||
}
|
||
|
||
pictureInput.value!.value = '' // 清空input值,允许重复选择相同文件
|
||
}
|
||
catch (error) {
|
||
message.error(currentUploadType.value === 'img' ? '图片上传失败' : '文件上传失败')
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="bg-white rounded-lg px-6">
|
||
<n-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
label-placement="left"
|
||
label-width="auto"
|
||
require-mark-placement="right-hanging"
|
||
>
|
||
<n-form-item path="content" :show-label="false">
|
||
<n-input
|
||
v-model:value="formData.content"
|
||
type="textarea"
|
||
placeholder="点击发表主题"
|
||
:autosize="{ minRows: 5, maxRows: 10 }"
|
||
class="rounded-lg"
|
||
/>
|
||
</n-form-item>
|
||
|
||
<div v-if="fileName.length > 0" class="mt-4 flex flex-wrap gap-3 mb-2">
|
||
<div
|
||
v-for="(item, index) in fileName"
|
||
:key="index"
|
||
class="flex items-center gap-2"
|
||
>
|
||
{{ item }}
|
||
<n-icon color="#3f7ef7" class="cursor-pointer flex items-center justify-center w-6 h-6">
|
||
<CloseOutline class="text-[20px]" size="20" @click="fileName.splice(index, 1)" />
|
||
</n-icon>
|
||
</div>
|
||
</div>
|
||
<!-- 上传的图片预览 -->
|
||
<div v-if="imageUrl.length > 0" class="mt-4 flex flex-wrap gap-3 mb-2">
|
||
<div
|
||
v-for="(item, index) in imageUrl"
|
||
:key="index"
|
||
class="relative group"
|
||
>
|
||
<img
|
||
:src="item"
|
||
class="w-[125px] h-[125px] rounded"
|
||
>
|
||
<n-icon color="#fff" class="absolute top-1 right-1 p-1 z-40 cursor-pointer w-6 h-6">
|
||
<CloseOutline class="text-[20px]" size="20" @click="questionUrlList.splice(index, 1)" />
|
||
</n-icon>
|
||
</div>
|
||
</div>
|
||
<!-- <n-form-item v-if="formData.type === 1" path="amount" class="mb-3"> -->
|
||
|
||
<!-- </n-form-item> -->
|
||
<div class="flex items-center justify-between my-2">
|
||
<div class="flex">
|
||
<div class="border border-gray-300 rounded p-1 cursor-pointer hover:bg-gray-50 transition-colors mr-6" @click="handlePictureInput('img')">
|
||
<ImagePlus class="w-5 h-5" />
|
||
</div>
|
||
<div class="border border-gray-300 rounded p-1 cursor-pointer hover:bg-gray-50 transition-colors" @click="handlePictureInput('file')">
|
||
<FolderPlus class="w-5 h-5" />
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-8">
|
||
<n-button
|
||
type="primary"
|
||
:loading="loading"
|
||
class="!px-8 rounded"
|
||
:theme-overrides="{
|
||
common: {
|
||
primaryColor: '#3f7ef7',
|
||
primaryColorHover: '#3f7ef7',
|
||
},
|
||
}"
|
||
@click="handlePublish"
|
||
>
|
||
发布
|
||
</n-button>
|
||
</div>
|
||
</div>
|
||
</n-form>
|
||
<input
|
||
ref="pictureInput"
|
||
type="file"
|
||
:accept="acceptTypes"
|
||
class="hidden"
|
||
multiple="true"
|
||
@change="handlePictureChange"
|
||
>
|
||
</div>
|
||
</template>
|