2144 行
52 KiB
Vue
2144 行
52 KiB
Vue
<template>
|
||
<view class="create fc-page">
|
||
<!-- 统一顶部深绿质感导航栏,右侧提供独立草稿箱入口 -->
|
||
<fc-navbar title="发布信息" theme="gradient" :show-back="true">
|
||
<template #right>
|
||
<view class="create__draft-entry" @click="goDraftsPage">
|
||
<image class="create__draft-icon" :src="iconUrl('mine-draft')" mode="aspectFit" />
|
||
<text class="create__draft-text">草稿箱</text>
|
||
<text v-if="draftCount > 0" class="create__draft-badge">{{ draftCount }}</text>
|
||
</view>
|
||
</template>
|
||
</fc-navbar>
|
||
|
||
<!-- 1. 分类选择单元格(唯一入口,点击唤起全部分类抽屉,避免同一分类重复展示) -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__cell" @click="openCatDrawer">
|
||
<view class="create__cell-left">
|
||
<text class="create__label">所属分类</text>
|
||
<text class="create__required">*</text>
|
||
</view>
|
||
<view class="create__cell-right">
|
||
<view v-if="currentCat" class="create__selected-cat">
|
||
<image class="create__selected-cat-icon" :src="catIcon(currentCat)" mode="aspectFit" />
|
||
<text class="create__selected-cat-name">{{ currentCat.name }}</text>
|
||
</view>
|
||
<text v-else class="create__cell-ph">请选择信息所属分类</text>
|
||
<text class="create__arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 2. 发布身份选择(个人 / 商家二选一,未认证商家同样展示并支持跳转认证) -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__label-row">
|
||
<text class="create__label">发布身份</text>
|
||
<text v-if="!isMerchantUser" class="create__label-tip">认证商家享专属标识与引流</text>
|
||
</view>
|
||
<view class="create__identity-group">
|
||
<view
|
||
class="create__identity-item"
|
||
:class="{ 'create__identity-item--active': form.identityType === 'person' }"
|
||
@click="switchIdentity('person')"
|
||
>
|
||
<text class="create__identity-title">个人</text>
|
||
<text class="create__identity-desc">发布便民闲置信息</text>
|
||
</view>
|
||
<view
|
||
class="create__identity-item"
|
||
:class="{
|
||
'create__identity-item--active': form.identityType === 'merchant',
|
||
'create__identity-item--unauth': !isMerchantUser
|
||
}"
|
||
@click="switchIdentity('merchant')"
|
||
>
|
||
<view class="create__identity-title-row">
|
||
<text class="create__identity-title">商家</text>
|
||
<text class="create__merchant-badge" :class="'create__merchant-badge--' + merchantBadgeClass">
|
||
{{ merchantBadgeText }}
|
||
</text>
|
||
</view>
|
||
<text class="create__identity-desc fc-ellipsis">{{ merchantDescText }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 3. 基本信息表单(标题、详细内容、媒体上传) -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__label">标题<text class="create__required">*</text></view>
|
||
<input
|
||
v-model="form.title"
|
||
class="create__input"
|
||
placeholder="一句话清晰概括(如:诚聘配电工 待遇从优 / 急售九成新电动车)"
|
||
maxlength="40"
|
||
placeholder-class="create__ph"
|
||
@input="onFieldInput"
|
||
/>
|
||
|
||
<view class="create__label create__label--mt">详细内容<text class="create__required">*</text></view>
|
||
<textarea
|
||
v-model="form.content"
|
||
class="create__textarea"
|
||
placeholder="补充价格、服务时间、详细要求等,信息越详细真实越容易成交..."
|
||
maxlength="500"
|
||
placeholder-class="create__ph"
|
||
@input="onFieldInput"
|
||
/>
|
||
<text class="create__count">{{ (form.content || '').length }}/500</text>
|
||
|
||
<view class="create__label create__label--mt">图片 / 视频(实拍更具可信度)</view>
|
||
<view class="create__media">
|
||
<view v-for="(m, i) in form.media" :key="m + i" class="create__media-item fc-thumb">
|
||
<image v-if="!isVideo(m)" class="create__media-img" :src="assetUrl(m)" mode="aspectFill" />
|
||
<view v-else class="create__media-video">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('plus-ink')" mode="aspectFit" />
|
||
<text class="create__media-video-txt">视频</text>
|
||
</view>
|
||
<view class="create__media-del" @click.stop="removeMedia(i)">
|
||
<text>×</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 上传图片按钮 -->
|
||
<view v-if="!uploading && imageCount < 6" class="create__upload" @click="chooseImage">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('image')" mode="aspectFit" />
|
||
<text class="create__upload-txt">图片 {{ imageCount }}/6</text>
|
||
</view>
|
||
|
||
<!-- 上传视频按钮 -->
|
||
<view v-if="!uploading && videoCount < 1" class="create__upload" @click="chooseVideo">
|
||
<image class="fc-icon fc-icon--md" :src="iconUrl('plus-ink')" mode="aspectFit" />
|
||
<text class="create__upload-txt">短视频 {{ videoCount }}/1</text>
|
||
</view>
|
||
</view>
|
||
<text v-if="uploading" class="create__uploading">媒体上传中,请稍候…</text>
|
||
</view>
|
||
|
||
<!-- 4. 价格与特色标签(按分类推荐单位与亮点) -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__label-row">
|
||
<text class="create__label">期望价格 / 薪资</text>
|
||
<view class="create__negotiable" @click="toggleNegotiable">
|
||
<view class="create__checkbox" :class="{ 'create__checkbox--checked': form.isNegotiable }">
|
||
<text v-if="form.isNegotiable" class="create__checkbox-tick">✓</text>
|
||
</view>
|
||
<text class="create__negotiable-label">面议 / 无标价</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 标价输入 -->
|
||
<view v-if="!form.isNegotiable" class="create__price-box">
|
||
<view class="create__price-input-row">
|
||
<text class="create__price-symbol">¥</text>
|
||
<input
|
||
v-model="form.price"
|
||
class="create__price-input"
|
||
type="digit"
|
||
placeholder="0.00"
|
||
placeholder-class="create__ph"
|
||
@input="onFieldInput"
|
||
/>
|
||
<text class="create__price-unit-text">{{ form.priceUnit || '元' }}</text>
|
||
</view>
|
||
|
||
<!-- 计价单位快捷选择胶囊 -->
|
||
<view class="create__unit-chips">
|
||
<view
|
||
v-for="u in currentUnits"
|
||
:key="u"
|
||
class="create__unit-chip"
|
||
:class="{ 'create__unit-chip--active': form.priceUnit === u }"
|
||
@click="selectPriceUnit(u)"
|
||
>
|
||
{{ u }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 特色亮点标签(最多5个) -->
|
||
<view class="create__label create__label--mt">特色亮点(最多5个)</view>
|
||
|
||
<!-- 已选标签胶囊 -->
|
||
<view v-if="form.tags && form.tags.length" class="create__tags-wrapper">
|
||
<view
|
||
v-for="(t, i) in form.tags"
|
||
:key="'tag-' + t + i"
|
||
class="create__tag-badge"
|
||
@click="removeTag(i)"
|
||
>
|
||
<text class="create__tag-badge-text">{{ t }}</text>
|
||
<text class="create__tag-badge-del">×</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 推荐标签胶囊 -->
|
||
<view v-if="recommendTags.length > 0" class="create__recommend-tags">
|
||
<text class="create__recommend-title">推荐亮点:</text>
|
||
<view class="create__recommend-chips">
|
||
<view
|
||
v-for="rt in recommendTags"
|
||
:key="rt"
|
||
class="create__recommend-chip"
|
||
:class="{ 'create__recommend-chip--disabled': form.tags.includes(rt) }"
|
||
@click="addRecommendTag(rt)"
|
||
>
|
||
+ {{ rt }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 手动添加自定义标签 -->
|
||
<view v-if="form.tags.length < 5" class="create__tag-custom-row">
|
||
<input
|
||
v-model="customTagInput"
|
||
class="create__tag-custom-input"
|
||
placeholder="自定义亮点(如:随时看 / 包过户)"
|
||
maxlength="8"
|
||
placeholder-class="create__ph"
|
||
confirm-type="done"
|
||
@confirm="addCustomTag"
|
||
/>
|
||
<view class="create__tag-custom-btn" @click="addCustomTag">
|
||
<text class="create__tag-custom-btn-txt">添加</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 5. 联系方式与地址定位 -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__row">
|
||
<text class="create__row-label">联系人</text>
|
||
<input
|
||
v-model="form.contact"
|
||
class="create__input create__input--row"
|
||
placeholder="请输入您的称呼(如:李先生)"
|
||
placeholder-class="create__ph"
|
||
@input="onFieldInput"
|
||
/>
|
||
</view>
|
||
|
||
<view class="create__row create__row--line">
|
||
<text class="create__row-label">联系电话</text>
|
||
<input
|
||
v-model="form.phone"
|
||
class="create__input create__input--row"
|
||
type="number"
|
||
maxlength="11"
|
||
placeholder="请输入11位联系手机号"
|
||
placeholder-class="create__ph"
|
||
@input="onFieldInput"
|
||
/>
|
||
</view>
|
||
|
||
<view class="create__row create__row--line">
|
||
<text class="create__row-label">微信号</text>
|
||
<input
|
||
v-model="form.wechat"
|
||
class="create__input create__input--row"
|
||
placeholder="选填,方便意向买家直接微信联系"
|
||
placeholder-class="create__ph"
|
||
maxlength="40"
|
||
@input="onFieldInput"
|
||
/>
|
||
</view>
|
||
|
||
<view class="create__row create__row--line" @click="chooseLocation">
|
||
<text class="create__row-label">所在位置</text>
|
||
<view class="create__location">
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('location')" mode="aspectFit" />
|
||
<text class="create__location-text fc-ellipsis">{{ form.address || '点击定位/选择商铺' }}</text>
|
||
<text class="create__location-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="create__row create__row--line">
|
||
<text class="create__row-label">所属区域</text>
|
||
<fc-area-picker
|
||
class="create__area-picker"
|
||
:areas="areaRows"
|
||
:value="form.areaId"
|
||
variant="plain"
|
||
show-full
|
||
placeholder="请选择省 / 市 / 区"
|
||
@change="onRegionPicked"
|
||
/>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 6. 发布方式与计费(由后台「发布与费用配置」下发) -->
|
||
<view class="fc-card create__section">
|
||
<view class="create__label-row">
|
||
<text class="create__label">发布方式</text>
|
||
<text v-if="publish.mode === 'paid'" class="create__quota">
|
||
套餐额度:剩余 {{ publish.quotaLeft }} 条
|
||
</text>
|
||
</view>
|
||
|
||
<view v-if="publish.mode === 'free'" class="create__free-tip">
|
||
<text>当前处于限时免费模式,所有用户均可直接免费发布!</text>
|
||
</view>
|
||
|
||
<view v-else class="create__plans">
|
||
<view
|
||
v-for="p in plans"
|
||
:key="p.key"
|
||
class="create__plan"
|
||
:class="{ 'create__plan--active': form.plan === p.key }"
|
||
@click="selectPlan(p)"
|
||
>
|
||
<text class="create__plan-name">{{ p.name }}</text>
|
||
<text class="create__plan-price">{{ p.price }}</text>
|
||
<text class="create__plan-desc">{{ p.desc }}</text>
|
||
<text v-if="p.tag" class="create__plan-tag">{{ p.tag }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 支付方式选择(微信 / 余额) -->
|
||
<view v-if="needPay" class="create__pay">
|
||
<text class="create__pay-label">支付方式</text>
|
||
<view class="create__pay-types">
|
||
<view
|
||
class="create__pay-type"
|
||
:class="{ 'create__pay-type--active': form.payType === 'wxpay' }"
|
||
@click="form.payType = 'wxpay'"
|
||
>
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('paywechat')" mode="aspectFit" />
|
||
<text class="create__pay-text">微信支付</text>
|
||
</view>
|
||
<view
|
||
class="create__pay-type"
|
||
:class="{ 'create__pay-type--active': form.payType === 'balance' }"
|
||
@click="form.payType = 'balance'"
|
||
>
|
||
<image class="fc-icon fc-icon--sm" :src="iconUrl('wallet')" mode="aspectFit" />
|
||
<text class="create__pay-text">余额支付(¥{{ balance }})</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部固定主控操作栏 -->
|
||
<view class="create__bar">
|
||
<view class="create__bar-draft" @click="saveDraftManual">
|
||
<image class="create__bar-draft-icon" :src="iconUrl('mine-draft')" mode="aspectFit" />
|
||
<text class="create__bar-draft-txt">存草稿</text>
|
||
</view>
|
||
|
||
<view
|
||
class="create__bar-submit"
|
||
:class="{ 'create__bar-submit--disabled': submitting || uploading }"
|
||
@click="submit"
|
||
>
|
||
<text class="create__bar-submit-txt">
|
||
{{ submitting ? '提交中…' : (needPay ? '确认支付并发布' : '立即公开发布') }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="fc-safe-bottom"></view>
|
||
|
||
<!-- ================= 全部分类弹窗选择器抽屉(海量分类由接口返回决定,支持流畅自适应滚动) ================= -->
|
||
<view
|
||
v-if="catDrawerVisible"
|
||
class="cat-drawer-mask"
|
||
:class="{ 'cat-drawer-mask--visible': catDrawerAnim }"
|
||
@click="closeCatDrawer"
|
||
>
|
||
<view
|
||
class="cat-drawer"
|
||
:class="{ 'cat-drawer--visible': catDrawerAnim }"
|
||
@click.stop
|
||
>
|
||
<view class="cat-drawer__header">
|
||
<text class="cat-drawer__title">选择信息分类</text>
|
||
<view class="cat-drawer__close" @click="closeCatDrawer">
|
||
<text class="cat-drawer__close-txt">✕</text>
|
||
</view>
|
||
</view>
|
||
|
||
<scroll-view class="cat-drawer__body" scroll-y :show-scrollbar="false">
|
||
<view class="cat-drawer__grid">
|
||
<view
|
||
v-for="c in categories"
|
||
:key="c.id"
|
||
class="cat-drawer__item"
|
||
:class="{ 'cat-drawer__item--active': Number(form.categoryId) === Number(c.id) }"
|
||
@click="onSelectDrawerCat(c)"
|
||
>
|
||
<view class="cat-drawer__icon-box">
|
||
<image class="cat-drawer__icon" :src="catIcon(c)" mode="aspectFit" />
|
||
</view>
|
||
<text class="cat-drawer__name">{{ c.name }}</text>
|
||
<view v-if="Number(form.categoryId) === Number(c.id)" class="cat-drawer__check">✓</view>
|
||
</view>
|
||
</view>
|
||
<view class="cat-drawer__space"></view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
/**
|
||
* 信息发布页面(重构版)
|
||
* 核心优化:
|
||
* 1. 分类选择由接口动态返回决定,统一收敛为「所属分类单元格 + 全部分类抽屉」单一入口,
|
||
* 避免同一分类在页面内重复出现(已选值只展示一次);
|
||
* 2. 彻底剥离草稿箱列表到独立页面 /pages/post/drafts,发布页右上方提供直通入口与存草稿闭环;
|
||
* 3. 支持个人 / 商家身份二选一(已认证商家可切换为商家身份发布并附带门店信息);
|
||
* 4. 严格遵循春绿规范,大厂级布局与无障碍高对比度。
|
||
*/
|
||
import FcNavbar from '@/components/fc-navbar/fc-navbar.vue'
|
||
import FcAreaPicker from '@/components/fc-area-picker/fc-area-picker.vue'
|
||
import homeApi from '@/common/api/home.js'
|
||
import postApi from '@/common/api/post.js'
|
||
import { useUserStore } from '@/common/store/index.js'
|
||
import { iconUrl, categoryIconUrl, loadUiConfig, requestSubscribe } from '@/common/store/ui.js'
|
||
import { pay } from '@/common/utils/pay.js'
|
||
import { assetUrl } from '@/common/utils/format.js'
|
||
import config from '@/common/config/index.js'
|
||
|
||
export default {
|
||
components: { FcNavbar, FcAreaPicker },
|
||
data() {
|
||
return {
|
||
categories: [],
|
||
draftCount: 0,
|
||
currentDraftId: 0, // 当前正在编辑的草稿ID(编辑自某草稿)
|
||
// 平铺服务区域(每条自带省/市/区县),交给级联选择器分组
|
||
areaRows: [],
|
||
submitting: false,
|
||
uploading: false,
|
||
draftTimer: null,
|
||
catDrawerVisible: false,
|
||
catDrawerAnim: false,
|
||
customTagInput: '',
|
||
form: {
|
||
categoryId: 0,
|
||
identityType: 'person', // 'person' | 'merchant'
|
||
title: '',
|
||
content: '',
|
||
media: [],
|
||
price: '',
|
||
priceUnit: '元',
|
||
isNegotiable: false,
|
||
wechat: '',
|
||
tags: [],
|
||
contact: '',
|
||
phone: '',
|
||
address: '',
|
||
areaId: 0,
|
||
area: '',
|
||
lat: null,
|
||
lng: null,
|
||
plan: 'free',
|
||
payType: config.defaultPayType,
|
||
},
|
||
publish: {
|
||
mode: 'paid',
|
||
singlePrice: 5,
|
||
discountRate: 1,
|
||
discountText: '',
|
||
monthPrice: 19.9,
|
||
monthQuota: 30,
|
||
yearPrice: 168,
|
||
yearQuota: 500,
|
||
quotaLeft: 0,
|
||
freeQuotaLeft: 0,
|
||
freeQuotaCycle: 'daily',
|
||
freeUnlimited: false,
|
||
},
|
||
}
|
||
},
|
||
computed: {
|
||
/**
|
||
* 当前用户是否已认证为商家
|
||
* @returns {boolean}
|
||
*/
|
||
isMerchantUser() {
|
||
try {
|
||
const u = useUserStore().state.userInfo
|
||
return !!(u && (u.isMerchant || Number(u.merchantStatus) === 1))
|
||
} catch (e) {
|
||
return false
|
||
}
|
||
},
|
||
/**
|
||
* 商家资质审核状态
|
||
* @returns {number} -1未申请, 0审核中, 1已通过, 2未通过
|
||
*/
|
||
merchantAuditStatus() {
|
||
try {
|
||
const u = useUserStore().state.userInfo
|
||
if (u && u.merchantStatus != null) {
|
||
return Number(u.merchantStatus)
|
||
}
|
||
if (u && u.isMerchant) return 1
|
||
return -1
|
||
} catch (e) {
|
||
return -1
|
||
}
|
||
},
|
||
/**
|
||
* 商家店铺名称
|
||
* @returns {string}
|
||
*/
|
||
merchantShopName() {
|
||
try {
|
||
const u = useUserStore().state.userInfo
|
||
return (u && u.merchant && (u.merchant.shop_name || u.merchant.name)) || ''
|
||
} catch (e) {
|
||
return ''
|
||
}
|
||
},
|
||
/**
|
||
* 商家身份徽章展示文案
|
||
* @returns {string}
|
||
*/
|
||
merchantBadgeText() {
|
||
if (this.isMerchantUser) return '已认证'
|
||
const s = this.merchantAuditStatus
|
||
if (s === 0) return '审核中'
|
||
if (s === 2) return '未通过'
|
||
return '去认证'
|
||
},
|
||
/**
|
||
* 商家身份徽章样式类名
|
||
* @returns {'approved'|'pending'|'rejected'|'unauth'}
|
||
*/
|
||
merchantBadgeClass() {
|
||
if (this.isMerchantUser) return 'approved'
|
||
const s = this.merchantAuditStatus
|
||
if (s === 0) return 'pending'
|
||
if (s === 2) return 'rejected'
|
||
return 'unauth'
|
||
},
|
||
/**
|
||
* 商家身份卡片副描述文案
|
||
* @returns {string}
|
||
*/
|
||
merchantDescText() {
|
||
if (this.isMerchantUser) {
|
||
return this.merchantShopName || '展示店铺专属信息'
|
||
}
|
||
const s = this.merchantAuditStatus
|
||
if (s === 0) return '资质审核中,点击查看'
|
||
if (s === 2) return '资质未通过,点击修改'
|
||
return '未认证,点击立即前往认证'
|
||
},
|
||
/**
|
||
* 当前选中的分类对象
|
||
* @returns {Object|null}
|
||
*/
|
||
currentCat() {
|
||
return this.categories.find((c) => Number(c.id) === Number(this.form.categoryId)) || null
|
||
},
|
||
balance() {
|
||
try {
|
||
return useUserStore().state.userInfo?.balance ?? 0
|
||
} catch (e) {
|
||
return 0
|
||
}
|
||
},
|
||
imageCount() {
|
||
return this.form.media.filter((m) => !this.isVideo(m)).length
|
||
},
|
||
videoCount() {
|
||
return this.form.media.filter((m) => this.isVideo(m)).length
|
||
},
|
||
discountRate() {
|
||
const r = Number(this.publish.discountRate)
|
||
return r > 0 && r <= 1 ? r : 1
|
||
},
|
||
singlePriceFinal() {
|
||
return Math.round(Number(this.publish.singlePrice || 0) * this.discountRate * 100) / 100
|
||
},
|
||
discountLabel() {
|
||
return this.discountRate < 1 ? this.publish.discountText || `${Math.round(this.discountRate * 100) / 10} 折` : ''
|
||
},
|
||
plans() {
|
||
const p = this.publish
|
||
if (p.mode === 'free') return []
|
||
const list = []
|
||
const freeLeft = Number(p.freeQuotaLeft)
|
||
const freeUnlimited = p.freeUnlimited === true || freeLeft === -1
|
||
if (p.quotaLeft > 0) {
|
||
list.push({ key: 'quota', name: '套餐额度', price: '免费', desc: `剩余 ${p.quotaLeft} 条`, tag: '可用' })
|
||
} else if (freeUnlimited || freeLeft > 0) {
|
||
const cycle = { daily: '今日', monthly: '本月', total: '累计' }[p.freeQuotaCycle] || '本期'
|
||
list.push({
|
||
key: 'quota',
|
||
name: `${cycle}免费`,
|
||
price: '免费',
|
||
desc: freeUnlimited ? '不限条数' : `${cycle}剩余 ${freeLeft} 条`,
|
||
tag: '可用',
|
||
})
|
||
}
|
||
list.push({
|
||
key: 'single',
|
||
name: '会员单条',
|
||
price: `¥${this.money(this.singlePriceFinal)}`,
|
||
desc: this.discountLabel ? `${this.discountLabel}(原价 ¥${this.money(p.singlePrice)})` : '发布 1 条',
|
||
tag: this.discountLabel ? '会员价' : '',
|
||
})
|
||
list.push({ key: 'month', name: '按月发布', price: `¥${this.money(p.monthPrice)}`, desc: `含 ${p.monthQuota} 条`, tag: '推荐' })
|
||
list.push({ key: 'year', name: '按年发布', price: `¥${this.money(p.yearPrice)}`, desc: `含 ${p.yearQuota} 条`, tag: '更划算' })
|
||
return list
|
||
},
|
||
needPay() {
|
||
return this.publish.mode === 'paid' && this.form.plan !== 'quota'
|
||
},
|
||
/**
|
||
* 当前分类对应的常用计价单位
|
||
*/
|
||
currentUnits() {
|
||
const catId = Number(this.form.categoryId || 0)
|
||
if (catId === 1) return ['元/月', '元/天', '元/小时', '元/次']
|
||
if (catId === 2) return ['元/月', '万元', '元/天', '元/季']
|
||
if (catId === 3) return ['元']
|
||
if (catId === 4) return ['万元', '元']
|
||
if (catId === 5) return ['元起', '元/次', '元/小时', '元/天']
|
||
if (catId === 6) return ['元/课时', '元', '元/月']
|
||
if (catId === 7) return ['元/次', '元/小时', '元/㎡', '元/月']
|
||
return ['元', '元/月', '元/次', '万元']
|
||
},
|
||
/**
|
||
* 当前分类对应的常用同城亮点标签
|
||
*/
|
||
recommendTags() {
|
||
const catId = Number(this.form.categoryId || 0)
|
||
const map = {
|
||
1: ['日结', '包吃住', '双休', '五险一金', '经验不限', '就近分配'],
|
||
2: ['精装修', '近地铁', '随时看房', '押一付一', '家电齐全', '独立卫浴'],
|
||
3: ['9成新', '支持验机', '同城自提', '急出可刀', '配件齐全', '保修期内'],
|
||
4: ['一手车', '无事故', '准新车', '支持检测', '省油好开', '带牌转让'],
|
||
5: ['上门服务', '明码标价', '十年经验', '专业高效', '质保售后', '免费检测'],
|
||
6: ['体验课', '一对一', '名师授课', '小班教学', '零基础', '包学会'],
|
||
7: ['自带工具', '持健康证', '深度保洁', '满意付款', '实名认证'],
|
||
8: ['运动搭子', '周末活动', 'AA制', '新手友好', '同城聚会']
|
||
}
|
||
return map[catId] || ['高品质', '值得信赖', '同城便民', '价格透明']
|
||
},
|
||
},
|
||
onLoad(query) {
|
||
if (query && query.categoryId) this.form.categoryId = Number(query.categoryId)
|
||
if (query && query.title) this.form.title = decodeURIComponent(query.title)
|
||
if (query && query.draftId) {
|
||
this.loadDraftPost(Number(query.draftId))
|
||
} else if (query && query.editId) {
|
||
this.loadEditPost(Number(query.editId))
|
||
}
|
||
loadUiConfig()
|
||
this.init()
|
||
},
|
||
/**
|
||
* 页面每次显示时触发:刷新草稿数并静默同步最新用户资料(如认证状态)
|
||
*/
|
||
async onShow() {
|
||
this.updateDraftCount()
|
||
try {
|
||
const userStore = useUserStore()
|
||
if (userStore.isLogin.value) {
|
||
await userStore.fetchProfile()
|
||
}
|
||
} catch (e) {}
|
||
},
|
||
methods: {
|
||
iconUrl,
|
||
assetUrl,
|
||
catIcon(c) {
|
||
if (!c) return ''
|
||
return (c.iconKey && iconUrl(c.iconKey)) || categoryIconUrl(c.id)
|
||
},
|
||
/**
|
||
* 页面基础数据初始化
|
||
*/
|
||
async init() {
|
||
try {
|
||
const cats = await homeApi.categories()
|
||
this.categories = Array.isArray(cats) ? cats : []
|
||
// 若未指定分类且已有分类列表,默认选中第一个
|
||
if (!this.form.categoryId && this.categories.length) {
|
||
this.form.categoryId = Number(this.categories[0].id)
|
||
} else if (this.form.categoryId) {
|
||
this.form.categoryId = Number(this.form.categoryId)
|
||
}
|
||
// 联动初始化当前分类的首选计价单位
|
||
if (this.currentUnits && this.currentUnits.length && (!this.form.priceUnit || this.form.priceUnit === '元')) {
|
||
this.form.priceUnit = this.currentUnits[0]
|
||
}
|
||
} catch (e) {
|
||
uni.showToast({ title: '分类数据加载失败', icon: 'none' })
|
||
}
|
||
|
||
try {
|
||
const rows = await homeApi.areas()
|
||
this.areaRows = Array.isArray(rows) ? rows : []
|
||
} catch (e) {}
|
||
|
||
this.loadPublish()
|
||
this.updateDraftCount()
|
||
},
|
||
/**
|
||
* 刷新草稿箱数量统计
|
||
*/
|
||
async updateDraftCount() {
|
||
try {
|
||
const drafts = await postApi.drafts()
|
||
this.draftCount = Array.isArray(drafts) ? drafts.length : 0
|
||
} catch (e) {
|
||
this.draftCount = 0
|
||
}
|
||
},
|
||
/**
|
||
* 跳转独立草稿箱页面
|
||
*/
|
||
goDraftsPage() {
|
||
uni.navigateTo({
|
||
url: '/pages/post/drafts',
|
||
})
|
||
},
|
||
/**
|
||
* 从草稿中还原数据
|
||
* @param {number} draftId
|
||
*/
|
||
async loadDraftPost(draftId) {
|
||
try {
|
||
const drafts = await postApi.drafts()
|
||
const target = (Array.isArray(drafts) ? drafts : []).find((d) => d.draftId === draftId)
|
||
if (target) {
|
||
this.currentDraftId = draftId
|
||
if (target.categoryId) this.form.categoryId = target.categoryId
|
||
this.form.title = target.title || ''
|
||
this.form.content = target.content || ''
|
||
this.form.contact = target.contact || ''
|
||
this.form.phone = target.phone || ''
|
||
this.form.wechat = target.wechat || ''
|
||
this.form.address = target.address || ''
|
||
this.form.areaId = target.areaId || 0
|
||
this.form.area = target.area || ''
|
||
this.form.lat = target.lat || null
|
||
this.form.lng = target.lng || null
|
||
if (target.identityType) this.form.identityType = target.identityType
|
||
if (target.price != null && target.price > 0) {
|
||
this.form.price = String(target.price)
|
||
this.form.isNegotiable = false
|
||
} else if (target.priceUnit === '面议') {
|
||
this.form.price = ''
|
||
this.form.isNegotiable = true
|
||
}
|
||
if (target.priceUnit) this.form.priceUnit = target.priceUnit
|
||
if (Array.isArray(target.tags)) this.form.tags = [...target.tags]
|
||
if (Array.isArray(target.media)) this.form.media = [...target.media]
|
||
uni.showToast({ title: '已载入草稿内容', icon: 'none' })
|
||
}
|
||
} catch (e) {}
|
||
},
|
||
/**
|
||
* 载入重新编辑信息
|
||
* @param {number} id
|
||
*/
|
||
async loadEditPost(id) {
|
||
try {
|
||
const p = await postApi.detail(id)
|
||
if (p) {
|
||
if (p.categoryId) this.form.categoryId = p.categoryId
|
||
this.form.title = p.title || ''
|
||
this.form.content = p.content || ''
|
||
this.form.contact = p.contact || ''
|
||
this.form.phone = p.phone || ''
|
||
this.form.wechat = p.wechat || ''
|
||
this.form.address = p.address || ''
|
||
this.form.areaId = p.areaId || 0
|
||
this.form.area = p.area || ''
|
||
this.form.lat = p.lat || null
|
||
this.form.lng = p.lng || null
|
||
if (p.identityType) this.form.identityType = p.identityType
|
||
if (p.price != null && p.price > 0) {
|
||
this.form.price = String(p.price)
|
||
this.form.isNegotiable = false
|
||
} else if (p.priceUnit === '面议' || p.price === 0) {
|
||
this.form.price = ''
|
||
this.form.isNegotiable = true
|
||
}
|
||
if (p.priceUnit) this.form.priceUnit = p.priceUnit
|
||
if (Array.isArray(p.tags)) this.form.tags = [...p.tags]
|
||
if (Array.isArray(p.media)) this.form.media = [...p.media]
|
||
uni.showToast({ title: '已载入待修改内容', icon: 'none' })
|
||
}
|
||
} catch (e) {}
|
||
},
|
||
/**
|
||
* 切换期望价格面议状态
|
||
*/
|
||
toggleNegotiable() {
|
||
this.form.isNegotiable = !this.form.isNegotiable
|
||
if (this.form.isNegotiable) {
|
||
this.form.price = ''
|
||
this.form.priceUnit = '面议'
|
||
} else {
|
||
this.form.priceUnit = (this.currentUnits && this.currentUnits[0]) || '元'
|
||
}
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 快速选择计价单位
|
||
* @param {string} u 计价单位
|
||
*/
|
||
selectPriceUnit(u) {
|
||
this.form.priceUnit = u
|
||
if (this.form.isNegotiable) {
|
||
this.form.isNegotiable = false
|
||
}
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 点击添加分类推荐亮点标签
|
||
* @param {string} rt 推荐标签
|
||
*/
|
||
addRecommendTag(rt) {
|
||
if (!rt) return
|
||
if (this.form.tags.includes(rt)) {
|
||
this.removeTag(this.form.tags.indexOf(rt))
|
||
return
|
||
}
|
||
if (this.form.tags.length >= 5) {
|
||
uni.showToast({ title: '最多添加5个标签', icon: 'none' })
|
||
return
|
||
}
|
||
this.form.tags.push(rt)
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 移除已选亮点标签
|
||
* @param {number} idx 标签序号
|
||
*/
|
||
removeTag(idx) {
|
||
this.form.tags.splice(idx, 1)
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 手动添加自定义标签
|
||
*/
|
||
addCustomTag() {
|
||
const tag = (this.customTagInput || '').trim()
|
||
if (!tag) return
|
||
if (this.form.tags.includes(tag)) {
|
||
uni.showToast({ title: '标签已存在', icon: 'none' })
|
||
return
|
||
}
|
||
if (this.form.tags.length >= 5) {
|
||
uni.showToast({ title: '最多添加5个标签', icon: 'none' })
|
||
return
|
||
}
|
||
this.form.tags.push(tag)
|
||
this.customTagInput = ''
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 选中发布套餐卡片(区分单条与会员月卡/年卡特权)
|
||
* @param {Object} p 套餐对象
|
||
*/
|
||
selectPlan(p) {
|
||
if (p.key === 'month' || p.key === 'year') {
|
||
uni.showModal({
|
||
title: '开通会员特权',
|
||
content: `${p.name}为会员特权服务(${p.price} / ${p.desc})。开通后可畅享海量发布额度,是否前往会员中心开通?`,
|
||
confirmText: '去开通',
|
||
cancelText: '再想想',
|
||
confirmColor: '#00e070',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.navigateTo({ url: '/pages/member/index' })
|
||
}
|
||
},
|
||
})
|
||
return
|
||
}
|
||
this.form.plan = p.key
|
||
},
|
||
/**
|
||
* 读取后台发布计费配置
|
||
*/
|
||
async loadPublish() {
|
||
try {
|
||
const p = await postApi.publishConfig()
|
||
this.publish = { ...this.publish, ...p }
|
||
if (p.mode === 'free') {
|
||
this.form.plan = 'free'
|
||
} else {
|
||
const freeAvailable = p.quotaLeft > 0 || p.freeUnlimited === true || Number(p.freeQuotaLeft) > 0
|
||
this.form.plan = freeAvailable ? 'quota' : 'single'
|
||
}
|
||
} catch (e) {}
|
||
},
|
||
/**
|
||
* 切换发布身份(个人 / 商家)
|
||
* 商家未认证时弹窗提示并引导跳转商家资质认证页面
|
||
* @param {'person'|'merchant'} type 身份类型
|
||
*/
|
||
switchIdentity(type) {
|
||
if (type === 'merchant') {
|
||
// 未认证商家时,提示并跳转商家认证页面
|
||
if (!this.isMerchantUser) {
|
||
const status = this.merchantAuditStatus
|
||
let title = '商家认证提示'
|
||
let content = '发布商家信息需先完成商家资质认证,认证后尊享商家标识与店铺展示。是否立即前往认证?'
|
||
let confirmText = '去认证'
|
||
|
||
if (status === 0) {
|
||
content = '您的商家资质正在审核中,工作人员将在1-3个工作日内完成审核。是否前往查看进度?'
|
||
confirmText = '查看进度'
|
||
} else if (status === 2) {
|
||
content = '您的商家资质审核未通过,请核对资料后重新提交。是否前往修改?'
|
||
confirmText = '重新提交'
|
||
}
|
||
|
||
uni.showModal({
|
||
title,
|
||
content,
|
||
confirmText,
|
||
cancelText: '取消',
|
||
confirmColor: '#00e070',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.navigateTo({ url: '/pages/merchant/info' })
|
||
}
|
||
},
|
||
})
|
||
return
|
||
}
|
||
this.form.identityType = 'merchant'
|
||
// 自动带入商家的认证信息
|
||
const u = useUserStore().state.userInfo
|
||
if (u && u.merchant) {
|
||
const contact = u.merchant.contact_name || u.merchant.contactName || ''
|
||
const phone = u.merchant.contact_phone || u.merchant.contactPhone || ''
|
||
const address = u.merchant.address || ''
|
||
if (!this.form.contact && contact) {
|
||
this.form.contact = contact
|
||
}
|
||
if (!this.form.phone && phone) {
|
||
this.form.phone = phone
|
||
}
|
||
if (!this.form.address && address) {
|
||
this.form.address = address
|
||
}
|
||
}
|
||
} else {
|
||
this.form.identityType = 'person'
|
||
}
|
||
},
|
||
/**
|
||
* 打开全部分类弹窗抽屉
|
||
*/
|
||
openCatDrawer() {
|
||
this.catDrawerVisible = true
|
||
setTimeout(() => {
|
||
this.catDrawerAnim = true
|
||
}, 20)
|
||
},
|
||
/**
|
||
* 关闭全部分类抽屉
|
||
*/
|
||
closeCatDrawer() {
|
||
this.catDrawerAnim = false
|
||
setTimeout(() => {
|
||
this.catDrawerVisible = false
|
||
}, 200)
|
||
},
|
||
/**
|
||
* 在抽屉中点选分类
|
||
* @param {Object} c 分类项
|
||
*/
|
||
onSelectDrawerCat(c) {
|
||
this.selectCat(c)
|
||
this.closeCatDrawer()
|
||
},
|
||
/**
|
||
* 选中分类
|
||
* @param {Object} c 分类项
|
||
*/
|
||
selectCat(c) {
|
||
if (!c) return
|
||
const prevCat = this.form.categoryId
|
||
this.form.categoryId = c.id
|
||
if (prevCat !== c.id && !this.form.isNegotiable) {
|
||
this.form.priceUnit = (this.currentUnits && this.currentUnits[0]) || '元'
|
||
}
|
||
this.triggerAutoSave()
|
||
},
|
||
money(v) {
|
||
const n = Number(v || 0)
|
||
return Number.isInteger(n) ? String(n) : n.toFixed(2)
|
||
},
|
||
isVideo(url) {
|
||
return /\.(mp4|mov|m4v|avi|webm|mkv)(\?|$)/i.test(String(url || ''))
|
||
},
|
||
chooseImage() {
|
||
if (this.uploading) return
|
||
const remain = 6 - this.imageCount
|
||
if (remain <= 0) return uni.showToast({ title: '最多上传 6 张图片', icon: 'none' })
|
||
uni.chooseImage({
|
||
count: remain,
|
||
success: async (res) => {
|
||
await this.uploadFiles(res.tempFilePaths || [], 'image')
|
||
},
|
||
})
|
||
},
|
||
chooseVideo() {
|
||
if (this.uploading) return
|
||
if (this.videoCount >= 1) return uni.showToast({ title: '最多上传 1 个视频', icon: 'none' })
|
||
uni.chooseVideo({
|
||
maxDuration: 60,
|
||
success: async (res) => {
|
||
await this.uploadFiles([res.tempFilePath], 'video')
|
||
},
|
||
})
|
||
},
|
||
async uploadFiles(paths, type) {
|
||
if (!paths.length) return
|
||
this.uploading = true
|
||
uni.showLoading({ title: '上传中…', mask: true })
|
||
try {
|
||
for (const p of paths) {
|
||
const up = await postApi.uploadMedia(p, type)
|
||
if (up && up.url) this.form.media.push(up.url)
|
||
}
|
||
this.triggerAutoSave()
|
||
uni.hideLoading()
|
||
uni.showToast({ title: '上传成功', icon: 'none' })
|
||
} catch (e) {
|
||
uni.hideLoading()
|
||
uni.showToast({ title: e.message || '上传失败', icon: 'none' })
|
||
} finally {
|
||
this.uploading = false
|
||
}
|
||
},
|
||
removeMedia(i) {
|
||
this.form.media.splice(i, 1)
|
||
this.triggerAutoSave()
|
||
},
|
||
chooseLocation() {
|
||
uni.chooseLocation({
|
||
success: (res) => {
|
||
this.form.address = res.address || res.name
|
||
this.form.lat = typeof res.latitude === 'number' ? res.latitude : null
|
||
this.form.lng = typeof res.longitude === 'number' ? res.longitude : null
|
||
// 定位成功后自动匹配省 / 市 / 区(失败保留用户已选区域)
|
||
this.matchRegionByLocation(this.form.lat, this.form.lng)
|
||
this.triggerAutoSave()
|
||
},
|
||
fail: () => {
|
||
uni.showToast({ title: '请选择所属区域并填写地址', icon: 'none' })
|
||
},
|
||
})
|
||
},
|
||
/** 级联选择器选中服务区域 */
|
||
onRegionPicked(area) {
|
||
this.form.areaId = area ? Number(area.areaId) || 0 : 0
|
||
this.form.area = area ? area.district || '' : ''
|
||
this.triggerAutoSave()
|
||
},
|
||
/**
|
||
* 按经纬度匹配服务区域(后端 /home/locate)
|
||
* @param {number|null} lat
|
||
* @param {number|null} lng
|
||
*/
|
||
async matchRegionByLocation(lat, lng) {
|
||
if (lat == null || lng == null) return
|
||
try {
|
||
const found = await homeApi.locate({ lat, lng })
|
||
if (!found || !found.areaId) return
|
||
this.form.areaId = Number(found.areaId) || 0
|
||
this.form.area = found.district || ''
|
||
} catch (e) {}
|
||
},
|
||
onFieldInput() {
|
||
this.triggerAutoSave()
|
||
},
|
||
triggerAutoSave() {
|
||
if (this.draftTimer) clearTimeout(this.draftTimer)
|
||
this.draftTimer = setTimeout(() => {
|
||
if (this.form.title || this.form.content) {
|
||
this.executeSaveDraft(true)
|
||
}
|
||
}, 1200)
|
||
},
|
||
/**
|
||
* 用户点击手动存草稿
|
||
*/
|
||
async saveDraftManual() {
|
||
if (!this.form.title && !this.form.content) {
|
||
uni.showToast({ title: '内容为空,无需保存', icon: 'none' })
|
||
return
|
||
}
|
||
await this.executeSaveDraft(false)
|
||
},
|
||
/**
|
||
* 执行保存草稿接口
|
||
* @param {boolean} silent 是否静默保存
|
||
*/
|
||
async executeSaveDraft(silent = false) {
|
||
try {
|
||
const payload = {
|
||
...this.form,
|
||
price: this.form.isNegotiable ? 0 : (Number(this.form.price) || 0),
|
||
priceUnit: this.form.isNegotiable ? '面议' : (this.form.priceUnit || '元'),
|
||
tags: this.form.tags,
|
||
draftId: this.currentDraftId || 0,
|
||
}
|
||
const res = await postApi.saveDraft(payload)
|
||
if (res && res.draftId) {
|
||
this.currentDraftId = res.draftId
|
||
}
|
||
this.updateDraftCount()
|
||
if (!silent) {
|
||
uni.showToast({ title: '已存入草稿箱', icon: 'success' })
|
||
}
|
||
} catch (e) {
|
||
if (!silent) {
|
||
uni.showToast({ title: (e && e.message) || '保存失败', icon: 'none' })
|
||
}
|
||
}
|
||
},
|
||
/**
|
||
* 表单合法性验证
|
||
* @returns {string} 错误信息,为空则验证通过
|
||
*/
|
||
validate() {
|
||
if (!this.form.categoryId) return '请选择所属分类'
|
||
if (this.form.identityType === 'merchant' && !this.isMerchantUser) return '请先完成商家资质认证'
|
||
if (!this.form.title || !this.form.title.trim()) return '请填写标题'
|
||
if (!this.form.content || !this.form.content.trim()) return '请填写详细内容'
|
||
if (!this.form.areaId) return '请选择所属区域'
|
||
if (this.form.phone && !/^1\d{10}$/.test(this.form.phone)) return '请输入正确的11位手机号'
|
||
return ''
|
||
},
|
||
/**
|
||
* 提交发布信息
|
||
*/
|
||
async submit() {
|
||
if (this.submitting) return
|
||
if (this.uploading) {
|
||
uni.showToast({ title: '媒体上传中,请稍候', icon: 'none' })
|
||
return
|
||
}
|
||
const err = this.validate()
|
||
if (err) {
|
||
uni.showToast({ title: err, icon: 'none' })
|
||
return
|
||
}
|
||
|
||
this.submitting = true
|
||
try {
|
||
// 订阅消息授权(审核结果);未配置模板时静默跳过
|
||
await requestSubscribe('audit')
|
||
const payload = {
|
||
...this.form,
|
||
price: this.form.isNegotiable ? 0 : (Number(this.form.price) || 0),
|
||
priceUnit: this.form.isNegotiable ? '面议' : (this.form.priceUnit || '元'),
|
||
tags: this.form.tags,
|
||
plan: this.form.plan === 'quota' ? 'free' : this.form.plan,
|
||
}
|
||
const res = await postApi.create(payload)
|
||
|
||
// 若有需要支付的订单
|
||
if (res && res.order) {
|
||
try {
|
||
await pay(res.order, this.form.payType)
|
||
} catch (payErr) {
|
||
uni.showToast({ title: payErr.message || '支付未完成', icon: 'none' })
|
||
return
|
||
}
|
||
}
|
||
|
||
// 若发布成功且当前编辑自草稿,自动删除该草稿
|
||
if (this.currentDraftId) {
|
||
postApi.deleteDraft(this.currentDraftId).catch(() => {})
|
||
}
|
||
|
||
uni.showToast({
|
||
title: res.auditStatus === 0 ? '发布成功,审核中' : '发布成功',
|
||
icon: 'success',
|
||
})
|
||
|
||
setTimeout(() => {
|
||
uni.redirectTo({
|
||
url: `/pages/detail/detail?id=${res.postId}`,
|
||
})
|
||
}, 600)
|
||
} catch (e) {
|
||
uni.showToast({ title: e.message || '发布失败', icon: 'none' })
|
||
} finally {
|
||
this.submitting = false
|
||
}
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.create {
|
||
min-height: 100vh;
|
||
background-color: $fc-bg;
|
||
padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
|
||
}
|
||
|
||
/* 顶部独立草稿箱入口按钮 */
|
||
.create__draft-entry {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(255, 255, 255, 0.18);
|
||
border: 1rpx solid rgba(255, 255, 255, 0.35);
|
||
border-radius: 28rpx;
|
||
padding: 8rpx 18rpx;
|
||
position: relative;
|
||
cursor: pointer;
|
||
transition: opacity 0.15s ease;
|
||
|
||
&:active {
|
||
opacity: 0.8;
|
||
}
|
||
}
|
||
|
||
.create__draft-icon {
|
||
width: 28rpx;
|
||
height: 28rpx;
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.create__draft-text {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.create__draft-badge {
|
||
position: absolute;
|
||
top: -10rpx;
|
||
right: -10rpx;
|
||
background: #ff5252;
|
||
color: #ffffff;
|
||
font-size: 18rpx;
|
||
font-weight: 700;
|
||
min-width: 28rpx;
|
||
height: 28rpx;
|
||
border-radius: 14rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 6rpx;
|
||
box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.2);
|
||
}
|
||
|
||
/* 表单卡片区域 */
|
||
.create__section {
|
||
margin: 20rpx 28rpx 0;
|
||
padding: 30rpx 28rpx;
|
||
background: #ffffff;
|
||
border-radius: 24rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(4, 48, 30, 0.03);
|
||
}
|
||
|
||
.create__label {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
&--mt {
|
||
margin-top: 32rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
}
|
||
|
||
.create__required {
|
||
color: #e02020;
|
||
margin-left: 6rpx;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.create__label-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
/* 分类选择单元格(唯一入口) */
|
||
.create__cell {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
min-height: 88rpx;
|
||
padding: 12rpx 0;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.create__cell-left {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.create__cell-right {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.create__cell-ph {
|
||
font-size: 28rpx;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
|
||
.create__arrow {
|
||
font-size: 36rpx;
|
||
color: #b5c7bc;
|
||
margin-left: 12rpx;
|
||
line-height: 1;
|
||
}
|
||
|
||
.create__selected-cat {
|
||
display: flex;
|
||
align-items: center;
|
||
background: rgba(0, 224, 112, 0.12);
|
||
border: 1rpx solid rgba(0, 224, 112, 0.3);
|
||
border-radius: 30rpx;
|
||
padding: 8rpx 20rpx;
|
||
}
|
||
|
||
.create__selected-cat-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 10rpx;
|
||
}
|
||
|
||
.create__selected-cat-name {
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
color: #04874a;
|
||
}
|
||
|
||
.create__label-tip {
|
||
font-size: 22rpx;
|
||
color: $fc-text-placeholder;
|
||
font-weight: 400;
|
||
margin-left: auto;
|
||
}
|
||
|
||
/* 2. 身份切换组 */
|
||
.create__identity-group {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: 20rpx;
|
||
margin-top: 12rpx;
|
||
}
|
||
|
||
.create__identity-item {
|
||
border: 2rpx solid #e2eee6;
|
||
background: #f8fbf9;
|
||
border-radius: 18rpx;
|
||
padding: 22rpx 20rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transition: all 0.2s ease;
|
||
cursor: pointer;
|
||
|
||
&--active {
|
||
border-color: #00e070;
|
||
background: #edfbf3;
|
||
|
||
.create__identity-title {
|
||
color: #04874a;
|
||
}
|
||
}
|
||
|
||
&--unauth {
|
||
border-style: dashed;
|
||
background: #fafdfb;
|
||
}
|
||
}
|
||
|
||
.create__identity-title-row {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.create__identity-title {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
}
|
||
|
||
.create__merchant-badge {
|
||
font-size: 18rpx;
|
||
font-weight: 700;
|
||
border-radius: 6rpx;
|
||
padding: 2rpx 10rpx;
|
||
margin-left: 10rpx;
|
||
line-height: 26rpx;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
|
||
&--approved {
|
||
background: #f5a623;
|
||
color: #4a2600;
|
||
font-weight: 700;
|
||
}
|
||
|
||
&--unauth {
|
||
background: #e6f9ef;
|
||
color: #04874a;
|
||
border: 1rpx solid #b8ebd0;
|
||
}
|
||
|
||
&--pending {
|
||
background: #eff6ff;
|
||
color: #2563eb;
|
||
border: 1rpx solid #bfdbfe;
|
||
}
|
||
|
||
&--rejected {
|
||
background: #fef2f2;
|
||
color: #dc2626;
|
||
border: 1rpx solid #fecaca;
|
||
}
|
||
}
|
||
|
||
.create__identity-desc {
|
||
margin-top: 8rpx;
|
||
font-size: 22rpx;
|
||
color: $fc-text-placeholder;
|
||
}
|
||
|
||
/* 输入框与多行文本 */
|
||
.create__input {
|
||
height: 88rpx;
|
||
background: #f8faf8;
|
||
border-radius: 16rpx;
|
||
border: 1rpx solid #e6f0ea;
|
||
padding: 0 24rpx;
|
||
font-size: 28rpx;
|
||
color: $fc-text;
|
||
margin-top: 16rpx;
|
||
transition: border-color 0.2s ease;
|
||
|
||
&:focus {
|
||
border-color: #00e070;
|
||
background: #ffffff;
|
||
}
|
||
|
||
&--row {
|
||
margin-top: 0;
|
||
text-align: right;
|
||
border: none;
|
||
background: transparent;
|
||
padding: 0;
|
||
}
|
||
}
|
||
|
||
.create__textarea {
|
||
width: 100%;
|
||
height: 200rpx;
|
||
background: #f8faf8;
|
||
border-radius: 16rpx;
|
||
border: 1rpx solid #e6f0ea;
|
||
padding: 20rpx 24rpx;
|
||
font-size: 28rpx;
|
||
color: $fc-text;
|
||
box-sizing: border-box;
|
||
|
||
&:focus {
|
||
border-color: #00e070;
|
||
background: #ffffff;
|
||
}
|
||
}
|
||
|
||
.create__ph {
|
||
color: $fc-text-placeholder;
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.create__count {
|
||
display: block;
|
||
text-align: right;
|
||
font-size: 22rpx;
|
||
color: $fc-text-placeholder;
|
||
margin-top: 8rpx;
|
||
}
|
||
|
||
/* 媒体上传 */
|
||
.create__media {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.create__media-item {
|
||
width: 156rpx;
|
||
height: 156rpx;
|
||
border-radius: 16rpx;
|
||
position: relative;
|
||
background: #f4f7f5;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.create__media-img {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
|
||
.create__media-video {
|
||
width: 100%;
|
||
height: 100%;
|
||
background: #1a2d23;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.create__media-video-txt {
|
||
font-size: 22rpx;
|
||
color: #ffffff;
|
||
margin-top: 8rpx;
|
||
}
|
||
|
||
.create__media-del {
|
||
position: absolute;
|
||
top: 8rpx;
|
||
right: 8rpx;
|
||
width: 38rpx;
|
||
height: 38rpx;
|
||
border-radius: 50%;
|
||
background: rgba(0, 0, 0, 0.65);
|
||
color: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
line-height: 1;
|
||
}
|
||
|
||
.create__upload {
|
||
width: 156rpx;
|
||
height: 156rpx;
|
||
border-radius: 16rpx;
|
||
border: 2rpx dashed #b8d4c4;
|
||
background: #f9fbf9;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
|
||
&:active {
|
||
background: #eef7f2;
|
||
}
|
||
}
|
||
|
||
.create__upload-txt {
|
||
font-size: 20rpx;
|
||
color: $fc-text-sub;
|
||
margin-top: 10rpx;
|
||
}
|
||
|
||
.create__uploading {
|
||
display: block;
|
||
margin-top: 12rpx;
|
||
font-size: 22rpx;
|
||
color: #04874a;
|
||
}
|
||
|
||
/* 价格与面议开关 */
|
||
.create__negotiable {
|
||
display: flex;
|
||
align-items: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.create__checkbox {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
border-radius: 8rpx;
|
||
border: 2rpx solid #b8d4c4;
|
||
background: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 10rpx;
|
||
transition: all 0.15s ease;
|
||
|
||
&--checked {
|
||
border-color: #00e070;
|
||
background: #00e070;
|
||
}
|
||
}
|
||
|
||
.create__checkbox-tick {
|
||
font-size: 20rpx;
|
||
font-weight: 900;
|
||
color: #04301e;
|
||
line-height: 1;
|
||
}
|
||
|
||
.create__negotiable-label {
|
||
font-size: 26rpx;
|
||
color: $fc-text-sub;
|
||
}
|
||
|
||
/* 标价与计价单位 */
|
||
.create__price-box {
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.create__price-input-row {
|
||
display: flex;
|
||
align-items: center;
|
||
background: #f8faf8;
|
||
border-radius: 16rpx;
|
||
border: 1rpx solid #e6f0ea;
|
||
padding: 0 24rpx;
|
||
height: 92rpx;
|
||
transition: border-color 0.2s ease;
|
||
|
||
&:focus-within {
|
||
border-color: #00e070;
|
||
background: #ffffff;
|
||
}
|
||
}
|
||
|
||
.create__price-symbol {
|
||
font-size: 34rpx;
|
||
font-weight: 800;
|
||
color: #f5a623; /* 阳光金强调价值 */
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.create__price-input {
|
||
flex: 1;
|
||
height: 88rpx;
|
||
font-size: 36rpx;
|
||
font-weight: 700;
|
||
color: #f5a623;
|
||
}
|
||
|
||
.create__price-unit-text {
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
color: $fc-text-sub;
|
||
margin-left: 12rpx;
|
||
}
|
||
|
||
/* 计价单位快捷胶囊 */
|
||
.create__unit-chips {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 14rpx;
|
||
margin-top: 18rpx;
|
||
}
|
||
|
||
.create__unit-chip {
|
||
padding: 10rpx 24rpx;
|
||
border-radius: 28rpx;
|
||
font-size: 24rpx;
|
||
color: $fc-text;
|
||
background: #f4f8f5;
|
||
border: 1rpx solid #dcece1;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
|
||
&--active {
|
||
background: rgba(0, 224, 112, 0.16);
|
||
border-color: #00e070;
|
||
color: #04874a;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
|
||
/* 特色亮点标签 */
|
||
.create__tags-wrapper {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 14rpx;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.create__tag-badge {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
background: #00e070;
|
||
border-radius: 28rpx;
|
||
padding: 8rpx 20rpx;
|
||
cursor: pointer;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 224, 112, 0.2);
|
||
}
|
||
|
||
.create__tag-badge-text {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #04301e; /* 亮绿背景严格使用深墨绿 */
|
||
margin-right: 8rpx;
|
||
}
|
||
|
||
.create__tag-badge-del {
|
||
font-size: 26rpx;
|
||
font-weight: 900;
|
||
color: #04301e;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* 推荐标签列表 */
|
||
.create__recommend-tags {
|
||
margin-top: 20rpx;
|
||
padding: 18rpx 20rpx;
|
||
background: #f8fbf9;
|
||
border-radius: 16rpx;
|
||
border: 1rpx dashed #d8eee0;
|
||
}
|
||
|
||
.create__recommend-title {
|
||
font-size: 22rpx;
|
||
color: #04874a;
|
||
font-weight: 600;
|
||
display: block;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.create__recommend-chips {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.create__recommend-chip {
|
||
font-size: 22rpx;
|
||
color: #04874a;
|
||
background: #ffffff;
|
||
border: 1rpx solid #cbe9d5;
|
||
border-radius: 24rpx;
|
||
padding: 6rpx 18rpx;
|
||
cursor: pointer;
|
||
transition: all 0.15s ease;
|
||
|
||
&--disabled {
|
||
opacity: 0.45;
|
||
background: #f0f4f1;
|
||
border-color: #dbe4df;
|
||
color: $fc-text-placeholder;
|
||
pointer-events: none;
|
||
}
|
||
}
|
||
|
||
/* 自定义亮点标签输入行 */
|
||
.create__tag-custom-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 16rpx;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.create__tag-custom-input {
|
||
flex: 1;
|
||
height: 72rpx;
|
||
background: #f8faf8;
|
||
border-radius: 14rpx;
|
||
border: 1rpx solid #e6f0ea;
|
||
padding: 0 20rpx;
|
||
font-size: 24rpx;
|
||
color: $fc-text;
|
||
}
|
||
|
||
.create__tag-custom-btn {
|
||
height: 72rpx;
|
||
padding: 0 28rpx;
|
||
background: #04874a;
|
||
border-radius: 14rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.create__tag-custom-btn-txt {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
}
|
||
|
||
/* 联系信息行 */
|
||
.create__row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 96rpx;
|
||
|
||
&--line {
|
||
border-top: 1rpx solid #f2f6f3;
|
||
}
|
||
}
|
||
|
||
.create__row-label {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: $fc-text;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.create__area-picker {
|
||
flex: 1;
|
||
margin-left: 16rpx;
|
||
}
|
||
.create__location {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
flex: 1;
|
||
max-width: 500rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.create__location-text {
|
||
font-size: 26rpx;
|
||
color: $fc-text-sub;
|
||
margin: 0 8rpx;
|
||
}
|
||
|
||
.create__location-arrow {
|
||
font-size: 32rpx;
|
||
color: #b5c7bc;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* 发布套餐与计费 */
|
||
.create__free-tip {
|
||
background: rgba(0, 224, 112, 0.1);
|
||
border: 1rpx solid rgba(0, 224, 112, 0.25);
|
||
border-radius: 14rpx;
|
||
padding: 20rpx;
|
||
font-size: 24rpx;
|
||
color: #04874a;
|
||
text-align: center;
|
||
}
|
||
|
||
.create__quota {
|
||
font-size: 22rpx;
|
||
color: #f5a623;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.create__plans {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.create__plan {
|
||
border: 2rpx solid #e2eee6;
|
||
background: #f8fbf9;
|
||
border-radius: 18rpx;
|
||
padding: 20rpx;
|
||
position: relative;
|
||
cursor: pointer;
|
||
transition: all 0.2s ease;
|
||
|
||
&--active {
|
||
border-color: #00e070;
|
||
background: #edfbf3;
|
||
|
||
.create__plan-name {
|
||
color: #04874a;
|
||
}
|
||
|
||
.create__plan-price {
|
||
color: #04301e;
|
||
}
|
||
}
|
||
}
|
||
|
||
.create__plan-name {
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
display: block;
|
||
}
|
||
|
||
.create__plan-price {
|
||
font-size: 32rpx;
|
||
font-weight: 800;
|
||
color: $fc-text;
|
||
margin: 8rpx 0;
|
||
display: block;
|
||
}
|
||
|
||
.create__plan-desc {
|
||
font-size: 20rpx;
|
||
color: $fc-text-placeholder;
|
||
display: block;
|
||
}
|
||
|
||
.create__plan-tag {
|
||
position: absolute;
|
||
top: -12rpx;
|
||
right: 14rpx;
|
||
background: #ff5252;
|
||
color: #ffffff;
|
||
font-size: 18rpx;
|
||
font-weight: 700;
|
||
padding: 2rpx 10rpx;
|
||
border-radius: 8rpx;
|
||
}
|
||
|
||
/* 支付方式 */
|
||
.create__pay {
|
||
margin-top: 24rpx;
|
||
padding-top: 24rpx;
|
||
border-top: 1rpx solid #f2f6f3;
|
||
}
|
||
|
||
.create__pay-label {
|
||
font-size: 26rpx;
|
||
font-weight: 600;
|
||
color: $fc-text;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
}
|
||
|
||
.create__pay-types {
|
||
display: flex;
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.create__pay-type {
|
||
flex: 1;
|
||
height: 84rpx;
|
||
border-radius: 16rpx;
|
||
border: 1rpx solid #e2eee6;
|
||
background: #f8faf8;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
cursor: pointer;
|
||
|
||
&--active {
|
||
border-color: #00e070;
|
||
background: #ebfaf0;
|
||
|
||
.create__pay-text {
|
||
color: #04874a;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
}
|
||
|
||
.create__pay-text {
|
||
font-size: 24rpx;
|
||
color: $fc-text;
|
||
}
|
||
|
||
/* 底部主控操作条 */
|
||
.create__bar {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 90;
|
||
background: #ffffff;
|
||
border-top: 1rpx solid #e8f0eb;
|
||
padding: 18rpx 32rpx calc(18rpx + env(safe-area-inset-bottom));
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.create__bar-draft {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 16rpx;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.create__bar-draft-icon {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
opacity: 0.7;
|
||
}
|
||
|
||
.create__bar-draft-txt {
|
||
font-size: 20rpx;
|
||
color: $fc-text-sub;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.create__bar-submit {
|
||
flex: 1;
|
||
height: 92rpx;
|
||
border-radius: 46rpx;
|
||
background: linear-gradient(135deg, #00e070 0%, #00c860 100%);
|
||
box-shadow: 0 8rpx 24rpx rgba(0, 224, 112, 0.3);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
transition: opacity 0.15s ease, transform 0.15s ease;
|
||
|
||
&:active {
|
||
transform: scale(0.985);
|
||
}
|
||
|
||
&--disabled {
|
||
opacity: 0.55;
|
||
pointer-events: none;
|
||
}
|
||
}
|
||
|
||
.create__bar-submit-txt {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #04301e; /* 遵守春绿规范:亮绿上必须深墨绿 */
|
||
letter-spacing: 1rpx;
|
||
}
|
||
|
||
/* ================= 全部分类抽屉弹窗 ================= */
|
||
.cat-drawer-mask {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
z-index: 999;
|
||
background: rgba(0, 0, 0, 0);
|
||
transition: background-color 0.2s ease;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: flex-end;
|
||
|
||
&--visible {
|
||
background: rgba(0, 0, 0, 0.5);
|
||
}
|
||
}
|
||
|
||
.cat-drawer {
|
||
background: #ffffff;
|
||
border-radius: 36rpx 36rpx 0 0;
|
||
max-height: 75vh;
|
||
display: flex;
|
||
flex-direction: column;
|
||
transform: translateY(100%);
|
||
transition: transform 0.22s ease-out;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
|
||
&--visible {
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
|
||
.cat-drawer__header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 32rpx 36rpx 20rpx;
|
||
border-bottom: 1rpx solid #f0f4f2;
|
||
}
|
||
|
||
.cat-drawer__title {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: $fc-text;
|
||
}
|
||
|
||
.cat-drawer__close {
|
||
width: 54rpx;
|
||
height: 54rpx;
|
||
border-radius: 50%;
|
||
background: #f2f6f4;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.cat-drawer__close-txt {
|
||
font-size: 24rpx;
|
||
color: #8c9e94;
|
||
line-height: 1;
|
||
}
|
||
|
||
.cat-drawer__body {
|
||
max-height: 60vh;
|
||
padding: 24rpx 32rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.cat-drawer__grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(3, 1fr);
|
||
gap: 20rpx;
|
||
}
|
||
|
||
.cat-drawer__item {
|
||
background: #f7faf8;
|
||
border: 2rpx solid #e7efe9;
|
||
border-radius: 20rpx;
|
||
padding: 24rpx 16rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
transition: all 0.15s ease;
|
||
cursor: pointer;
|
||
|
||
&--active {
|
||
border-color: #00e070;
|
||
background: #ebfaf0;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 224, 112, 0.2);
|
||
|
||
.cat-drawer__name {
|
||
color: #04874a;
|
||
font-weight: 700;
|
||
}
|
||
}
|
||
}
|
||
|
||
.cat-drawer__icon-box {
|
||
width: 72rpx;
|
||
height: 72rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.cat-drawer__icon {
|
||
width: 60rpx;
|
||
height: 60rpx;
|
||
}
|
||
|
||
.cat-drawer__name {
|
||
font-size: 26rpx;
|
||
color: $fc-text;
|
||
text-align: center;
|
||
}
|
||
|
||
.cat-drawer__check {
|
||
position: absolute;
|
||
top: 8rpx;
|
||
right: 12rpx;
|
||
font-size: 22rpx;
|
||
font-weight: 900;
|
||
color: #04874a;
|
||
}
|
||
|
||
.cat-drawer__space {
|
||
height: 40rpx;
|
||
}
|
||
</style>
|