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.
871 lines
23 KiB
871 lines
23 KiB
<template>
|
|
<view class="release-page">
|
|
<view class="header" :style="{ paddingTop: statusBarTop + 'px' }">
|
|
<view class="back" @tap="back">
|
|
<uni-icons type="left" size="22" color="#18372f"></uni-icons>
|
|
</view>
|
|
<view class="header-title">{{isEdit ? '编辑校园二手' : '发布校园二手'}}</view>
|
|
<view class="header-sub">实名发布,线下面交,请勿提前转账</view>
|
|
<view class="tabs">
|
|
<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>
|
|
|
|
<view class="form-scroll" :style="{ paddingTop: headerHeight + 'px' }">
|
|
<view class="form-card">
|
|
<view class="field" id="fieldTitle">
|
|
<view class="label">标题</view>
|
|
<input v-model.trim="form.title" maxlength="10" placeholder="最多10个字" />
|
|
</view>
|
|
|
|
<view class="field price-row" id="fieldPrice">
|
|
<view class="price-field">
|
|
<view class="label">{{publishType == 'sell' ? '售价' : '预算'}}</view>
|
|
<input v-model="form.price" type="digit" placeholder="0.00" />
|
|
</view>
|
|
<view class="price-field" v-if="publishType == 'sell'">
|
|
<view class="label">原价</view>
|
|
<input v-model="form.originPrice" type="digit" placeholder="可不填" />
|
|
</view>
|
|
</view>
|
|
|
|
<view class="field">
|
|
<view class="label">分类</view>
|
|
<picker :range="categoryNames" @change="chooseCategory">
|
|
<view class="picker-value">{{selectedCategoryName || '请选择分类'}} <text>›</text></view>
|
|
</picker>
|
|
</view>
|
|
|
|
<view class="field">
|
|
<view class="label">图片 <text>{{publishType == 'sell' ? '最多9张' : '最多1张,可选'}}</text></view>
|
|
<view class="image-list">
|
|
<view class="image-item" v-for="(item,index) in form.images" :key="item">
|
|
<image :src="item" mode="aspectFill"></image>
|
|
<view class="remove" @tap="removeImage(index)">×</view>
|
|
</view>
|
|
<view class="image-add" v-if="form.images.length < maxImageCount" @tap="chooseImages">
|
|
<uni-icons type="plusempty" size="28" color="#8aa09a"></uni-icons>
|
|
<text>上传</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="field" id="fieldContent">
|
|
<view class="label">{{publishType == 'sell' ? '商品介绍' : '求购内容'}}</view>
|
|
<view class="editor-box">
|
|
<sp-editor
|
|
editor-id="fishReleaseEditor"
|
|
:toolbar-config="editorToolbarConfig"
|
|
:maxlength="1000"
|
|
:placeholder="publishType == 'sell' ? '描述成色、尺寸、交易地点、可取时间等' : '描述想要的物品、预算、交易地点、可取时间等'"
|
|
@init="initEditor"
|
|
@input="inputEditor"
|
|
@upinImage="upinEditorImage"
|
|
@overMax="overEditorMax"
|
|
></sp-editor>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="field" id="fieldContact">
|
|
<view class="label">联系方式</view>
|
|
<input v-model.trim="form.wechat" maxlength="20" placeholder="微信号,可选" cursor-spacing="180" />
|
|
<input v-model.trim="form.phone" class="contact-input" maxlength="11" type="number" placeholder="手机号,可选" cursor-spacing="180" />
|
|
</view>
|
|
|
|
<view class="field" v-if="publishType == 'sell'">
|
|
<view class="label">商品标签</view>
|
|
<view class="tag-list">
|
|
<view class="tag" :class="{ checked: form.tags.indexOf(item) > -1 }" v-for="item in tagOptions" :key="item" @tap="toggleTag(item)">
|
|
{{item}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="safe-tip">发布内容、图片、评论都会进行内容安全审核。可以留电话或微信,但请线下面交,谨防诈骗。</view>
|
|
<view class="bottom-space"></view>
|
|
</view>
|
|
|
|
<view class="submit-bar">
|
|
<view class="submit-btn" :class="{ disabled: submitting }" @tap="submit">{{submitting ? '提交中...' : '提交发布'}}</view>
|
|
</view>
|
|
<view class="audit-mask" v-if="submitting">
|
|
<view class="audit-card">
|
|
<view class="audit-spinner">
|
|
<view></view>
|
|
<view></view>
|
|
<view></view>
|
|
</view>
|
|
<view class="audit-title">{{auditTitle}}</view>
|
|
<view class="audit-desc">发布内容正在提交审核,请勿重复点击</view>
|
|
</view>
|
|
</view>
|
|
<ie-auth-dialog />
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { getIeProfile } from '@/common/ieApi.js'
|
|
import { ensureIeVerifiedBeforeAction } from '@/common/ieRealNameAuth.js'
|
|
import IeAuthDialog from '@/package1/components/ie-auth-dialog/ie-auth-dialog.vue'
|
|
import SpEditor from '@/package1/components/sp-editor/components/sp-editor/sp-editor.vue'
|
|
import {
|
|
listFishCategories,
|
|
getFishGoodsDetail,
|
|
getFishWantDetail,
|
|
publishFishGoods,
|
|
publishFishWant,
|
|
uploadFishReleaseImage
|
|
} from '@/common/fishMarketApi.js'
|
|
|
|
export default {
|
|
components: {
|
|
IeAuthDialog,
|
|
SpEditor
|
|
},
|
|
data() {
|
|
return {
|
|
statusBarTop: 24,
|
|
publishType: 'sell',
|
|
editId: '',
|
|
isEdit: false,
|
|
pendingEditDetail: null,
|
|
pendingEditorHtml: '',
|
|
categories: [],
|
|
selectedCategoryIndex: -1,
|
|
submitting: false,
|
|
submitLocked: false,
|
|
keyboardOpen: false,
|
|
auditTitle: '提交中,等待审核',
|
|
editorIns: null,
|
|
editorToolbarConfig: {
|
|
keys: ['bold', 'italic', 'underline', 'header', 'listOrdered', 'listBullet', 'align', 'image', 'removeFormat', 'clear'],
|
|
iconSize: '17px',
|
|
iconColumns: 10
|
|
},
|
|
tagOptions: ['可小刀', '当天可取', '宿舍自提', '可送宿舍', '急出', '九成新'],
|
|
form: {
|
|
title: '',
|
|
price: '',
|
|
originPrice: '',
|
|
content: '',
|
|
contentText: '',
|
|
images: [],
|
|
wechat: '',
|
|
phone: '',
|
|
tags: ['可小刀']
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
categoryNames() {
|
|
return this.categories.map(item => item.name)
|
|
},
|
|
selectedCategoryName() {
|
|
const item = this.categories[this.selectedCategoryIndex]
|
|
return item ? item.name : ''
|
|
},
|
|
maxImageCount() {
|
|
return this.publishType == 'sell' ? 9 : 1
|
|
},
|
|
headerHeight() {
|
|
return this.statusBarTop + uni.upx2px(300)
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
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()
|
|
},
|
|
onUnload() {
|
|
if (uni.offKeyboardHeightChange) {
|
|
uni.offKeyboardHeightChange()
|
|
}
|
|
},
|
|
methods: {
|
|
bindKeyboardListener() {
|
|
if (!uni.onKeyboardHeightChange) return
|
|
uni.onKeyboardHeightChange((res) => {
|
|
this.keyboardOpen = Number(res && res.height) > 0
|
|
})
|
|
},
|
|
back() {
|
|
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)
|
|
}
|
|
},
|
|
getArea() {
|
|
const area = uni.getStorageSync('area')
|
|
if (!area) return {}
|
|
if (typeof area === 'string') {
|
|
try {
|
|
return JSON.parse(area)
|
|
} catch (e) {
|
|
return {}
|
|
}
|
|
}
|
|
return area
|
|
},
|
|
loadCategories() {
|
|
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({
|
|
profile: profile || {},
|
|
actionText: '发布校园二手信息',
|
|
authDialog: this.fishAuthDialogOptions(),
|
|
reload: getIeProfile
|
|
})
|
|
if (!verified) {
|
|
setTimeout(() => this.back(), 300)
|
|
}
|
|
},
|
|
chooseCategory(e) {
|
|
this.selectedCategoryIndex = Number(e.detail.value)
|
|
},
|
|
chooseImages() {
|
|
const remain = this.maxImageCount - this.form.images.length
|
|
if (remain <= 0) return
|
|
uni.chooseImage({
|
|
count: remain,
|
|
sizeType: ['compressed'],
|
|
sourceType: ['album', 'camera'],
|
|
success: async (res) => {
|
|
const paths = res.tempFilePaths || []
|
|
uni.showLoading({ title: '上传中...', mask: true })
|
|
const failMessages = []
|
|
try {
|
|
for (let i = 0; i < paths.length; i++) {
|
|
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)
|
|
}
|
|
})
|
|
},
|
|
removeImage(index) {
|
|
this.form.images.splice(index, 1)
|
|
},
|
|
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: '内容最多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 result = filePath ? await uploadFishReleaseImage(filePath) : null
|
|
if (result && result.passed && result.url) {
|
|
editorCtx.insertImage({
|
|
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)
|
|
if (index > -1) {
|
|
this.form.tags.splice(index, 1)
|
|
} else {
|
|
this.form.tags.push(tag)
|
|
}
|
|
},
|
|
syncEditorContent() {
|
|
return new Promise((resolve) => {
|
|
if (!this.editorIns || !this.editorIns.getContents) {
|
|
resolve()
|
|
return
|
|
}
|
|
this.editorIns.getContents({
|
|
success: (res) => {
|
|
this.form.content = res.html || this.form.content || ''
|
|
this.form.contentText = res.text || this.form.contentText || ''
|
|
resolve()
|
|
},
|
|
fail: () => resolve()
|
|
})
|
|
})
|
|
},
|
|
validate() {
|
|
const title = String(this.form.title || '').trim()
|
|
const price = String(this.form.price || '').trim()
|
|
const originPrice = String(this.form.originPrice || '').trim()
|
|
const contentText = String(this.form.contentText || '').replace(/[ \t\r\n]/g, '')
|
|
const wechat = String(this.form.wechat || '').trim()
|
|
const phone = String(this.form.phone || '').trim()
|
|
if (!title) return '请填写标题'
|
|
if (title.length < 2) return '标题至少2个字'
|
|
if (title.length > 10) return '标题最多10个字'
|
|
if (this.selectedCategoryIndex < 0) return '请选择分类'
|
|
if (!price) return this.publishType == 'sell' ? '请填写售价' : '请填写预算'
|
|
if (!this.isValidPrice(price)) return this.publishType == 'sell' ? '售价必须大于0且最多2位小数' : '预算必须大于0且最多2位小数'
|
|
if (originPrice && !this.isValidAmount(originPrice)) return '原价最多2位小数'
|
|
if (this.publishType == 'sell' && this.form.images.length == 0) return '请至少上传1张商品图片'
|
|
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 (contentText.length > 1000) return this.publishType == 'sell' ? '商品介绍最多1000字' : '求购内容最多1000字'
|
|
if (wechat && !this.isValidWechat(wechat)) return '请输入正确的微信号'
|
|
if (phone && !this.isValidPhone(phone)) return '请输入正确的手机号'
|
|
return ''
|
|
},
|
|
isValidPrice(value) {
|
|
return /^\d+(\.\d{1,2})?$/.test(value) && Number(value) > 0
|
|
},
|
|
isValidAmount(value) {
|
|
return /^\d+(\.\d{1,2})?$/.test(value) && Number(value) >= 0
|
|
},
|
|
isValidWechat(value) {
|
|
return /^[a-zA-Z][-_a-zA-Z0-9]{5,19}$/.test(value)
|
|
},
|
|
isValidPhone(value) {
|
|
return /^1[3-9]\d{9}$/.test(value)
|
|
},
|
|
async submit() {
|
|
if (this.submitLocked) return
|
|
this.submitLocked = true
|
|
let submitSuccess = false
|
|
try {
|
|
await this.syncEditorContent()
|
|
const error = this.validate()
|
|
if (error) {
|
|
uni.showToast({ title: error, icon: 'none' })
|
|
return
|
|
}
|
|
const profile = await getIeProfile().catch(() => null)
|
|
const verified = await ensureIeVerifiedBeforeAction({
|
|
profile: profile || {},
|
|
actionText: '发布校园二手信息',
|
|
authDialog: this.fishAuthDialogOptions(),
|
|
reload: getIeProfile
|
|
})
|
|
if (!verified) return
|
|
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,
|
|
categoryId: category.id,
|
|
categoryName: category.name,
|
|
images: this.publishType == 'want' ? this.form.images.slice(0, 1) : this.form.images,
|
|
contactInfo: {
|
|
wechat: this.form.wechat,
|
|
phone: this.form.phone
|
|
},
|
|
tags: this.form.tags,
|
|
negotiable: this.form.tags.indexOf('可小刀') > -1 ? 1 : 0
|
|
}
|
|
this.submitting = true
|
|
this.auditTitle = this.isEdit ? '保存中,等待审核' : '提交中,等待审核'
|
|
const res = this.publishType == 'sell' ? await publishFishGoods(payload) : await publishFishWant(payload)
|
|
if (res) {
|
|
submitSuccess = true
|
|
this.auditTitle = this.isEdit ? '保存成功,等待审核' : '提交成功,等待审核'
|
|
setTimeout(() => uni.navigateBack(), 800)
|
|
}
|
|
} finally {
|
|
if (!submitSuccess) {
|
|
this.submitting = false
|
|
this.submitLocked = false
|
|
}
|
|
}
|
|
},
|
|
fishAuthDialogOptions() {
|
|
return {
|
|
badge: '校园二手',
|
|
title: '实名认证',
|
|
content: '根据法律法规要求,对应流程需要调用阿里云实名认证。半径里不会存储您的实名信息。',
|
|
steps: []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
page {
|
|
background: #f7f9f7;
|
|
color: #15362f;
|
|
}
|
|
|
|
.release-page {
|
|
min-height: 100vh;
|
|
overflow: visible;
|
|
background: linear-gradient(180deg, #e7fbf4 0%, #f7f9f7 280rpx);
|
|
}
|
|
|
|
.header {
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
z-index: 20;
|
|
padding: 0 32rpx 28rpx;
|
|
background: linear-gradient(180deg, #e7fbf4 0%, rgba(247, 249, 247, 0.98) 100%);
|
|
box-shadow: 0 8rpx 24rpx rgba(24, 99, 78, 0.05);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.back {
|
|
width: 64rpx;
|
|
height: 64rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.header-title {
|
|
margin-top: 12rpx;
|
|
font-size: 42rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.header-sub {
|
|
margin-top: 8rpx;
|
|
color: #729088;
|
|
font-size: 24rpx;
|
|
}
|
|
|
|
.form-scroll {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.tabs {
|
|
width: 360rpx;
|
|
height: 72rpx;
|
|
margin: 26rpx 0 0;
|
|
padding: 6rpx;
|
|
display: flex;
|
|
border-radius: 42rpx;
|
|
background: rgba(255, 255, 255, 0.86);
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.tab {
|
|
flex: 1;
|
|
height: 60rpx;
|
|
line-height: 60rpx;
|
|
border-radius: 34rpx;
|
|
text-align: center;
|
|
font-size: 26rpx;
|
|
font-weight: 800;
|
|
color: #7c8d88;
|
|
}
|
|
|
|
.tab.active {
|
|
background: linear-gradient(135deg, #39ca8f, #24b979);
|
|
color: #fff;
|
|
box-shadow: 0 8rpx 18rpx rgba(36, 185, 121, 0.22);
|
|
}
|
|
|
|
.tab.disabled {
|
|
opacity: .72;
|
|
}
|
|
|
|
.form-card {
|
|
margin: 0 24rpx;
|
|
padding: 4rpx 26rpx 26rpx;
|
|
border-radius: 30rpx;
|
|
background: #fff;
|
|
box-shadow: 0 12rpx 32rpx rgba(29, 74, 60, 0.06);
|
|
}
|
|
|
|
.field {
|
|
padding-top: 26rpx;
|
|
}
|
|
|
|
.label {
|
|
margin-bottom: 14rpx;
|
|
color: #18372f;
|
|
font-size: 27rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.label text {
|
|
color: #9aa8a4;
|
|
font-size: 21rpx;
|
|
font-weight: 400;
|
|
}
|
|
|
|
input,
|
|
textarea,
|
|
.picker-value {
|
|
width: 100%;
|
|
min-height: 78rpx;
|
|
padding: 0 22rpx;
|
|
border-radius: 18rpx;
|
|
background: #f5f8f6;
|
|
box-sizing: border-box;
|
|
color: #223b35;
|
|
font-size: 26rpx;
|
|
}
|
|
|
|
textarea {
|
|
height: 220rpx;
|
|
padding-top: 20rpx;
|
|
line-height: 38rpx;
|
|
}
|
|
|
|
.editor-box {
|
|
min-height: 420rpx;
|
|
overflow: hidden;
|
|
border-radius: 18rpx;
|
|
background: #f5f8f6;
|
|
border: 1rpx solid #edf2ef;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.editor-box ::v-deep .sp-editor-toolbar {
|
|
background: #fff;
|
|
border-bottom: 1rpx solid #edf2ef;
|
|
}
|
|
|
|
.editor-box ::v-deep .sp-editor-wrapper {
|
|
min-height: 320rpx;
|
|
}
|
|
|
|
.editor-box ::v-deep .editor-container {
|
|
min-height: 320rpx;
|
|
padding: 18rpx 20rpx;
|
|
box-sizing: border-box;
|
|
font-size: 26rpx;
|
|
line-height: 40rpx;
|
|
}
|
|
|
|
.picker-value {
|
|
line-height: 78rpx;
|
|
}
|
|
|
|
.picker-value text {
|
|
float: right;
|
|
color: #8ca09a;
|
|
font-size: 34rpx;
|
|
}
|
|
|
|
.price-row {
|
|
display: flex;
|
|
gap: 18rpx;
|
|
}
|
|
|
|
.price-field {
|
|
flex: 1;
|
|
}
|
|
|
|
.image-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 14rpx;
|
|
}
|
|
|
|
.image-item,
|
|
.image-add {
|
|
position: relative;
|
|
width: 150rpx;
|
|
height: 150rpx;
|
|
border-radius: 18rpx;
|
|
overflow: hidden;
|
|
background: #f2f7f4;
|
|
}
|
|
|
|
.image-item image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.remove {
|
|
position: absolute;
|
|
top: 8rpx;
|
|
right: 8rpx;
|
|
width: 34rpx;
|
|
height: 34rpx;
|
|
border-radius: 50%;
|
|
background: rgba(0, 0, 0, 0.48);
|
|
color: #fff;
|
|
text-align: center;
|
|
line-height: 30rpx;
|
|
}
|
|
|
|
.image-add {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #8aa09a;
|
|
font-size: 22rpx;
|
|
}
|
|
|
|
.contact-input {
|
|
margin-top: 14rpx;
|
|
}
|
|
|
|
.tag-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 14rpx;
|
|
}
|
|
|
|
.tag {
|
|
height: 56rpx;
|
|
padding: 0 20rpx;
|
|
border-radius: 28rpx;
|
|
background: #f2f6f4;
|
|
color: #6f817c;
|
|
font-size: 23rpx;
|
|
line-height: 56rpx;
|
|
}
|
|
|
|
.tag.checked {
|
|
background: #e5fbf2;
|
|
color: #1a9a72;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.safe-tip {
|
|
margin: 22rpx 32rpx 0;
|
|
color: #84948f;
|
|
font-size: 22rpx;
|
|
line-height: 34rpx;
|
|
}
|
|
|
|
.submit-bar {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
padding: 18rpx 28rpx calc(18rpx + env(safe-area-inset-bottom));
|
|
background: rgba(255, 255, 255, 0.96);
|
|
box-shadow: 0 -8rpx 24rpx rgba(23, 54, 47, 0.06);
|
|
}
|
|
|
|
.submit-btn {
|
|
height: 88rpx;
|
|
border-radius: 46rpx;
|
|
background: linear-gradient(135deg, #37c990, #19af7e);
|
|
color: #fff;
|
|
font-size: 30rpx;
|
|
font-weight: 900;
|
|
text-align: center;
|
|
line-height: 88rpx;
|
|
}
|
|
|
|
.submit-btn.disabled {
|
|
opacity: 0.62;
|
|
}
|
|
|
|
.audit-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
z-index: 1200;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(12, 31, 25, 0.34);
|
|
}
|
|
|
|
.audit-card {
|
|
width: 480rpx;
|
|
padding: 48rpx 36rpx 42rpx;
|
|
border-radius: 34rpx;
|
|
background: rgba(255, 255, 255, 0.96);
|
|
box-shadow: 0 24rpx 60rpx rgba(19, 70, 54, 0.18);
|
|
text-align: center;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.audit-spinner {
|
|
width: 124rpx;
|
|
height: 124rpx;
|
|
margin: 0 auto 28rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 12rpx;
|
|
border-radius: 50%;
|
|
background: linear-gradient(135deg, #e7fbf4, #f8fffc);
|
|
}
|
|
|
|
.audit-spinner view {
|
|
width: 16rpx;
|
|
height: 16rpx;
|
|
border-radius: 50%;
|
|
background: #20b985;
|
|
animation: audit-bounce 0.9s infinite ease-in-out;
|
|
}
|
|
|
|
.audit-spinner view:nth-child(2) {
|
|
animation-delay: 0.12s;
|
|
}
|
|
|
|
.audit-spinner view:nth-child(3) {
|
|
animation-delay: 0.24s;
|
|
}
|
|
|
|
.audit-title {
|
|
color: #17362f;
|
|
font-size: 31rpx;
|
|
font-weight: 900;
|
|
}
|
|
|
|
.audit-desc {
|
|
margin-top: 14rpx;
|
|
color: #84948f;
|
|
font-size: 23rpx;
|
|
line-height: 34rpx;
|
|
}
|
|
|
|
@keyframes audit-bounce {
|
|
0%,
|
|
80%,
|
|
100% {
|
|
transform: translateY(0);
|
|
opacity: 0.45;
|
|
}
|
|
|
|
40% {
|
|
transform: translateY(-18rpx);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.bottom-space {
|
|
height: 240rpx;
|
|
}
|
|
</style>
|
|
|