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.

425 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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 :label="3">投融资</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 v-if="form.type !== 3" label="详细描述">
<el-input v-model="form.content" type="textarea" :rows="4" maxlength="200" show-word-limit />
</el-form-item>
<el-form-item v-if="form.type !== 3" 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>
<!-- 投融资专属字段:当 type === 3 时显示 -->
<template v-if="form.type === 3">
<el-form-item label="资金类型">
<el-select v-model="form.fund_type" placeholder="请选择资金类型" style="width: 240px;">
<el-option label="投资" value="投资" />
<el-option label="融资" value="融资" />
</el-select>
</el-form-item>
<el-form-item label="金额">
<el-input-number v-model="form.amount" :precision="2" :step="0.01" :min="0" style="width: 240px;" />
</el-form-item>
<el-form-item label="融资阶段">
<el-input v-model="form.fund_stage" maxlength="50" />
</el-form-item>
<el-form-item label="期望资金属性">
<el-input v-model="form.expect_fund_attr" maxlength="50" />
</el-form-item>
<el-form-item label="行业类型">
<el-input v-model="form.industry_type" maxlength="50" />
</el-form-item>
<el-form-item label="主要产品">
<el-input v-model="form.product" maxlength="50" />
</el-form-item>
<el-form-item label="简要描述">
<el-input v-model="form.desc" type="textarea" :rows="4" maxlength="200" show-word-limit />
</el-form-item>
</template>
<!-- 图片上传 -->
<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张图片支持jpg、png格式单张不超过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: '',
// 投融资专属字段
fund_type: '',
amount: 0,
fund_stage: '',
expect_fund_attr: '',
industry_type: '',
product: '',
desc: '',
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: '',
fund_type: '',
amount: 0,
fund_stage: '',
expect_fund_attr: '',
industry_type: '',
product: '',
desc: '',
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 || '',
fund_type: val.fund_type || '',
amount: typeof val.amount === 'number' ? val.amount : (parseFloat(val.amount) || 0),
fund_stage: val.fund_stage || '',
expect_fund_attr: val.expect_fund_attr || '',
industry_type: val.industry_type || '',
product: val.product || '',
desc: val.desc || '',
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.type === 3 ? '' : 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)
}
// 投融资类型下提交专属字段,其它类型清空
if (this.form.type === 3) {
data.fund_type = this.form.fund_type
data.amount = this.form.amount
data.fund_stage = this.form.fund_stage
data.expect_fund_attr = this.form.expect_fund_attr
data.industry_type = this.form.industry_type
data.product = this.form.product
data.desc = this.form.desc
// 投融资不提交行业标签与原描述
data.tag = ''
} else {
data.fund_type = ''
data.amount = 0
data.fund_stage = ''
data.expect_fund_attr = ''
data.industry_type = ''
data.product = ''
data.desc = ''
}
// 如果存在新上传的文件,确保它们都包含在 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>