You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
11 KiB

<template>
<el-dialog :visible.sync="dialogVisible" width="70%" title="编辑供需">
<el-form :model="form" label-width="80px">
<el-form-item label="供需类型">
<el-radio-group v-model="form.type">
<el-radio :label="1">供应</el-radio>
<el-radio :label="2">需求</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="标题">
<el-input v-model="form.title" maxlength="50" show-word-limit />
</el-form-item>
<el-form-item label="详细描述">
<el-input v-model="form.content" type="textarea" :rows="4" maxlength="200" show-word-limit />
</el-form-item>
<el-form-item label="行业标签">
<el-input
v-model="tagInput"
placeholder="输入后回车键确认"
style="margin-bottom: 8px;"
@keyup.enter.native="addTag"
@blur="addTag"
/>
<div>
<el-tag
v-for="(tag, idx) in tagList"
:key="tag + idx"
closable
style="margin-right: 8px;"
@close="removeTag(idx)"
>{{ tag }}</el-tag>
</div>
<div style="color: #999; font-size: 12px; margin-top: 4px;">
建议添加相关行业标签方便其他校友找到你
</div>
</el-form-item>
<!-- 图片上传 -->
<el-form-item label="相关图片">
<el-upload
list-type="picture-card"
:file-list="imageList"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:before-upload="beforeImageUpload"
:on-success="handleUploadSuccess"
:http-request="handleCustomUpload"
multiple
>
<i class="el-icon-plus" />
</el-upload>
<el-dialog :visible.sync="previewVisible">
<img width="100%" :src="previewImage" alt="">
</el-dialog>
<div style="color: #999; font-size: 12px; margin-top: 4px;">
最多上传9张图片支持jpgpng格式单张不超过2MB
</div>
</el-form-item>
<!-- 时效性选择 -->
<el-form-item label="时效性">
<el-radio-group v-model="form.validityType">
<el-radio label="longterm">长期有效</el-radio>
<el-radio label="specific">具体日期</el-radio>
</el-radio-group>
<div v-if="form.validityType === 'specific'" style="margin-top: 12px;">
<el-date-picker
v-model="form.expireTime"
type="date"
placeholder="选择到期日期"
format="yyyy-MM-dd"
value-format="yyyy-MM-dd"
:picker-options="pickerOptions"
/>
</div>
<div style="color: #999; font-size: 12px; margin-top: 4px;">
<span v-if="form.validityType === 'longterm'"></span>
<span v-else></span>
</div>
</el-form-item>
<!-- 联系人 -->
<el-form-item label="联系人" required>
<el-input
v-model="form.contactName"
placeholder="请输入联系人姓名"
maxlength="20"
show-word-limit
/>
<div style="color: #999; font-size: 12px; margin-top: 4px;">
默认为您的姓名可修改
</div>
</el-form-item>
<el-form-item label="联系方式" required>
<div class="contact-type-group">
<el-button
:type="form.contactType === 'wechat' ? 'primary' : 'default'"
icon="el-icon-chat-dot-round"
@click="form.contactType = 'wechat'"
>微信</el-button>
<el-button
:type="form.contactType === 'mobile' ? 'primary' : 'default'"
icon="el-icon-phone"
@click="form.contactType = 'mobile'"
>电话</el-button>
<el-button
:type="form.contactType === 'email' ? 'primary' : 'default'"
icon="el-icon-message"
@click="form.contactType = 'email'"
>邮箱</el-button>
</div>
<div style="margin-top: 12px;">
<el-input
v-if="form.contactType === 'wechat'"
v-model="form.wechat"
placeholder="请输入微信号"
/>
<el-input
v-if="form.contactType === 'mobile'"
v-model="form.mobile"
placeholder="请输入手机号"
/>
<el-input
v-if="form.contactType === 'email'"
v-model="form.email"
placeholder="请输入邮箱"
/>
</div>
<!-- 联系方式公开模式 -->
<div style="margin-top: 16px;">
<div style="margin-bottom: 8px; color: #606266; font-size: 14px;">公开模式</div>
<el-radio-group v-model="form.publicWay">
<el-radio :label="1">直接公开</el-radio>
<el-radio :label="2">私信后自动公开</el-radio>
<el-radio :label="3">不公开</el-radio>
</el-radio-group>
<div style="color: #999; font-size: 12px; margin-top: 4px;">
<span v-if="form.publicWay === 1"></span>
<span v-else-if="form.publicWay === 2">用户私信后联系方式自动公开</span>
<span v-else></span>
</div>
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="handleCancel"></el-button>
<el-button type="primary" @click="handleSave"></el-button>
</span>
</el-dialog>
</template>
<script>
import { uploads } from '@/api/uploads'
export default {
props: {
visible: Boolean,
detail: {
type: Object,
default: () => null
}
},
data() {
return {
dialogVisible: false,
form: {
type: 1,
title: '',
content: '',
contactType: 'mobile',
mobile: '',
wechat: '',
email: '',
publicWay: 1,
validityType: 'longterm',
expireTime: '',
contactName: ''
},
tagInput: '',
tagList: [],
imageList: [],
newUploadedFileIds: [],
previewVisible: false,
previewImage: '',
pickerOptions: {
disabledDate(time) {
return time.getTime() < Date.now() - 8.64e7
}
}
}
},
watch: {
visible: {
immediate: true,
handler(val) {
this.dialogVisible = val
}
},
dialogVisible(val) {
this.$emit('update:visible', val)
},
detail: {
immediate: true,
handler(val) {
if (!val) {
// 如果 detail 为 null重置表单为默认值
this.form = {
type: 1,
title: '',
content: '',
contactType: 'mobile',
mobile: '',
wechat: '',
email: '',
publicWay: 1,
validityType: 'longterm',
expireTime: '',
contactName: ''
}
this.tagList = []
this.imageList = []
return
}
this.form = {
id: val.id,
type: val.type || 1,
title: val.title || '',
content: val.content || '',
contactType: val.wechat ? 'wechat' : (val.email ? 'email' : 'mobile'),
mobile: val.mobile || '',
wechat: val.wechat || '',
email: val.email || '',
publicWay: val.public_way || 1,
validityType: val.expire_time ? 'specific' : 'longterm',
expireTime: val.expire_time || '',
contactName: val.contact_name || ''
}
this.tagList = Array.isArray(val.tag)
? val.tag
: (val.tag ? val.tag.split(',').filter(Boolean) : [])
this.imageList = Array.isArray(val.files)
? val.files.map(f => ({ id: f.id, url: f.url, name: f.original_name || '' }))
: (Array.isArray(val.file_ids) ? val.file_ids.map(id => ({ id, url: (val.images && val.images[id]) || '' })) : [])
}
}
},
methods: {
addTag() {
const val = this.tagInput && this.tagInput.trim()
if (val && !this.tagList.includes(val)) {
this.tagList.push(val)
}
this.tagInput = ''
},
removeTag(idx) {
this.tagList.splice(idx, 1)
},
// 图片上传相关方法
handlePictureCardPreview(file) {
this.previewImage = file.url
this.previewVisible = true
},
handleRemove(file, fileList) {
this.imageList = fileList
// 同步移除已记录的新上传ID
const removedId = file.response?.id || file.id
if (removedId) {
this.newUploadedFileIds = this.newUploadedFileIds.filter(id => id !== removedId)
}
},
handleUploadSuccess(response, file, fileList) {
this.imageList = fileList
},
async handleCustomUpload({ file, onSuccess, onError }) {
try {
const formData = new FormData()
formData.append('file', file)
const res = await uploads(formData)
// 兼容返回结构
const uploadedId = res.id || res.data?.id
const uploadedUrl = res.url || res.data?.url
const responsePayload = { id: uploadedId, url: uploadedUrl }
// 记录ID
if (uploadedId) this.newUploadedFileIds.push(uploadedId)
// 通知 el-upload 成功
onSuccess(responsePayload, file)
} catch (e) {
onError(e)
}
},
beforeImageUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isPNG = file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 2
const isLt9 = this.imageList.length < 9
if (!isJPG && !isPNG) {
this.$message.error('上传图片只能是 JPG/PNG 格式!')
return false
}
if (!isLt2M) {
this.$message.error('上传图片大小不能超过 2MB!')
return false
}
if (!isLt9) {
this.$message.error('最多只能上传9张图片!')
return false
}
return true
},
handleCancel() {
this.dialogVisible = false
this.newUploadedFileIds = []
},
handleSave() {
const data = {
id: this.form.id,
title: this.form.title,
content: this.form.content,
tag: this.tagList.join(','),
wechat: this.form.wechat,
mobile: this.form.mobile,
email: this.form.email,
type: this.form.type,
public_way: this.form.publicWay,
validity_type: this.form.validityType,
expire_time: this.form.validityType === 'specific' ? this.form.expireTime : null,
contact_name: this.form.contactName,
file_ids: this.imageList.map(item => item.response?.id || item.id).filter(Boolean)
}
// 如果存在新上传的文件,确保它们都包含在 file_ids 中
if (this.newUploadedFileIds && this.newUploadedFileIds.length) {
const fileIdSet = new Set(data.file_ids)
this.newUploadedFileIds.forEach(id => fileIdSet.add(id))
data.file_ids = Array.from(fileIdSet)
}
if (this.form.contactType !== 'wechat') data.wechat = ''
if (this.form.contactType !== 'mobile') data.mobile = ''
if (this.form.contactType !== 'email') data.email = ''
this.$emit('save', data)
this.dialogVisible = false
}
}
}
</script>
<style scoped>
.contact-type-group {
display: flex;
gap: 12px;
margin-bottom: 8px;
}
</style>