|
|
|
@ -4,11 +4,11 @@ |
|
|
|
<view class="back" @tap="back"> |
|
|
|
<uni-icons type="left" size="22" color="#18372f"></uni-icons> |
|
|
|
</view> |
|
|
|
<view class="header-title">发布校园二手</view> |
|
|
|
<view class="header-title">{{isEdit ? '编辑校园二手' : '发布校园二手'}}</view> |
|
|
|
<view class="header-sub">实名发布,线下面交,请勿提前转账</view> |
|
|
|
<view class="tabs"> |
|
|
|
<view class="tab" :class="{ active: publishType == 'sell' }" @tap="switchType('sell')">出售</view> |
|
|
|
<view class="tab" :class="{ active: publishType == 'want' }" @tap="switchType('want')">求购</view> |
|
|
|
<view class="tab" :class="{ active: publishType == 'sell', disabled: isEdit }" @tap="switchType('sell')">出售</view> |
|
|
|
<view class="tab" :class="{ active: publishType == 'want', disabled: isEdit }" @tap="switchType('want')">求购</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
@ -57,7 +57,7 @@ |
|
|
|
<sp-editor |
|
|
|
editor-id="fishReleaseEditor" |
|
|
|
:toolbar-config="editorToolbarConfig" |
|
|
|
:maxlength="2000" |
|
|
|
:maxlength="1000" |
|
|
|
:placeholder="publishType == 'sell' ? '描述成色、尺寸、交易地点、可取时间等' : '描述想要的物品、预算、交易地点、可取时间等'" |
|
|
|
@init="initEditor" |
|
|
|
@input="inputEditor" |
|
|
|
@ -87,7 +87,7 @@ |
|
|
|
<view class="bottom-space"></view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<view class="submit-bar" v-if="!keyboardOpen"> |
|
|
|
<view class="submit-bar"> |
|
|
|
<view class="submit-btn" :class="{ disabled: submitting }" @tap="submit">{{submitting ? '提交中...' : '提交发布'}}</view> |
|
|
|
</view> |
|
|
|
<view class="audit-mask" v-if="submitting"> |
|
|
|
@ -112,9 +112,11 @@ |
|
|
|
import SpEditor from '@/package1/components/sp-editor/components/sp-editor/sp-editor.vue' |
|
|
|
import { |
|
|
|
listFishCategories, |
|
|
|
getFishGoodsDetail, |
|
|
|
getFishWantDetail, |
|
|
|
publishFishGoods, |
|
|
|
publishFishWant, |
|
|
|
uploadFishImage |
|
|
|
uploadFishReleaseImage |
|
|
|
} from '@/common/fishMarketApi.js' |
|
|
|
|
|
|
|
export default { |
|
|
|
@ -126,6 +128,10 @@ |
|
|
|
return { |
|
|
|
statusBarTop: 24, |
|
|
|
publishType: 'sell', |
|
|
|
editId: '', |
|
|
|
isEdit: false, |
|
|
|
pendingEditDetail: null, |
|
|
|
pendingEditorHtml: '', |
|
|
|
categories: [], |
|
|
|
selectedCategoryIndex: -1, |
|
|
|
submitting: false, |
|
|
|
@ -171,10 +177,17 @@ |
|
|
|
if (options && (options.type == 'want' || options.type == 'sell')) { |
|
|
|
this.publishType = options.type |
|
|
|
} |
|
|
|
if (options && options.mode == 'edit' && options.id) { |
|
|
|
this.isEdit = true |
|
|
|
this.editId = options.id |
|
|
|
} |
|
|
|
if (uni.getMenuButtonBoundingClientRect) { |
|
|
|
this.statusBarTop = uni.getMenuButtonBoundingClientRect().top || this.statusBarTop |
|
|
|
} |
|
|
|
this.loadCategories() |
|
|
|
if (this.isEdit) { |
|
|
|
this.loadEditDetail() |
|
|
|
} |
|
|
|
this.ensurePublishVerified() |
|
|
|
this.bindKeyboardListener() |
|
|
|
}, |
|
|
|
@ -194,6 +207,7 @@ |
|
|
|
uni.navigateBack({ fail: () => uni.switchTab({ url: '/pages/index/index' }) }) |
|
|
|
}, |
|
|
|
switchType(type) { |
|
|
|
if (this.isEdit) return |
|
|
|
this.publishType = type |
|
|
|
if (type == 'want' && this.form.images.length > 1) { |
|
|
|
this.form.images = this.form.images.slice(0, 1) |
|
|
|
@ -215,8 +229,78 @@ |
|
|
|
const area = this.getArea() |
|
|
|
listFishCategories(area.id || '').then(list => { |
|
|
|
this.categories = Array.isArray(list) ? list : [] |
|
|
|
this.applyEditCategory() |
|
|
|
}) |
|
|
|
}, |
|
|
|
loadEditDetail() { |
|
|
|
const request = this.publishType == 'want' ? getFishWantDetail(this.editId) : getFishGoodsDetail(this.editId) |
|
|
|
request.then(detail => { |
|
|
|
if (!detail) return |
|
|
|
this.pendingEditDetail = detail |
|
|
|
this.applyEditDetail(detail) |
|
|
|
}) |
|
|
|
}, |
|
|
|
applyEditDetail(detail) { |
|
|
|
const contact = this.parseJsonObject(detail.contactInfo) |
|
|
|
const imageList = detail.imageList && detail.imageList.length ? detail.imageList : this.parseJsonList(detail.images) |
|
|
|
const tagList = this.publishType == 'sell' ? this.parseJsonList(detail.tags) : [] |
|
|
|
const content = detail.content || '' |
|
|
|
this.form.title = detail.title || '' |
|
|
|
this.form.price = String(this.publishType == 'want' ? (detail.expectedPrice || '') : (detail.price || '')) |
|
|
|
this.form.originPrice = this.publishType == 'sell' && detail.originPrice ? String(detail.originPrice) : '' |
|
|
|
this.form.content = content |
|
|
|
this.form.contentText = this.extractText(content) |
|
|
|
this.form.images = imageList.slice(0, this.maxImageCount) |
|
|
|
this.form.wechat = contact.wechat || '' |
|
|
|
this.form.phone = contact.phone || '' |
|
|
|
this.form.tags = tagList.length ? tagList : (this.publishType == 'sell' ? ['可小刀'] : []) |
|
|
|
this.pendingEditorHtml = content |
|
|
|
this.applyEditCategory() |
|
|
|
this.applyPendingEditorContent() |
|
|
|
}, |
|
|
|
applyEditCategory() { |
|
|
|
const detail = this.pendingEditDetail |
|
|
|
if (!detail || !this.categories.length) return |
|
|
|
const index = this.categories.findIndex(item => String(item.id) == String(detail.categoryId) || item.name == detail.categoryName) |
|
|
|
this.selectedCategoryIndex = index > -1 ? index : this.selectedCategoryIndex |
|
|
|
}, |
|
|
|
applyPendingEditorContent() { |
|
|
|
if (!this.editorIns || !this.pendingEditorHtml) return |
|
|
|
if (this.editorIns.setContents) { |
|
|
|
this.editorIns.setContents({ |
|
|
|
html: this.pendingEditorHtml |
|
|
|
}) |
|
|
|
} |
|
|
|
}, |
|
|
|
parseJsonList(value) { |
|
|
|
if (!value) return [] |
|
|
|
if (Array.isArray(value)) return value |
|
|
|
try { |
|
|
|
const parsed = JSON.parse(value) |
|
|
|
return Array.isArray(parsed) ? parsed : [] |
|
|
|
} catch (e) { |
|
|
|
return [] |
|
|
|
} |
|
|
|
}, |
|
|
|
parseJsonObject(value) { |
|
|
|
if (!value) return {} |
|
|
|
if (typeof value === 'object') return value |
|
|
|
try { |
|
|
|
return JSON.parse(value) || {} |
|
|
|
} catch (e) { |
|
|
|
return {} |
|
|
|
} |
|
|
|
}, |
|
|
|
extractText(html) { |
|
|
|
return String(html || '') |
|
|
|
.replace(/<img[^>]*>/gi, '') |
|
|
|
.replace(/<[^>]+>/g, '') |
|
|
|
.replace(/ /g, ' ') |
|
|
|
.replace(/</g, '<') |
|
|
|
.replace(/>/g, '>') |
|
|
|
.replace(/&/g, '&') |
|
|
|
.trim() |
|
|
|
}, |
|
|
|
async ensurePublishVerified() { |
|
|
|
const profile = await getIeProfile().catch(() => null) |
|
|
|
const verified = await ensureIeVerifiedBeforeAction({ |
|
|
|
@ -242,14 +326,20 @@ |
|
|
|
success: async (res) => { |
|
|
|
const paths = res.tempFilePaths || [] |
|
|
|
uni.showLoading({ title: '上传中...', mask: true }) |
|
|
|
const failMessages = [] |
|
|
|
try { |
|
|
|
for (let i = 0; i < paths.length; i++) { |
|
|
|
const url = await uploadFishImage(paths[i]) |
|
|
|
if (url) this.form.images.push(url) |
|
|
|
const result = await uploadFishReleaseImage(paths[i]) |
|
|
|
if (result && result.passed && result.url) { |
|
|
|
this.form.images.push(result.url) |
|
|
|
} else { |
|
|
|
failMessages.push((result && result.message) || '图片审核未通过,请更换图片') |
|
|
|
} |
|
|
|
} |
|
|
|
} finally { |
|
|
|
uni.hideLoading() |
|
|
|
} |
|
|
|
this.showUploadAuditFail(failMessages) |
|
|
|
} |
|
|
|
}) |
|
|
|
}, |
|
|
|
@ -258,32 +348,47 @@ |
|
|
|
}, |
|
|
|
initEditor(editor) { |
|
|
|
this.editorIns = editor |
|
|
|
this.applyPendingEditorContent() |
|
|
|
}, |
|
|
|
inputEditor(e) { |
|
|
|
this.form.content = e && e.html ? e.html : '' |
|
|
|
this.form.contentText = e && e.text ? e.text : '' |
|
|
|
}, |
|
|
|
overEditorMax() { |
|
|
|
uni.showToast({ title: '内容最多2000字', icon: 'none' }) |
|
|
|
uni.showToast({ title: '内容最多1000字', icon: 'none' }) |
|
|
|
}, |
|
|
|
async upinEditorImage(tempFiles, editorCtx) { |
|
|
|
const files = Array.isArray(tempFiles) ? tempFiles : [] |
|
|
|
if (!files.length || !editorCtx) return |
|
|
|
uni.showLoading({ title: '上传中...', mask: true }) |
|
|
|
const failMessages = [] |
|
|
|
try { |
|
|
|
for (let i = 0; i < files.length; i++) { |
|
|
|
const filePath = files[i].tempFilePath || files[i].path |
|
|
|
const url = filePath ? await uploadFishImage(filePath) : '' |
|
|
|
if (url) { |
|
|
|
const result = filePath ? await uploadFishReleaseImage(filePath) : null |
|
|
|
if (result && result.passed && result.url) { |
|
|
|
editorCtx.insertImage({ |
|
|
|
src: url, |
|
|
|
src: result.url, |
|
|
|
width: '90%' |
|
|
|
}) |
|
|
|
} else { |
|
|
|
failMessages.push((result && result.message) || '图片审核未通过,请更换图片') |
|
|
|
} |
|
|
|
} |
|
|
|
} finally { |
|
|
|
uni.hideLoading() |
|
|
|
} |
|
|
|
this.showUploadAuditFail(failMessages) |
|
|
|
}, |
|
|
|
showUploadAuditFail(messages) { |
|
|
|
if (!messages || !messages.length) return |
|
|
|
const uniq = Array.from(new Set(messages.filter(Boolean))) |
|
|
|
uni.showModal({ |
|
|
|
title: '图片审核未通过', |
|
|
|
content: uniq.join('\n'), |
|
|
|
showCancel: false, |
|
|
|
confirmText: '知道了' |
|
|
|
}) |
|
|
|
}, |
|
|
|
toggleTag(tag) { |
|
|
|
const index = this.form.tags.indexOf(tag) |
|
|
|
@ -327,7 +432,7 @@ |
|
|
|
if (this.publishType == 'want' && this.form.images.length > 1) return '求购最多上传1张图片' |
|
|
|
if (!contentText) return this.publishType == 'sell' ? '请填写商品介绍' : '请填写求购内容' |
|
|
|
if (contentText.length < 5) return this.publishType == 'sell' ? '商品介绍至少5个字' : '求购内容至少5个字' |
|
|
|
if (!wechat && !phone) return '请至少填写一种联系方式' |
|
|
|
if (contentText.length > 1000) return this.publishType == 'sell' ? '商品介绍最多1000字' : '求购内容最多1000字' |
|
|
|
if (wechat && !this.isValidWechat(wechat)) return '请输入正确的微信号' |
|
|
|
if (phone && !this.isValidPhone(phone)) return '请输入正确的手机号' |
|
|
|
return '' |
|
|
|
@ -366,11 +471,13 @@ |
|
|
|
const area = this.getArea() |
|
|
|
const category = this.categories[this.selectedCategoryIndex] |
|
|
|
const payload = { |
|
|
|
id: this.isEdit ? this.editId : undefined, |
|
|
|
publishType: this.publishType, |
|
|
|
regionId: area.id || '', |
|
|
|
regionName: area.title || '', |
|
|
|
title: this.form.title, |
|
|
|
content: this.form.content, |
|
|
|
contentText: this.form.contentText, |
|
|
|
price: this.publishType == 'sell' ? Number(this.form.price) : undefined, |
|
|
|
originPrice: this.form.originPrice ? Number(this.form.originPrice) : undefined, |
|
|
|
expectedPrice: this.publishType == 'want' ? Number(this.form.price) : undefined, |
|
|
|
@ -385,11 +492,11 @@ |
|
|
|
negotiable: this.form.tags.indexOf('可小刀') > -1 ? 1 : 0 |
|
|
|
} |
|
|
|
this.submitting = true |
|
|
|
this.auditTitle = '提交中,等待审核' |
|
|
|
this.auditTitle = this.isEdit ? '保存中,等待审核' : '提交中,等待审核' |
|
|
|
const res = this.publishType == 'sell' ? await publishFishGoods(payload) : await publishFishWant(payload) |
|
|
|
if (res) { |
|
|
|
submitSuccess = true |
|
|
|
this.auditTitle = '提交成功,等待审核' |
|
|
|
this.auditTitle = this.isEdit ? '保存成功,等待审核' : '提交成功,等待审核' |
|
|
|
setTimeout(() => uni.navigateBack(), 800) |
|
|
|
} |
|
|
|
} finally { |
|
|
|
@ -403,7 +510,7 @@ |
|
|
|
return { |
|
|
|
badge: '校园二手', |
|
|
|
title: '实名认证', |
|
|
|
content: '根据法律法规要求,对应流程需要实名认证。', |
|
|
|
content: '根据法律法规要求,对应流程需要调用阿里云实名认证。半径里不会存储您的实名信息。', |
|
|
|
steps: [] |
|
|
|
} |
|
|
|
} |
|
|
|
@ -486,6 +593,10 @@ |
|
|
|
box-shadow: 0 8rpx 18rpx rgba(36, 185, 121, 0.22); |
|
|
|
} |
|
|
|
|
|
|
|
.tab.disabled { |
|
|
|
opacity: .72; |
|
|
|
} |
|
|
|
|
|
|
|
.form-card { |
|
|
|
margin: 0 24rpx; |
|
|
|
padding: 4rpx 26rpx 26rpx; |
|
|
|
@ -755,6 +866,6 @@ |
|
|
|
} |
|
|
|
|
|
|
|
.bottom-space { |
|
|
|
height: 160rpx; |
|
|
|
height: 240rpx; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|