| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- <template>
- <view class="entry-apply-wrap">
- <safe-nav-bar title="商家入驻" />
- <view class="entry-apply-page">
- <view v-if="!entryOpen" class="entry-closed">
- <text>{{ agreement.message || '商家入驻暂未开放' }}</text>
- </view>
- <view v-else-if="blocked" class="entry-closed">
- <text>您有待审核或公示中的申请,请先在「我的入驻申请」查看进度</text>
- <button class="mine-btn-outline entry-closed__btn" @click="goList">查看申请</button>
- </view>
- <template v-else>
- <view class="entry-steps">
- <text
- v-for="(s, i) in stepTitles"
- :key="s"
- :class="['entry-steps__item', { 'entry-steps__item--on': stepIndex === i }]"
- >{{ s }}</text>
- </view>
- <scroll-view class="entry-scroll" scroll-y>
- <!-- 主体类型 -->
- <view v-if="currentStep === 'type'" class="form-card">
- <view
- :class="['type-card', { 'type-card--on': form.merchantType === '1' }]"
- @click="selectType('1')"
- >
- <text class="type-card__title">个人入驻</text>
- <text class="type-card__sub">身份证 + 个人账户</text>
- </view>
- <view
- :class="['type-card', { 'type-card--on': form.merchantType === '2' }]"
- @click="selectType('2')"
- >
- <text class="type-card__title">企业入驻</text>
- <text class="type-card__sub">法人 + 企业对公账户</text>
- </view>
- </view>
- <!-- 个人:主体信息 -->
- <view v-else-if="isPerson && currentStep === 'subject'" class="form-card">
- <entry-person-subject :subject="form.subject" />
- </view>
- <view v-else-if="isPerson && currentStep === 'biz'" class="form-card">
- <entry-person-biz :biz="form.biz" :region="regionBiz" @update:region="onBizRegion" />
- </view>
- <!-- 企业 -->
- <view v-else-if="!isPerson && currentStep === 'subject'" class="form-card">
- <entry-enterprise-subject
- :subject="form.subject"
- :region-reg="regionReg"
- @update:region-reg="onRegRegion"
- />
- </view>
- <view v-else-if="!isPerson && currentStep === 'biz'" class="form-card">
- <entry-enterprise-biz :biz="form.biz" :region="regionBiz" @update:region="onBizRegion" />
- </view>
- <!-- 店铺 -->
- <view v-else-if="currentStep === 'shop'" class="form-card">
- <entry-shop-fields :shop="form.shop" />
- </view>
- <!-- 提交 -->
- <view v-else-if="currentStep === 'submit'" class="form-card">
- <text class="submit-tip">请确认信息无误后勾选协议并提交</text>
- <agreement-block
- v-model="form.agreementAccepted"
- :enabled="agreement.enabled"
- :checkbox-label="agreement.checkboxLabel"
- :agreement-title="agreement.agreementTitle"
- :version-label="agreement.versionLabel"
- :content="agreement.content"
- />
- </view>
- </scroll-view>
- <view class="entry-actions">
- <button v-if="stepIndex > 0" class="mine-btn-outline entry-actions__prev" @click="prevStep">
- 上一步
- </button>
- <button class="form-footer__btn entry-actions__next" :disabled="submitting" @click="nextStep">
- {{ nextBtnText }}
- </button>
- </view>
- </template>
- </view>
- </view>
- </template>
- <script setup>
- import { ref, reactive, computed } from 'vue'
- import SafeNavBar from '@/components/common/SafeNavBar.vue'
- import { onLoad } from '@dcloudio/uni-app'
- import { getEntryAgreement, getEntryStatus, getMyEntryApplies, submitEntryApply } from '@/api/merchantEntry'
- import { ensureApiToken } from '@/utils/apiAuth'
- import { hasBlockingApply } from '@/utils/entryConstants'
- import { createEntryForm, validateEntryStep, buildEntrySubmitPayload, applyRegion, applyRegRegion } from '@/utils/entryForm'
- import { MERCHANT_TYPE_PERSON } from '@/utils/entryConstants'
- import AgreementBlock from '@/components/account/AgreementBlock.vue'
- import EntryPersonSubject from '@/components/mine/entry/EntryPersonSubject.vue'
- import EntryPersonBiz from '@/components/mine/entry/EntryPersonBiz.vue'
- import EntryEnterpriseSubject from '@/components/mine/entry/EntryEnterpriseSubject.vue'
- import EntryEnterpriseBiz from '@/components/mine/entry/EntryEnterpriseBiz.vue'
- import EntryShopFields from '@/components/mine/entry/EntryShopFields.vue'
- import { PAGE_ENTRY_LIST, PAGE_PROFILE } from '@/utils/pageRoute'
- import { useUserStore } from '@/store/user'
- import { useActionGuard } from '@/utils/actionGuard'
- const submitGuard = useActionGuard()
- const submitting = submitGuard.locked
- const form = reactive(createEntryForm(MERCHANT_TYPE_PERSON))
- const agreement = reactive({
- enabled: false,
- message: '',
- agreementTitle: '',
- versionLabel: '',
- content: '',
- checkboxLabel: '我已阅读并同意《商城入驻协议》'
- })
- const stepIndex = ref(0)
- const entryOpen = ref(true)
- const blocked = ref(false)
- const regionBiz = ref({ regionCode: '', regionName: '', pathCodes: [] })
- const regionReg = ref({ regionCode: '', regionName: '', pathCodes: [] })
- const userStore = useUserStore()
- const stepKeys = computed(() => ['type', 'subject', 'biz', 'shop', 'submit'])
- const stepTitles = ['类型', '主体', '经营', '店铺', '提交']
- const currentStep = computed(() => stepKeys.value[stepIndex.value])
- const isPerson = computed(() => form.merchantType === MERCHANT_TYPE_PERSON)
- const nextBtnText = computed(() => {
- if (submitting.value) return '提交中…'
- return currentStep.value === 'submit' ? '提交申请' : '下一步'
- })
- onLoad(() => {
- if (!ensureApiToken()) return
- initPage()
- })
- function initPage() {
- Promise.all([getEntryAgreement(), getEntryStatus(), getMyEntryApplies()])
- .then(([agRes, stRes, myRes]) => {
- const ag = agRes.data || {}
- agreement.enabled = !!ag.enabled
- agreement.message = ag.message || ''
- agreement.agreementTitle = ag.agreementTitle || '商城入驻协议'
- agreement.versionLabel = ag.versionLabel || ''
- agreement.content = ag.content || ''
- agreement.checkboxLabel = ag.checkboxLabel || agreement.checkboxLabel
- entryOpen.value = stRes.data?.entryOpen !== false && agreement.enabled
- blocked.value = hasBlockingApply(myRes.data || [])
- if (entryOpen.value && !blocked.value) {
- ensureMemberNickName()
- }
- })
- .catch(() => {})
- }
- /** 入驻须会员昵称非空(经营账号登录名) */
- function ensureMemberNickName() {
- const cached = (userStore.state.nickName || '').trim()
- if (cached) return Promise.resolve(true)
- return userStore.fetchUserInfo().then(() => {
- const nick = (userStore.state.nickName || '').trim()
- if (nick) return true
- uni.showModal({
- title: '提示',
- content: '请先完善个人资料中的昵称,方可提交入驻申请',
- confirmText: '去完善',
- success: (r) => {
- if (r.confirm) uni.navigateTo({ url: PAGE_PROFILE })
- }
- })
- return false
- })
- .catch(() => false)
- }
- function selectType(type) {
- form.merchantType = type
- const next = createEntryForm(type)
- form.subject = next.subject
- form.biz = next.biz
- form.shop = next.shop
- form.agreementAccepted = false
- regionBiz.value = { regionCode: '', regionName: '', pathCodes: [] }
- regionReg.value = { regionCode: '', regionName: '', pathCodes: [] }
- }
- function onBizRegion(v) {
- regionBiz.value = v
- applyRegion(form.biz, v)
- }
- function onRegRegion(v) {
- regionReg.value = v
- applyRegRegion(form.subject, v)
- }
- function prevStep() {
- if (stepIndex.value > 0) stepIndex.value -= 1
- }
- function nextStep() {
- const key = currentStep.value
- const err = validateEntryStep(form, key)
- if (err) {
- uni.showToast({ title: err, icon: 'none' })
- return
- }
- if (key === 'submit') {
- doSubmit()
- return
- }
- if (stepIndex.value < stepKeys.value.length - 1) {
- stepIndex.value += 1
- }
- }
- function doSubmit() {
- const nick = (userStore.state.nickName || '').trim()
- if (!nick) {
- ensureMemberNickName()
- return
- }
- uni.showModal({
- title: '确认提交',
- content: '提交后不可修改,是否确认?',
- success: (res) => {
- if (!res.confirm) return
- submitGuard.run(async () => {
- await submitEntryApply(buildEntrySubmitPayload(form))
- uni.showToast({ title: '提交成功,请等待审核', icon: 'none', duration: 2500 })
- setTimeout(() => {
- uni.redirectTo({ url: PAGE_ENTRY_LIST })
- }, 1500)
- })
- }
- })
- }
- function goList() {
- uni.navigateTo({ url: PAGE_ENTRY_LIST })
- }
- </script>
- <style lang="scss" scoped>
- @import '@/styles/mine.scss';
- .entry-apply-wrap {
- min-height: 100vh;
- display: flex;
- flex-direction: column;
- background: #f0ebe5;
- }
- .entry-apply-page {
- flex: 1;
- display: flex;
- flex-direction: column;
- min-height: 0;
- }
- .entry-closed {
- padding: 80rpx 40rpx;
- text-align: center;
- font-size: 28rpx;
- color: #666;
- }
- .entry-closed__btn {
- margin-top: 32rpx;
- width: 100%;
- }
- .entry-steps {
- display: flex;
- padding: 20rpx 16rpx;
- background: #fff;
- }
- .entry-steps__item {
- flex: 1;
- text-align: center;
- font-size: 24rpx;
- color: #999;
- }
- .entry-steps__item--on {
- color: #2e7d32;
- font-weight: 600;
- }
- .entry-scroll {
- flex: 1;
- // height: 0;
- padding: 24rpx;
- box-sizing: border-box;
- }
- .entry-actions {
- display: flex;
- gap: 20rpx;
- padding: 20rpx 24rpx;
- padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
- background: #fff;
- }
- .entry-actions__prev {
- flex: 1;
- height: 88rpx;
- line-height: 88rpx;
- }
- .entry-actions__next {
- flex: 2;
- height: 88rpx;
- line-height: 88rpx;
- }
- .type-card {
- margin-bottom: 20rpx;
- padding: 32rpx;
- border: 2rpx solid #e5ded6;
- border-radius: 16rpx;
- }
- .type-card--on {
- border-color: #2e7d32;
- background: #f1f8f4;
- }
- .type-card__title {
- display: block;
- font-size: 32rpx;
- font-weight: 600;
- color: #333;
- }
- .type-card__sub {
- display: block;
- margin-top: 8rpx;
- font-size: 24rpx;
- color: #999;
- }
- .submit-tip {
- display: block;
- padding: 16rpx 0 24rpx;
- font-size: 26rpx;
- color: #666;
- }
- </style>
|