|
|
@@ -1,7 +1,705 @@
|
|
|
<template>
|
|
|
- <view>签约结算渠道</view>
|
|
|
+ <view class="settlement-page">
|
|
|
+ <view class="channel-panel">
|
|
|
+ <view class="panel-title">认证渠道</view>
|
|
|
+
|
|
|
+ <radio-group @change="handleChannelChange">
|
|
|
+ <label
|
|
|
+ v-for="channel in channelList"
|
|
|
+ :key="channel.value"
|
|
|
+ class="channel-item"
|
|
|
+ :class="{
|
|
|
+ 'channel-item--active': channel.selectable && selectedSubjectLocation === channel.value,
|
|
|
+ 'channel-item--disabled': !channel.selectable,
|
|
|
+ }"
|
|
|
+ @click="handleSelectChannel(channel)"
|
|
|
+ >
|
|
|
+ <text class="channel-name">{{ channel.label }}</text>
|
|
|
+
|
|
|
+ <radio
|
|
|
+ v-if="channel.selectable"
|
|
|
+ class="channel-radio"
|
|
|
+ :value="channel.value"
|
|
|
+ :checked="selectedSubjectLocation === channel.value"
|
|
|
+ color="#3fa3f1"
|
|
|
+ />
|
|
|
+
|
|
|
+ <text v-else class="channel-status">
|
|
|
+ {{ channel.statusText }}
|
|
|
+ </text>
|
|
|
+ </label>
|
|
|
+ </radio-group>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view v-if="showSubmit" class="submit-bar">
|
|
|
+ <button
|
|
|
+ class="submit-button"
|
|
|
+ :class="{ 'submit-button--disabled': !canSubmit }"
|
|
|
+ :disabled="!canSubmit"
|
|
|
+ hover-class="none"
|
|
|
+ @click="handleSubmit"
|
|
|
+ >
|
|
|
+ {{ isSubmitting ? '提交中...' : '提交' }}
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <wd-popup
|
|
|
+ v-model="agreementPopupVisible"
|
|
|
+ position="center"
|
|
|
+ custom-style="width: 640rpx; border-radius: 24rpx; overflow: hidden;"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ @close="handleCloseAgreementPopup"
|
|
|
+ >
|
|
|
+ <view class="agreement-popup">
|
|
|
+ <view class="agreement-title">业务合作协议</view>
|
|
|
+
|
|
|
+ <scroll-view scroll-y class="agreement-scroll">
|
|
|
+ <view class="agreement-policy">
|
|
|
+ 为开通共享经济业务,请阅读、勾选签署以下平台业务合作协议。
|
|
|
+ 点击勾选协议,即表示您已阅读并同意接受该协议内容。若不同意,请勿勾选。
|
|
|
+ </view>
|
|
|
+ </scroll-view>
|
|
|
+
|
|
|
+ <view class="agreement-check-row">
|
|
|
+ <wd-checkbox v-model="agreementChecked" shape="square" checked-color="#3fa3f1" />
|
|
|
+
|
|
|
+ <view class="agreement-check-content">
|
|
|
+ <text>已阅读并同意</text>
|
|
|
+
|
|
|
+ <template v-for="(agreement, index) in agreementList" :key="agreement.templateUrl">
|
|
|
+ <text class="agreement-link" @click.stop="handlePreviewAgreementPdf(agreement)">
|
|
|
+ 《{{ agreement.name }}》
|
|
|
+ </text>
|
|
|
+
|
|
|
+ <text v-if="index < agreementList.length - 1">、</text>
|
|
|
+ </template>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+
|
|
|
+ <view class="agreement-actions">
|
|
|
+ <button
|
|
|
+ class="agreement-action agreement-action--cancel"
|
|
|
+ hover-class="none"
|
|
|
+ @click="handleCloseAgreementPopup"
|
|
|
+ >
|
|
|
+ 退出
|
|
|
+ </button>
|
|
|
+
|
|
|
+ <button
|
|
|
+ class="agreement-action agreement-action--confirm"
|
|
|
+ hover-class="none"
|
|
|
+ @click="handleConfirmAgreement"
|
|
|
+ >
|
|
|
+ 同意
|
|
|
+ </button>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </wd-popup>
|
|
|
+ </view>
|
|
|
</template>
|
|
|
|
|
|
-<script setup lang="ts"></script>
|
|
|
+<script setup lang="ts">
|
|
|
+import { computed, ref } from 'vue'
|
|
|
+
|
|
|
+import { onLoad } from '@dcloudio/uni-app'
|
|
|
+
|
|
|
+import {
|
|
|
+ batchChannelCertApi,
|
|
|
+ saveBaseInfoApi,
|
|
|
+ signAgreementApi,
|
|
|
+ signCertApi,
|
|
|
+ signRedirectApi,
|
|
|
+} from '@/services/modules/auth'
|
|
|
+import { getDictTypeApi } from '@/services/modules/common'
|
|
|
+import type { DictItem } from '@/services/modules/common/type'
|
|
|
+import type { CertItem } from '@/services/modules/login/userInfo'
|
|
|
+import { getSubjectLocationAgreementApi } from '@/services/modules/mine/common'
|
|
|
+import type { agreementInfosItem } from '@/services/modules/mine/common/type'
|
|
|
+
|
|
|
+import { useSettlementSignStore } from '@/stores/modules/settlementSign'
|
|
|
+import { useUserStore } from '@/stores/modules/user'
|
|
|
+
|
|
|
+import { previewAgreementPdf } from '@/utils/agreementPdfPreview'
|
|
|
+
|
|
|
+const settlementSignStore = useSettlementSignStore()
|
|
|
+interface RadioChangeEvent {
|
|
|
+ detail: {
|
|
|
+ value: string
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+interface ChannelItem {
|
|
|
+ value: string
|
|
|
+ label: string
|
|
|
+ selectable: boolean
|
|
|
+ statusText: string
|
|
|
+}
|
|
|
+
|
|
|
+interface AgreementPdfItem {
|
|
|
+ name: string
|
|
|
+ templateUrl: string
|
|
|
+}
|
|
|
+
|
|
|
+const SELECTABLE_CERT_STATUS = new Set(['UN_SIGN', 'FAIL_SIGN'])
|
|
|
+
|
|
|
+const userStore = useUserStore()
|
|
|
+
|
|
|
+const subjectLocationDictList = ref<DictItem[]>([])
|
|
|
+const selectedSubjectLocation = ref('')
|
|
|
+const isSubmitting = ref(false)
|
|
|
+
|
|
|
+const agreementList = ref<AgreementPdfItem[]>([])
|
|
|
+const agreementPopupVisible = ref(false)
|
|
|
+const agreementChecked = ref(false)
|
|
|
+
|
|
|
+const currentUserInfo = computed(() => userStore.currentUserInfo)
|
|
|
+
|
|
|
+const subjectLocationList = computed(() => {
|
|
|
+ return currentUserInfo.value?.subjectLocationList ?? []
|
|
|
+})
|
|
|
+
|
|
|
+const certList = computed(() => {
|
|
|
+ return currentUserInfo.value?.certList ?? []
|
|
|
+})
|
|
|
+
|
|
|
+const channelList = computed<ChannelItem[]>(() => {
|
|
|
+ return subjectLocationList.value.map((subjectLocation) => {
|
|
|
+ const certItem = findCertItem(subjectLocation)
|
|
|
+ const selectable = isSelectableChannel(certItem)
|
|
|
+
|
|
|
+ return {
|
|
|
+ value: subjectLocation,
|
|
|
+ label: getSubjectLocationName(subjectLocation),
|
|
|
+ selectable,
|
|
|
+ statusText: selectable ? '' : getCertStatusText(certItem),
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+const selectedChannel = computed(() => {
|
|
|
+ return channelList.value.find((channel) => {
|
|
|
+ return channel.value === selectedSubjectLocation.value
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+const showSubmit = computed(() => {
|
|
|
+ return channelList.value.some((channel) => channel.selectable)
|
|
|
+})
|
|
|
+
|
|
|
+const canSubmit = computed(() => {
|
|
|
+ return Boolean(selectedChannel.value?.selectable) && !isSubmitting.value
|
|
|
+})
|
|
|
+
|
|
|
+const showToast = (title: string): void => {
|
|
|
+ uni.showToast({
|
|
|
+ title,
|
|
|
+ icon: 'none',
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const getSubjectLocationDict = async (): Promise<void> => {
|
|
|
+ try {
|
|
|
+ const res = await getDictTypeApi('subject_location?filterData=false')
|
|
|
+ subjectLocationDictList.value = res.data ?? []
|
|
|
+ } catch (error) {
|
|
|
+ console.log('getSubjectLocationDict error:', error)
|
|
|
+ subjectLocationDictList.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const getSubjectLocationName = (value: string): string => {
|
|
|
+ const dictItem = subjectLocationDictList.value.find((item) => {
|
|
|
+ return String(item.value) === value
|
|
|
+ })
|
|
|
+
|
|
|
+ return dictItem?.label || value
|
|
|
+}
|
|
|
+
|
|
|
+const findCertItem = (subjectLocation: string): CertItem | undefined => {
|
|
|
+ return certList.value.find((item) => {
|
|
|
+ return item.subjectLocation === subjectLocation
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const isSelectableChannel = (certItem?: CertItem): boolean => {
|
|
|
+ if (!certItem) return true
|
|
|
+
|
|
|
+ return SELECTABLE_CERT_STATUS.has(certItem.commonCertStatus ?? '')
|
|
|
+}
|
|
|
+
|
|
|
+const getCertStatusText = (certItem?: CertItem): string => {
|
|
|
+ return certItem?.commonCertStatusName || '已提交'
|
|
|
+}
|
|
|
+
|
|
|
+const handleSelectChannel = (channel: ChannelItem): void => {
|
|
|
+ if (!channel.selectable) return
|
|
|
+
|
|
|
+ selectedSubjectLocation.value = channel.value
|
|
|
+}
|
|
|
+
|
|
|
+const handleChannelChange = (event: RadioChangeEvent): void => {
|
|
|
+ selectedSubjectLocation.value = event.detail.value
|
|
|
+}
|
|
|
+
|
|
|
+const normalizeAgreementInfos = (list: agreementInfosItem[] = []): AgreementPdfItem[] => {
|
|
|
+ return list
|
|
|
+ .filter((item) => Boolean(item.templateUrl?.trim()))
|
|
|
+ .map((item) => {
|
|
|
+ return {
|
|
|
+ name: item.name?.trim() || '协议',
|
|
|
+ templateUrl: item.templateUrl.trim(),
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const handleSubmit = async (): Promise<void> => {
|
|
|
+ if (!canSubmit.value) {
|
|
|
+ showToast('请选择认证渠道')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ agreementList.value = []
|
|
|
+ isSubmitting.value = true
|
|
|
+
|
|
|
+ try {
|
|
|
+ const saved = await saveBaseInfo()
|
|
|
+
|
|
|
+ if (!saved) return
|
|
|
+
|
|
|
+ await signCert()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('handleSubmit error:', error)
|
|
|
+ showToast('提交失败,请稍后重试')
|
|
|
+ } finally {
|
|
|
+ isSubmitting.value = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const saveBaseInfo = async (): Promise<boolean> => {
|
|
|
+ const data = {
|
|
|
+ userId: currentUserInfo.value?.userId || '',
|
|
|
+ idCardNumber: currentUserInfo.value?.idCardNumber || '',
|
|
|
+ bankCardNumber: currentUserInfo.value?.bankCardNumber || '',
|
|
|
+ bankName: currentUserInfo.value?.bankName || '',
|
|
|
+ bankPhone: currentUserInfo.value?.bankPhone || '',
|
|
|
+ subjectLocation: selectedSubjectLocation.value,
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await saveBaseInfoApi(data)
|
|
|
+
|
|
|
+ if (res.code !== 0) {
|
|
|
+ showToast(res.msg || '保存信息失败')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ return true
|
|
|
+}
|
|
|
+
|
|
|
+const signCert = async (): Promise<void> => {
|
|
|
+ const data = {
|
|
|
+ userId: currentUserInfo.value?.userId || '',
|
|
|
+ subjectLocation: selectedSubjectLocation.value,
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await signCertApi(data)
|
|
|
+
|
|
|
+ if (res.code !== 0) {
|
|
|
+ showToast(res.msg || '签约失败')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ await afterSignCert()
|
|
|
+}
|
|
|
+
|
|
|
+// 判断是否是有感签约
|
|
|
+const isExternal = computed(() => {
|
|
|
+ const externalValueArr = ['BOSS_KG_YJB', 'OSAIS']
|
|
|
+ const currentGigItem = subjectLocationDictList.value.find(
|
|
|
+ (item) => item.value === selectedSubjectLocation.value
|
|
|
+ )
|
|
|
+ return externalValueArr.includes(currentGigItem?.externalValue || '')
|
|
|
+})
|
|
|
+
|
|
|
+const afterSignCert = async (): Promise<void> => {
|
|
|
+ if (selectedSubjectLocation.value === 'FESCO') {
|
|
|
+ uni.navigateTo({
|
|
|
+ url: '/pages-auth/fesco/index',
|
|
|
+ })
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const currentCert = findCertItem(selectedSubjectLocation.value)
|
|
|
+
|
|
|
+ const shouldLoadAgreement =
|
|
|
+ (!certList.value.length ||
|
|
|
+ !currentCert ||
|
|
|
+ !currentCert.agreementUrl ||
|
|
|
+ currentCert.commonCertStatus === 'FAIL_SIGN') &&
|
|
|
+ !isExternal.value
|
|
|
+
|
|
|
+ if (shouldLoadAgreement) {
|
|
|
+ await getSubjectLocationAgreement()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ certFn()
|
|
|
+}
|
|
|
+
|
|
|
+const getSubjectLocationAgreement = async (): Promise<void> => {
|
|
|
+ try {
|
|
|
+ const res = await getSubjectLocationAgreementApi({
|
|
|
+ subjectLocation: selectedSubjectLocation.value,
|
|
|
+ })
|
|
|
+
|
|
|
+ agreementList.value = normalizeAgreementInfos(res.data?.agreementInfos)
|
|
|
+
|
|
|
+ showAgreementPopupIfNeeded()
|
|
|
+ } catch (error) {
|
|
|
+ console.error('getSubjectLocationAgreement error:', error)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const showAgreementPopupIfNeeded = (): void => {
|
|
|
+ agreementChecked.value = false
|
|
|
+ if (agreementList.value.length) {
|
|
|
+ agreementPopupVisible.value = true
|
|
|
+ return
|
|
|
+ }
|
|
|
+ certFn()
|
|
|
+}
|
|
|
+
|
|
|
+const handleCloseAgreementPopup = (): void => {
|
|
|
+ agreementChecked.value = false
|
|
|
+ agreementPopupVisible.value = false
|
|
|
+}
|
|
|
+
|
|
|
+interface SignatureSuccessPayload {
|
|
|
+ signatureUrl: string
|
|
|
+}
|
|
|
+
|
|
|
+const handleConfirmAgreement = () => {
|
|
|
+ if (!agreementChecked.value) {
|
|
|
+ showToast('请先勾选相关协议')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ agreementChecked.value = false
|
|
|
+ agreementPopupVisible.value = false
|
|
|
+
|
|
|
+ // 有感签约下 直接去认证
|
|
|
+ if (isExternal.value) {
|
|
|
+ certFn()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages-common/signature/index?type=SETTLEMENT_CHANNEL_SIGN`,
|
|
|
+ events: {
|
|
|
+ authSuccess: handleSignatureSuccess,
|
|
|
+ },
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const handleSignatureSuccess = async (payload: SignatureSuccessPayload) => {
|
|
|
+ const signatureUrl = payload.signatureUrl?.trim()
|
|
|
+
|
|
|
+ if (!signatureUrl) {
|
|
|
+ showToast('签名地址为空')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const obj = {
|
|
|
+ userId: currentUserInfo.value?.userId || '',
|
|
|
+ subjectLocation: selectedSubjectLocation.value,
|
|
|
+ agreementUrl: signatureUrl,
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await signAgreementApi(obj)
|
|
|
+ if (res.code === 0) {
|
|
|
+ certFn()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const handlePreviewAgreementPdf = (agreement: AgreementPdfItem): void => {
|
|
|
+ void previewAgreementPdf({
|
|
|
+ url: agreement.templateUrl,
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+const certFn = async () => {
|
|
|
+ const subjectLocation = selectedSubjectLocation.value
|
|
|
+
|
|
|
+ if (!subjectLocation) {
|
|
|
+ showToast('请选择认证渠道')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const accountInfo = wx.getAccountInfoSync()
|
|
|
+ const appId = accountInfo.miniProgram.appId
|
|
|
+
|
|
|
+ const signRedirectUrl = `/pages-auth/settlement-channel-sign/index?subjectLocationByUrl=${encodeURIComponent(
|
|
|
+ subjectLocation
|
|
|
+ )}`
|
|
|
+
|
|
|
+ const data = {
|
|
|
+ userId: currentUserInfo.value?.userId || '',
|
|
|
+ subjectLocation,
|
|
|
+ token: currentUserInfo.value?.certToken || '',
|
|
|
+ signRedirectUrl,
|
|
|
+ wxMiniAppId: appId,
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await batchChannelCertApi(data)
|
|
|
+
|
|
|
+ if (res.code !== 0) {
|
|
|
+ showToast(res.msg || '签约失败')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const h5SignUrl = res.data?.h5SignUrl
|
|
|
+
|
|
|
+ if (h5SignUrl) {
|
|
|
+ const context = settlementSignStore.createContext(subjectLocation)
|
|
|
+
|
|
|
+ uni.navigateTo({
|
|
|
+ url: `/pages-auth/web-view/index?url=${encodeURIComponent(
|
|
|
+ h5SignUrl
|
|
|
+ )}&subjectLocation=${encodeURIComponent(
|
|
|
+ subjectLocation
|
|
|
+ )}&signTraceId=${encodeURIComponent(context.signTraceId)}`,
|
|
|
+ })
|
|
|
+
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ settlementSignStore.clearContext()
|
|
|
+
|
|
|
+ uni.showToast({
|
|
|
+ title: '签约成功',
|
|
|
+ icon: 'success',
|
|
|
+ duration: 2000,
|
|
|
+ })
|
|
|
+
|
|
|
+ await userStore.getUserInfoByCode()
|
|
|
+}
|
|
|
+
|
|
|
+const signRedirect = async (subjectLocation: string): Promise<boolean> => {
|
|
|
+ if (!subjectLocation) {
|
|
|
+ showToast('参数异常')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ const res = await signRedirectApi({
|
|
|
+ subjectLocation,
|
|
|
+ })
|
|
|
+ if (res.code !== 0) {
|
|
|
+ showToast(res.msg || '签约失败')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
+ settlementSignStore.clearContext()
|
|
|
+ uni.showToast({
|
|
|
+ title: '签约成功',
|
|
|
+ icon: 'success',
|
|
|
+ })
|
|
|
+ await userStore.getUserInfoByCode()
|
|
|
+ return true
|
|
|
+ } catch (error) {
|
|
|
+ console.error('signRedirect error:', error)
|
|
|
+ showToast('网络异常,请稍后重试')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onLoad(async (query) => {
|
|
|
+ await userStore.getUserInfoByCode()
|
|
|
+ const subjectLocation = query?.subjectLocationByUrl?.trim() || ''
|
|
|
+
|
|
|
+ if (subjectLocation) {
|
|
|
+ await signRedirect(subjectLocation)
|
|
|
+ }
|
|
|
+
|
|
|
+ getSubjectLocationDict()
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.settlement-page {
|
|
|
+ min-height: 100vh;
|
|
|
+ padding-bottom: 132rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: #f5f6f8;
|
|
|
+}
|
|
|
+
|
|
|
+.channel-panel {
|
|
|
+ margin: 24rpx;
|
|
|
+ padding: 32rpx 28rpx 8rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-radius: 20rpx;
|
|
|
+ background: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.panel-title {
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+ font-size: 34rpx;
|
|
|
+ line-height: 48rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #1f2329;
|
|
|
+}
|
|
|
+
|
|
|
+.channel-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ min-height: 96rpx;
|
|
|
+ border-bottom: 1rpx solid #edf0f5;
|
|
|
+}
|
|
|
+
|
|
|
+.channel-item:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+}
|
|
|
+
|
|
|
+.channel-item--active {
|
|
|
+ .channel-name {
|
|
|
+ color: #3fa3f1;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.channel-item--disabled {
|
|
|
+ .channel-name {
|
|
|
+ color: #4e5969;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.channel-name {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ padding-right: 24rpx;
|
|
|
+ font-size: 30rpx;
|
|
|
+ line-height: 42rpx;
|
|
|
+ color: #333333;
|
|
|
+}
|
|
|
+
|
|
|
+.channel-radio {
|
|
|
+ flex-shrink: 0;
|
|
|
+ transform: scale(0.82);
|
|
|
+}
|
|
|
+
|
|
|
+.channel-status {
|
|
|
+ flex-shrink: 0;
|
|
|
+ max-width: 180rpx;
|
|
|
+ padding: 6rpx 18rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+ font-size: 24rpx;
|
|
|
+ line-height: 34rpx;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.submit-bar {
|
|
|
+ position: fixed;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ left: 0;
|
|
|
+ z-index: 1;
|
|
|
+ padding: 18rpx 32rpx calc(18rpx + env(safe-area-inset-bottom));
|
|
|
+ box-sizing: border-box;
|
|
|
+ background: #ffffff;
|
|
|
+ box-shadow: 0 -6rpx 20rpx rgba(0, 0, 0, 0.04);
|
|
|
+}
|
|
|
+
|
|
|
+.submit-button {
|
|
|
+ width: 100%;
|
|
|
+ height: 84rpx;
|
|
|
+ padding: 0;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ line-height: 84rpx;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ background: #3fa3f1;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.submit-button--disabled {
|
|
|
+ color: #ffffff;
|
|
|
+ background: #c7d7ea;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-popup {
|
|
|
+ background: #ffffff;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-title {
|
|
|
+ padding: 32rpx 32rpx 20rpx;
|
|
|
+ font-size: 32rpx;
|
|
|
+ line-height: 44rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ text-align: center;
|
|
|
+ color: #1f2329;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-scroll {
|
|
|
+ min-height: 200rpx;
|
|
|
+ padding: 0 32rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-policy {
|
|
|
+ font-size: 28rpx;
|
|
|
+ line-height: 44rpx;
|
|
|
+ color: #4e5969;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-check-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: flex-start;
|
|
|
+ padding: 24rpx 32rpx 28rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-check-content {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ margin-left: 12rpx;
|
|
|
+ font-size: 24rpx;
|
|
|
+ line-height: 38rpx;
|
|
|
+ color: #4e5969;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-link {
|
|
|
+ color: #3fa3f1;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-actions {
|
|
|
+ display: flex;
|
|
|
+ border-top: 1rpx solid #edf0f5;
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-action {
|
|
|
+ flex: 1;
|
|
|
+ height: 88rpx;
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+ border-radius: 0;
|
|
|
+ font-size: 30rpx;
|
|
|
+ line-height: 88rpx;
|
|
|
+ background: #ffffff;
|
|
|
+
|
|
|
+ &::after {
|
|
|
+ border: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.agreement-action--cancel {
|
|
|
+ color: #86909c;
|
|
|
+ border-right: 1rpx solid #edf0f5;
|
|
|
+}
|
|
|
|
|
|
-<style lang="scss" scoped></style>
|
|
|
+.agreement-action--confirm {
|
|
|
+ color: #3fa3f1;
|
|
|
+ font-weight: 500;
|
|
|
+}
|
|
|
+</style>
|