213 lines
5.6 KiB
Vue
213 lines
5.6 KiB
Vue
<script setup lang="ts">
|
||
import { CloseOutline } from '@vicons/ionicons5'
|
||
import { Image } from 'lucide-vue-next'
|
||
import { useMessage } from 'naive-ui'
|
||
import { 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({
|
||
type: 0, // 提问类型:0免费,1付费
|
||
amount: 10, // 付费金额
|
||
content: '', // 提问内容
|
||
isAnonymous: 0, // 是否匿名 1匿名 0不匿名
|
||
questionUrl: '', // 提问图片
|
||
})
|
||
|
||
// 图片上传相关
|
||
const fileList = ref<string[]>([])
|
||
const questionUrlList = ref<string[]>([])
|
||
const loading = ref(false)
|
||
|
||
// 表单验证规则
|
||
const rules = {
|
||
content: {
|
||
required: true,
|
||
message: '请输入提问内容',
|
||
// trigger: ['blur'],
|
||
},
|
||
amount: {
|
||
required: (formData: any) => formData.type === 1,
|
||
message: '请输入付费金额',
|
||
// trigger: ['blur', 'change'],
|
||
type: 'number',
|
||
},
|
||
}
|
||
|
||
// 表单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,
|
||
questionUserId: userStore.userInfo.userId,
|
||
questionUrl: questionUrlList.value.join(','), // 将图片URL数组转为逗号分隔的字符串
|
||
}
|
||
|
||
const res = await request.post('/question/addQuestion', params)
|
||
if (res.code === 200) {
|
||
message.success('提问成功')
|
||
// 重置表单
|
||
formData.value = {
|
||
type: 0,
|
||
amount: undefined,
|
||
content: '',
|
||
isAnonymous: 0,
|
||
questionUrl: '',
|
||
}
|
||
fileList.value = []
|
||
questionUrlList.value = [] // 清空图片URL列表
|
||
emit('success') // 触发成功事件
|
||
}
|
||
}
|
||
catch (error) {
|
||
console.error(error)
|
||
}
|
||
finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
const pictureInput = ref<HTMLInputElement | null>(null)
|
||
function handlePictureInput() {
|
||
pictureInput.value?.click()
|
||
}
|
||
// 处理图片上传
|
||
async function handlePictureChange(event: Event) {
|
||
const files = (event.target as HTMLInputElement).files
|
||
if (!files || files.length === 0)
|
||
return
|
||
|
||
const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'))
|
||
if (imageFiles.length === 0) {
|
||
message.error('请选择有效的图片文件')
|
||
return
|
||
}
|
||
|
||
try {
|
||
const pictureResultList = await uploadImagesInBatches(imageFiles)
|
||
questionUrlList.value.push(...pictureResultList.map((item: any) => item.url))
|
||
pictureInput.value!.value = ''
|
||
}
|
||
catch (error: any) {
|
||
message.error('图片上传失败')
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<div class="bg-white rounded-lg px-6">
|
||
<n-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="rules"
|
||
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="questionUrlList.length > 0" class="mt-4 flex flex-wrap gap-3 mb-2">
|
||
<div
|
||
v-for="(url, index) in questionUrlList"
|
||
:key="index"
|
||
class="relative group"
|
||
>
|
||
<img
|
||
:src="url"
|
||
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-input-number
|
||
v-if="formData.type === 1"
|
||
v-model:value="formData.amount"
|
||
:min="10"
|
||
:max="999.9"
|
||
:precision="1"
|
||
placeholder="请输入付费金额"
|
||
class="w-[240px] my-5"
|
||
>
|
||
<template #prefix>
|
||
¥
|
||
</template>
|
||
</n-input-number>
|
||
<!-- </n-form-item> -->
|
||
<div class="flex items-center justify-between my-4">
|
||
<div class="border border-gray-300 rounded p-1 cursor-pointer hover:bg-gray-50 transition-colors" @click="handlePictureInput">
|
||
<Image class="w-6 h-6 size-6" />
|
||
</div>
|
||
<div class="flex items-center gap-8">
|
||
<n-radio-group v-model:value="formData.type">
|
||
<n-radio :value="0">
|
||
免费
|
||
</n-radio>
|
||
<n-radio :value="1">
|
||
付费
|
||
</n-radio>
|
||
</n-radio-group>
|
||
|
||
<n-checkbox v-model:checked="formData.isAnonymous" unchecked-value="0" checked-value="1">
|
||
匿名提问
|
||
</n-checkbox>
|
||
|
||
<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="image/*"
|
||
class="hidden"
|
||
@change="handlePictureChange"
|
||
>
|
||
</div>
|
||
</template>
|