| | |
| | | pages: [ |
| | | 'phoneBillRecharge/phoneBillRecharge', |
| | | 'electricBillRecharge/electricBillRecharge', |
| | | 'gasBillRecharge/gasBillRecharge', |
| | | 'selectPayType/selectPayType', |
| | | 'rechargeResult/rechargeResult', |
| | | 'rechargeElectricResult/rechargeElectricResult', |
| | |
| | | |
| | | phoneBillRecharge = '/subpackages/recharge/phoneBillRecharge/phoneBillRecharge', |
| | | electricBillRecharge = '/subpackages/recharge/electricBillRecharge/electricBillRecharge', |
| | | gasBillRecharge = '/subpackages/recharge/gasBillRecharge/gasBillRecharge', |
| | | order = '/subpackages/order/order/order', |
| | | selectPayType = '/subpackages/recharge/selectPayType/selectPayType', |
| | | rechargeResult = '/subpackages/recharge/rechargeResult/rechargeResult', |
| | |
| | | }); |
| | | const goGasBillRecharge = useAccessLogin(() => { |
| | | Taro.navigateTo({ |
| | | url: `${RouterPath.electricBillRecharge}`, |
| | | url: `${RouterPath.gasBillRecharge}`, |
| | | }); |
| | | }); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <div>燃气充值</div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'InnerPage', |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss"> |
| | | @import '@/styles/common.scss'; |
| | | </style> |
New file |
| | |
| | | export default definePageConfig({ |
| | | disableScroll: true, |
| | | }); |
New file |
| | |
| | | <template> |
| | | <PageLayout title="燃气充值" class="gasBillRecharge-page-wrapper" hasBorder> |
| | | <InnerPage /> |
| | | </PageLayout> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { PageLayout } from '@/components'; |
| | | import InnerPage from './InnerPage.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'gasBillRecharge', |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <PageLayout title="充值成功" class="rechargeResult-page-wrapper" hasBorder> |
| | | <ContentScrollView> |
| | | <RechargeResultView style="margin-top: 40px" @go-back-home="goHome()" /> |
| | | <RechargeResultView style="margin-top: 40px" @go-back-home="goHome()" :orderNo="orderNo" /> |
| | | </ContentScrollView> |
| | | </PageLayout> |
| | | </template> |
| | |
| | | import { PageLayout } from '@/components'; |
| | | import { goHome } from '@/utils'; |
| | | import { RechargeResultView } from '@life-payment/components'; |
| | | import Taro from '@tarojs/taro'; |
| | | |
| | | defineOptions({ |
| | | name: 'rechargeResult', |
| | | }); |
| | | |
| | | const router = Taro.useRouter(); |
| | | const orderNo = router.params?.orderNo ?? ''; |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <div class="account-add-card"><Uploader /> 新增手机号</div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { Uploader } from '@nutui/icons-vue-taro'; |
| | | |
| | | defineOptions({ |
| | | name: 'AccountAddCard', |
| | | }); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <div class="account-card"> |
| | | <div class="account-card-top"> |
| | | <div class="account-card-title">{{ title }}</div> |
| | | <div class="account-card-actions"> |
| | | <slot name="action" /> |
| | | </div> |
| | | </div> |
| | | <div class="account-card-content">{{ content }}</div> |
| | | <div class="account-card-remark">{{ remark }}</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'AccountCard', |
| | | }); |
| | | |
| | | type Props = { |
| | | title?: string; |
| | | content?: string; |
| | | remark?: string; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), {}); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <div class="par-account-list"></div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'AccountList', |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="confirm-dialog-content-info-item" :class="{ danger }"> |
| | | <div class="confirm-dialog-content-info-item-label">{{ label }}</div> |
| | | <div class="confirm-dialog-content-info-item-label" :style="{ width: _labelWidth }"> |
| | | {{ label }} |
| | | </div> |
| | | <div class="confirm-dialog-content-info-item-content">{{ content }}</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import Taro from '@tarojs/taro'; |
| | | import { computed } from 'vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'ConfirmDialogInfoItem', |
| | | }); |
| | |
| | | label?: string; |
| | | content?: string | number; |
| | | danger?: boolean; |
| | | labelWidth?: string | number; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), {}); |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | labelWidth: 'auto', |
| | | }); |
| | | |
| | | const _labelWidth = computed(() => { |
| | | if (typeof props.labelWidth === 'string') { |
| | | return props.labelWidth; |
| | | } |
| | | |
| | | return Taro.pxTransform(props.labelWidth); |
| | | }); |
| | | </script> |
| | |
| | | */ |
| | | Desc, |
| | | } |
| | | |
| | | export const CustomerServicePhone = '16505012333'; |
| | | export const CustomerServiceTips = `如充值过程中遇到问题,请联系客服 ${CustomerServicePhone}(周一到周五 9:00-17:30)`; |
New file |
| | |
| | | @use './common.scss' as *; |
| | | |
| | | .account-add-card { |
| | | border-radius: 16px; |
| | | min-height: 120px; |
| | | border: 1px solid #e8e8e8; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | font-size: 32px; |
| | | color: boleGetCssVar('color', 'primary'); |
| | | } |
| | | |
| | | .account-card { |
| | | border-radius: 16px; |
| | | border: 1px solid #e8e8e8; |
| | | padding: 28px; |
| | | |
| | | .account-card-top { |
| | | display: flex; |
| | | font-size: 28px; |
| | | line-height: 32px; |
| | | align-items: center; |
| | | margin-bottom: 32px; |
| | | |
| | | .account-card-title { |
| | | flex: 1; |
| | | min-width: 0; |
| | | @include ellipsis; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | } |
| | | |
| | | .account-card-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | |
| | | .account-card-action { |
| | | color: boleGetCssVar('color', 'primary'); |
| | | } |
| | | |
| | | .account-card-action + .account-card-action { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .account-card-content { |
| | | font-size: 36px; |
| | | font-weight: bold; |
| | | line-height: 48px; |
| | | align-items: center; |
| | | margin-bottom: 32px; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | @include ellipsis; |
| | | } |
| | | |
| | | .account-card-remark { |
| | | font-size: 28px; |
| | | line-height: 32px; |
| | | color: boleGetCssVar('text-color', 'secondary'); |
| | | @include ellipsis; |
| | | } |
| | | } |
| | | |
| | | .par-account-list { |
| | | .nut-radio--button { |
| | | margin-bottom: 20px !important; |
| | | } |
| | | } |
| | |
| | | .confirm-dialog-content-info-item-label { |
| | | color: boleGetCssVar('text-color', 'regular'); |
| | | margin-right: 12px; |
| | | text-align: left; |
| | | } |
| | | |
| | | .confirm-dialog-content-info-item-content { |
| | |
| | | line-height: 48px; |
| | | } |
| | | |
| | | .recharge-result-view-subtitle { |
| | | font-size: 28px; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | margin-bottom: 24px; |
| | | text-align: center; |
| | | line-height: 32px; |
| | | } |
| | | |
| | | .recharge-result-view-tips { |
| | | margin-bottom: 24px; |
| | | font-size: 32px; |
| | |
| | | } |
| | | |
| | | .recharge-result-view-warning { |
| | | margin-bottom: 40px; |
| | | margin-bottom: 24px; |
| | | font-size: 24px; |
| | | color: boleGetCssVar('color', 'warning'); |
| | | line-height: 32px; |
| | | } |
| | | |
| | | .recharge-result-view-customerService { |
| | | margin-bottom: 40px; |
| | | font-size: 24px; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | line-height: 32px; |
| | | } |
| | | |
| | | .recharge-result-view-btn-wrapper { |
| | | display: flex; |
| | | justify-content: center; |
| | |
| | | @use './var.scss' as *; |
| | | @use './function.scss' as *; |
| | | @use './orderCard.scss' as *; |
| | | @use './card.scss' as *; |
| | | @use './nut.scss' as *; |
| | | @use './layout.scss' as *; |
| | | @use './rechargeGrid.scss' as *; |
| | |
| | | <template> |
| | | <NutForm |
| | | :model-value="form" |
| | | ref="formRef" |
| | | :rules="rules" |
| | | label-position="top" |
| | | class="order-bill-recharge phone" |
| | | > |
| | | <NutFormItem label="选择运营商:" class="bole-form-item" prop="ispCode" required> |
| | | <NutRadioGroup v-model="form.ispCode" direction="horizontal" @change="changeIspCode"> |
| | | <BlRadio |
| | | :label="key" |
| | | v-for="(val, key) in BlLifeRecharge.constants.IspCodeText" |
| | | :key="key" |
| | | >{{ val }}</BlRadio |
| | | > |
| | | </NutRadioGroup> |
| | | </NutFormItem> |
| | | <NutFormItem label="充值手机号" class="bole-form-item" prop="phone" required> |
| | | <NutInput |
| | | v-model.trim="form.phone" |
| | | class="bole-input-text" |
| | | placeholder="请填写您需要充值的手机号码" |
| | | type="text" |
| | | /> |
| | | </NutFormItem> |
| | | <NutFormItem |
| | | label="姓名" |
| | | class="bole-form-item" |
| | | prop="name" |
| | | required |
| | | v-if="form.ispCode === BlLifeRecharge.constants.IspCode.dianxin" |
| | | > |
| | | <NutInput |
| | | v-model.trim="form.name" |
| | | class="bole-input-text" |
| | | placeholder="请填写您的姓名" |
| | | type="text" |
| | | /> |
| | | </NutFormItem> |
| | | <NutFormItem label="选择充值金额" class="bole-form-item" prop="parValue" required> |
| | | <NutRadioGroup v-model="form.parValue" direction="horizontal" class="parValue-radio-group"> |
| | | <NutRadio |
| | | :label="Number(item)" |
| | | :key="item" |
| | | shape="button" |
| | | v-for="item in parValueList" |
| | | class="parValue-item" |
| | | > |
| | | <div class="parValue-item-inner"> |
| | | <div class="amount-wrapper"> |
| | | <div class="amount">{{ item }}</div> |
| | | <div class="unit">元</div> |
| | | </div> |
| | | <div class="price-wrapper"> |
| | | <div class="price-text">折后</div> |
| | | <div class="price"> |
| | | {{ blLifeRecharge.getRechargeParValue(item, lifePayPhoneRate) }}元 |
| | | </div> |
| | | </div> |
| | | <div class="discountTag">{{ lifePayPhoneRate * 100 }}折</div> |
| | | </div> |
| | | </NutRadio> |
| | | </NutRadioGroup> |
| | | </NutFormItem> |
| | | <div class="common-content"> |
| | | <nut-button class="recharge-button" type="primary" @click="handleSubmit"> |
| | | <div class="recharge-button-inner"> |
| | | <div>¥{{ realParValue }}</div> |
| | | <div class="recharge-button-text">立即充值</div> |
| | | </div> |
| | | </nut-button> |
| | | <RechargeTipsView :tips="tips" /> |
| | | </div> |
| | | <ConfirmDialog v-model:visible="confirmDialogVisible" @ok="goPay"> |
| | | <template #info> |
| | | <ConfirmDialogInfoItem label="充值账号" :content="form.phone" /> |
| | | <ConfirmDialogInfoItem label="充值金额" :content="`¥${form.parValue.toFixed(2)}`" danger /> |
| | | <ConfirmDialogInfoItem label="优惠金额" :content="`¥${discountParValue.toFixed(2)}`" /> |
| | | <ConfirmDialogInfoItem label="实付金额" :content="`¥${realParValue}`" danger /> |
| | | </template> |
| | | </ConfirmDialog> |
| | | </NutForm> |
| | | <PhoneBillRechargeStep1 v-if="current === 'step1'" /> |
| | | <PhoneBillRechargeStep2 |
| | | v-else-if="current === 'step2'" |
| | | v-bind="props" |
| | | @go-pay="emit('goPay', $event)" |
| | | /> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { |
| | | Form as NutForm, |
| | | FormItem as NutFormItem, |
| | | RadioGroup as NutRadioGroup, |
| | | Radio as NutRadio, |
| | | Input as NutInput, |
| | | Button as NutButton, |
| | | } from '@nutui/nutui-taro'; |
| | | import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types'; |
| | | import { reactive, ref, computed } from 'vue'; |
| | | import BlRadio from '../../components/Radio/Radio.vue'; |
| | | import { FormValidator } from '../../utils'; |
| | | import { |
| | | useLifeRechargeContext, |
| | | BlLifeRecharge, |
| | | LifePhoneDataCreateLifePayOrderInput, |
| | | LifeRechargeConstants, |
| | | } from '@life-payment/core-vue'; |
| | | import RechargeTipsView from '../../components/RechargeTipsView/RechargeTipsView.vue'; |
| | | import ConfirmDialog from '../../components/Dialog/ConfirmDialog.vue'; |
| | | import ConfirmDialogInfoItem from '../../components/Dialog/ConfirmDialogInfoItem.vue'; |
| | | import { useGetRate, useGetPhoneParValue } from '../../hooks'; |
| | | import { computed, provide } from 'vue'; |
| | | import { useStepper } from 'senin-mini/hooks'; |
| | | import { PhoneBillRechargeContextKey } from './context'; |
| | | import PhoneBillRechargeStep1 from './PhoneBillRechargeStep1.vue'; |
| | | import PhoneBillRechargeStep2 from './PhoneBillRechargeStep2.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'PhoneBillRecharge', |
| | |
| | | isDev: false, |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ispCode: '', |
| | | phone: '', |
| | | parValue: 0, |
| | | name: '', |
| | | }); |
| | | const stepperInfo = useStepper(['step1', 'step2'], 'step2'); |
| | | const current = computed(() => stepperInfo.current.value); |
| | | |
| | | const emit = defineEmits<{ |
| | | (e: 'goPay', orderNo: string): void; |
| | | }>(); |
| | | |
| | | const { lifePayPhoneRate } = useGetRate(); |
| | | const { phoneParValueList } = useGetPhoneParValue(); |
| | | |
| | | const parValueList = computed( |
| | | () => phoneParValueList.value.find((x) => x.ispCode === form.ispCode)?.parValue ?? [] |
| | | ); |
| | | |
| | | function changeIspCode(val: LifeRechargeConstants.IspCode) { |
| | | const phoneParValueItem = phoneParValueList.value.find((x) => x.ispCode === val); |
| | | if (phoneParValueItem.parValue.every((x) => Number(x) !== form.parValue)) { |
| | | form.parValue = 0; |
| | | } |
| | | } |
| | | |
| | | const realParValue = computed(() => |
| | | blLifeRecharge.getRechargeParValue(form.parValue, lifePayPhoneRate.value) |
| | | ); |
| | | const discountParValue = computed(() => form.parValue - Number(realParValue.value)); |
| | | |
| | | const { blLifeRecharge } = useLifeRechargeContext(); |
| | | |
| | | const rules = reactive<FormRules>({ |
| | | ispCode: [{ required: true, message: '请选择运营商' }], |
| | | phone: [ |
| | | { required: true, message: '请输入充值手机号' }, |
| | | { validator: FormValidator.validatorPhoneNumber, message: '请输入正确的手机号' }, |
| | | ], |
| | | name: [{ required: true, message: '请输入姓名' }], |
| | | parValue: [ |
| | | { required: true, message: '请选择充值金额', validator: FormValidator.validatorNumberNotNull }, |
| | | ], |
| | | provide(PhoneBillRechargeContextKey, { |
| | | ...stepperInfo, |
| | | }); |
| | | |
| | | const formRef = ref<any>(null); |
| | | |
| | | function handleSubmit() { |
| | | if (!formRef.value) return; |
| | | formRef.value.validate().then(({ valid, errors }: any) => { |
| | | if (valid) { |
| | | recharge(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | const tips = [ |
| | | '平台提供慢充服务,订单提交后,话费将于0 - 24小时内到账。若未能按时到账,系统将自动发起退款。', |
| | | '充值期间,若同一号码款项未到账,请勿在其他平台重复充值;主副卡不可同时充值。因上述操作导致的资金损失,由用户自行承担。', |
| | | '本平台话费充值服务不适用于已停机号码。电信号码若有欠费,也无法完成充值。电信已完成维护的区域包括:广东、江苏、湖北、四川、江西、河北、河南、福建、辽宁。其它区域正在分批次进行维护中,在此期间可能会出现充值不成功并自动退款的情况,请您谅解。', |
| | | '如接到陌生来电,对方以缴费或误操作等理由要求处理款项,务必立即拉黑,谨防诈骗。', |
| | | '充值发票由运营商提供,您可登录网上营业厅下载电子发票。', |
| | | ]; |
| | | |
| | | const confirmDialogVisible = ref(false); |
| | | |
| | | function recharge() { |
| | | confirmDialogVisible.value = true; |
| | | } |
| | | |
| | | async function goPay() { |
| | | try { |
| | | let params: LifePhoneDataCreateLifePayOrderInput = { |
| | | userId: blLifeRecharge.accountModel.userId, |
| | | productData: { |
| | | ispCode: form.ispCode, |
| | | parValue: props.isDev ? 0.1 : form.parValue, |
| | | phone: form.phone, |
| | | name: form.ispCode === BlLifeRecharge.constants.IspCode.dianxin ? form.name : '', |
| | | }, |
| | | }; |
| | | let res = await blLifeRecharge.services.createLifePayPhoneOrder(params); |
| | | emit('goPay', res.orderNo); |
| | | } catch (error) {} |
| | | } |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <NutForm |
| | | :model-value="form" |
| | | ref="formRef" |
| | | :rules="rules" |
| | | label-position="top" |
| | | class="order-bill-recharge phone" |
| | | > |
| | | <NutFormItem label="选择运营商:" class="bole-form-item" prop="ispCode" required> |
| | | <NutRadioGroup v-model="form.ispCode" direction="horizontal"> |
| | | <BlRadio |
| | | :label="key" |
| | | v-for="(val, key) in BlLifeRecharge.constants.IspCodeText" |
| | | :key="key" |
| | | >{{ val }}</BlRadio |
| | | > |
| | | </NutRadioGroup> |
| | | </NutFormItem> |
| | | <NutFormItem label="充值手机号" class="bole-form-item" prop="phone" required> |
| | | <NutInput |
| | | v-model.trim="form.phone" |
| | | class="bole-input-text" |
| | | placeholder="请填写您需要充值的手机号码" |
| | | type="text" |
| | | /> |
| | | </NutFormItem> |
| | | <NutFormItem |
| | | label="姓名" |
| | | class="bole-form-item" |
| | | prop="name" |
| | | required |
| | | v-if="form.ispCode === BlLifeRecharge.constants.IspCode.dianxin" |
| | | > |
| | | <NutInput |
| | | v-model.trim="form.name" |
| | | class="bole-input-text" |
| | | placeholder="请填写您的姓名" |
| | | type="text" |
| | | /> |
| | | </NutFormItem> |
| | | <slot></slot> |
| | | </NutForm> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { |
| | | Form as NutForm, |
| | | FormItem as NutFormItem, |
| | | RadioGroup as NutRadioGroup, |
| | | Input as NutInput, |
| | | } from '@nutui/nutui-taro'; |
| | | import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types'; |
| | | import { reactive, ref, computed } from 'vue'; |
| | | import BlRadio from '../../components/Radio/Radio.vue'; |
| | | import { FormValidator } from '../../utils'; |
| | | import { BlLifeRecharge } from '@life-payment/core-vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'PhoneBillRechargeBaseForm', |
| | | }); |
| | | |
| | | const form = defineModel<{ |
| | | ispCode: string; |
| | | phone: string; |
| | | name: string; |
| | | }>('form'); |
| | | |
| | | const rules = reactive<FormRules>({ |
| | | ispCode: [{ required: true, message: '请选择运营商' }], |
| | | phone: [ |
| | | { required: true, message: '请输入充值手机号' }, |
| | | { validator: FormValidator.validatorPhoneNumber, message: '请输入正确的手机号' }, |
| | | ], |
| | | name: [{ required: true, message: '请输入姓名' }], |
| | | }); |
| | | |
| | | const formRef = ref<any>(null); |
| | | |
| | | defineExpose({ |
| | | validate: computed(() => formRef.value.validate), |
| | | }); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <PhoneBillRechargeBaseForm ref="formRef" v-model:form="form"> |
| | | <div class="common-content"> |
| | | <nut-button class="recharge-button" type="primary" @click="handleNext"> |
| | | <div class="recharge-button-inner"> |
| | | <div class="recharge-button-text">立即充值</div> |
| | | </div> |
| | | </nut-button> |
| | | </div> |
| | | </PhoneBillRechargeBaseForm> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { |
| | | Form as NutForm, |
| | | FormItem as NutFormItem, |
| | | RadioGroup as NutRadioGroup, |
| | | Radio as NutRadio, |
| | | Input as NutInput, |
| | | Button as NutButton, |
| | | } from '@nutui/nutui-taro'; |
| | | import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types'; |
| | | import { reactive, ref, computed, provide } from 'vue'; |
| | | import BlRadio from '../../components/Radio/Radio.vue'; |
| | | import { FormValidator } from '../../utils'; |
| | | import { |
| | | useLifeRechargeContext, |
| | | BlLifeRecharge, |
| | | LifePhoneDataCreateLifePayOrderInput, |
| | | LifeRechargeConstants, |
| | | } from '@life-payment/core-vue'; |
| | | import RechargeTipsView from '../../components/RechargeTipsView/RechargeTipsView.vue'; |
| | | import ConfirmDialog from '../../components/Dialog/ConfirmDialog.vue'; |
| | | import ConfirmDialogInfoItem from '../../components/Dialog/ConfirmDialogInfoItem.vue'; |
| | | import { useGetRate, useGetPhoneParValue } from '../../hooks'; |
| | | import PhoneBillRechargeBaseForm from './PhoneBillRechargeBaseForm.vue'; |
| | | import { usePhoneBillRechargeContext } from './context'; |
| | | |
| | | defineOptions({ |
| | | name: 'PhoneBillRechargeStep1', |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ispCode: '', |
| | | phone: '', |
| | | name: '', |
| | | }); |
| | | |
| | | const { goToNext } = usePhoneBillRechargeContext(); |
| | | |
| | | const formRef = ref<any>(null); |
| | | |
| | | function handleNext() { |
| | | if (!formRef.value) return; |
| | | formRef.value.validate().then(({ valid, errors }: any) => { |
| | | if (valid) { |
| | | goToNext(); |
| | | } |
| | | }); |
| | | } |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <NutForm |
| | | :model-value="form" |
| | | ref="formRef" |
| | | :rules="rules" |
| | | label-position="top" |
| | | class="order-bill-recharge phone" |
| | | > |
| | | <NutFormItem class="bole-form-item"> |
| | | <!-- <AccountAddCard /> --> |
| | | <NutRadioGroup v-model="val1" direction="horizontal" class="par-account-list"> |
| | | <NutRadio label="1" shape="button">Option 1</NutRadio> |
| | | <NutRadio label="2" shape="button">Option 2</NutRadio> |
| | | <NutRadio label="3" shape="button">Option 3</NutRadio> |
| | | <NutRadio label="4" shape="button">Option 4</NutRadio> |
| | | <NutRadio label="5" shape="button">Option 5</NutRadio> |
| | | <NutRadio label="6" shape="button">Option 6</NutRadio> |
| | | </NutRadioGroup> |
| | | <AccountCard title="充值手机号" content="18858418480" remark="的地方骄傲的开始和"> |
| | | <template #action> |
| | | <div class="account-card-action">新增</div> |
| | | </template> |
| | | </AccountCard> |
| | | </NutFormItem> |
| | | |
| | | <NutFormItem label="选择充值金额" class="bole-form-item" prop="parValue" required> |
| | | <NutRadioGroup v-model="form.parValue" direction="horizontal" class="parValue-radio-group"> |
| | | <NutRadio |
| | | :label="Number(item)" |
| | | :key="item" |
| | | shape="button" |
| | | v-for="item in parValueList" |
| | | class="parValue-item" |
| | | > |
| | | <div class="parValue-item-inner"> |
| | | <div class="amount-wrapper"> |
| | | <div class="amount">{{ item }}</div> |
| | | <div class="unit">元</div> |
| | | </div> |
| | | <div class="price-wrapper"> |
| | | <div class="price-text">折后</div> |
| | | <div class="price"> |
| | | {{ blLifeRecharge.getRechargeParValue(item, lifePayPhoneRate) }}元 |
| | | </div> |
| | | </div> |
| | | <div class="discountTag">{{ lifePayPhoneRate * 100 }}折</div> |
| | | </div> |
| | | </NutRadio> |
| | | </NutRadioGroup> |
| | | </NutFormItem> |
| | | <div class="common-content"> |
| | | <nut-button class="recharge-button" type="primary" @click="handleSubmit"> |
| | | <div class="recharge-button-inner"> |
| | | <div>¥{{ realParValue }}</div> |
| | | <div class="recharge-button-text">立即充值</div> |
| | | </div> |
| | | </nut-button> |
| | | <RechargeTipsView :tips="tips" /> |
| | | </div> |
| | | <ConfirmDialog v-model:visible="confirmDialogVisible" @ok="goPay"> |
| | | <template #info> |
| | | <ConfirmDialogInfoItem label="充值账号" :content="form.phone" /> |
| | | <ConfirmDialogInfoItem label="充值金额" :content="`¥${form.parValue.toFixed(2)}`" danger /> |
| | | <ConfirmDialogInfoItem label="优惠金额" :content="`¥${discountParValue.toFixed(2)}`" /> |
| | | <ConfirmDialogInfoItem label="实付金额" :content="`¥${realParValue}`" danger /> |
| | | </template> |
| | | </ConfirmDialog> |
| | | </NutForm> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { |
| | | Form as NutForm, |
| | | FormItem as NutFormItem, |
| | | RadioGroup as NutRadioGroup, |
| | | Radio as NutRadio, |
| | | Input as NutInput, |
| | | Button as NutButton, |
| | | } from '@nutui/nutui-taro'; |
| | | import { FormRules } from '@nutui/nutui-taro/dist/types/__VUE/form/types'; |
| | | import { reactive, ref, computed, provide } from 'vue'; |
| | | import { FormValidator } from '../../utils'; |
| | | import { |
| | | useLifeRechargeContext, |
| | | BlLifeRecharge, |
| | | LifePhoneDataCreateLifePayOrderInput, |
| | | LifeRechargeConstants, |
| | | } from '@life-payment/core-vue'; |
| | | import RechargeTipsView from '../../components/RechargeTipsView/RechargeTipsView.vue'; |
| | | import ConfirmDialog from '../../components/Dialog/ConfirmDialog.vue'; |
| | | import ConfirmDialogInfoItem from '../../components/Dialog/ConfirmDialogInfoItem.vue'; |
| | | import { useGetRate, useGetPhoneParValue } from '../../hooks'; |
| | | import { CustomerServiceTips } from '../../constants'; |
| | | import AccountAddCard from '../../components/Card/AccountAddCard.vue'; |
| | | import AccountCard from '../../components/Card/AccountCard.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'PhoneBillRechargeStep2', |
| | | }); |
| | | |
| | | type Props = { |
| | | isDev?: boolean; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), { |
| | | isDev: false, |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ispCode: '', |
| | | phone: '', |
| | | parValue: 0, |
| | | name: '', |
| | | }); |
| | | |
| | | const val1 = ref(''); |
| | | |
| | | const emit = defineEmits<{ |
| | | (e: 'goPay', orderNo: string): void; |
| | | }>(); |
| | | |
| | | const { lifePayPhoneRate } = useGetRate(); |
| | | const { phoneParValueList } = useGetPhoneParValue(); |
| | | |
| | | const parValueList = computed(() => { |
| | | const _parValueList = |
| | | phoneParValueList.value.find((x) => x.ispCode === form.ispCode)?.parValue ?? []; |
| | | return blLifeRecharge.filterParValueList(_parValueList); |
| | | }); |
| | | |
| | | function changeIspCode(val: LifeRechargeConstants.IspCode) { |
| | | const phoneParValueItem = phoneParValueList.value.find((x) => x.ispCode === val); |
| | | if (phoneParValueItem.parValue.every((x) => Number(x) !== form.parValue)) { |
| | | form.parValue = 0; |
| | | } |
| | | } |
| | | |
| | | const realParValue = computed(() => |
| | | blLifeRecharge.getRechargeParValue(form.parValue, lifePayPhoneRate.value) |
| | | ); |
| | | const discountParValue = computed(() => form.parValue - Number(realParValue.value)); |
| | | |
| | | const { blLifeRecharge } = useLifeRechargeContext(); |
| | | |
| | | const rules = reactive<FormRules>({ |
| | | parValue: [ |
| | | { required: true, message: '请选择充值金额', validator: FormValidator.validatorNumberNotNull }, |
| | | ], |
| | | }); |
| | | |
| | | const formRef = ref<any>(null); |
| | | |
| | | function handleSubmit() { |
| | | if (!formRef.value) return; |
| | | formRef.value.validate().then(({ valid, errors }: any) => { |
| | | if (valid) { |
| | | recharge(); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | const tips = [ |
| | | '平台提供慢充服务,订单提交后,话费将于0 - 24小时内到账。若未能按时到账,系统将自动发起退款。', |
| | | '充值期间,若同一号码款项未到账,请勿在其他平台重复充值;主副卡不可同时充值。因上述操作导致的资金损失,由用户自行承担。', |
| | | '本平台话费充值服务不适用于已停机号码。电信号码若有欠费,也无法完成充值。电信已完成维护的区域包括:广东、江苏、湖北、四川、江西、河北、河南、福建、辽宁。其它区域正在分批次进行维护中,在此期间可能会出现充值不成功并自动退款的情况,请您谅解。', |
| | | '如接到陌生来电,对方以缴费或误操作等理由要求处理款项,务必立即拉黑,谨防诈骗。', |
| | | '充值发票由运营商提供,您可登录网上营业厅下载电子发票。', |
| | | CustomerServiceTips, |
| | | ]; |
| | | |
| | | const confirmDialogVisible = ref(false); |
| | | |
| | | function recharge() { |
| | | confirmDialogVisible.value = true; |
| | | } |
| | | |
| | | async function goPay() { |
| | | try { |
| | | let params: LifePhoneDataCreateLifePayOrderInput = { |
| | | userId: blLifeRecharge.accountModel.userId, |
| | | productData: { |
| | | ispCode: form.ispCode, |
| | | parValue: props.isDev ? 0.1 : form.parValue, |
| | | phone: form.phone, |
| | | name: form.ispCode === BlLifeRecharge.constants.IspCode.dianxin ? form.name : '', |
| | | }, |
| | | }; |
| | | let res = await blLifeRecharge.services.createLifePayPhoneOrder(params); |
| | | emit('goPay', res.orderNo); |
| | | } catch (error) {} |
| | | } |
| | | </script> |
New file |
| | |
| | | import type { InjectionKey, UnwrapNestedRefs, Ref } from 'vue'; |
| | | import { inject } from 'vue'; |
| | | import { UseStepperReturn } from 'senin-mini/hooks'; |
| | | |
| | | type PhoneBillRechargeSteps = 'step1' | 'step2'; |
| | | |
| | | export interface PhoneBillRechargeContext |
| | | extends UseStepperReturn< |
| | | PhoneBillRechargeSteps, |
| | | PhoneBillRechargeSteps[], |
| | | PhoneBillRechargeSteps |
| | | > { |
| | | // form: UnwrapNestedRefs<{ |
| | | // ispCode: string; |
| | | // phone: string; |
| | | // parValue: number; |
| | | // name: string; |
| | | // }>; |
| | | } |
| | | |
| | | export const PhoneBillRechargeContextKey: InjectionKey<PhoneBillRechargeContext> = Symbol( |
| | | 'PhoneBillRechargeContextKey' |
| | | ); |
| | | |
| | | export function usePhoneBillRechargeContext() { |
| | | return inject(PhoneBillRechargeContextKey); |
| | | } |
| | |
| | | <template> |
| | | <div class="recharge-result-view"> |
| | | <div class="recharge-result-view-title">{{ title }}</div> |
| | | <div class="recharge-result-view-subtitle">订单号:{{ orderNo }}</div> |
| | | <div class="recharge-result-view-tips"> |
| | | 同一号码充值期间,未到账前切勿在其他任何平台再次充值。因此造成的资金损失须用户自行承担!!! |
| | | </div> |
| | | <div class="recharge-result-view-warning"> |
| | | 如接到陌生来电,对方以缴费或误操作等理由要求处理款项,务必立即拉黑,谨防诈骗!!! |
| | | </div> |
| | | <div class="recharge-result-view-customerService">{{ CustomerServiceTips }}</div> |
| | | <div class="recharge-result-view-btn-wrapper"> |
| | | <div class="recharge-result-view-btn" @click="emit('goBackHome')">回首页</div> |
| | | </div> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import { LifeRechargeConstants } from '@life-payment/core-vue'; |
| | | import { CustomerServiceTips } from '../../constants'; |
| | | |
| | | defineOptions({ |
| | | name: 'RechargeResultView', |
| | |
| | | label="电网类型" |
| | | :content="blLifeRecharge.constants.ElectricTypeText[form.electricType]" |
| | | /> |
| | | <ConfirmDialogInfoItem label="电费类型" content="住宅" /> |
| | | <ConfirmDialogInfoItem :label-width="96" label="户号" :content="form.electricAccount" /> |
| | | <ConfirmDialogInfoItem label="充值金额" :content="`¥${form.parValue.toFixed(2)}`" danger /> |
| | | <ConfirmDialogInfoItem label="优惠金额" :content="`¥${discountParValue.toFixed(2)}`" /> |
| | | <ConfirmDialogInfoItem label="实付金额" :content="`¥${realParValue}`" danger /> |
| | |
| | | import NumberInput from '../../components/Input/NumberInput.vue'; |
| | | import { useGetRate, useGetElectricParValue } from '../../hooks'; |
| | | import { FormValidator } from '../../utils'; |
| | | import { CustomerServiceTips } from '../../constants'; |
| | | |
| | | defineOptions({ |
| | | name: 'electricBillRecharge', |
| | |
| | | const { lifePayElectricRate } = useGetRate(); |
| | | const { electricParValueList } = useGetElectricParValue(); |
| | | |
| | | const parValueList = computed( |
| | | () => electricParValueList.value.find((x) => x.cityName === form.province)?.parValue ?? [] |
| | | ); |
| | | const parValueList = computed(() => { |
| | | const parValueList = |
| | | electricParValueList.value.find((x) => x.cityName === form.province)?.parValue ?? []; |
| | | return blLifeRecharge.filterParValueList(parValueList); |
| | | }); |
| | | |
| | | const electricCityList = computed( |
| | | () => electricParValueList.value.find((x) => x.cityName === form.province)?.childCityList ?? [] |
| | |
| | | '为确保充值顺利进行,目前平台不支持对欠款金额超过1000元的账户进行充值,且每次充值金额必须高于欠费总额。', |
| | | '如接到陌生来电,对方以缴费或误操作等理由要求处理款项,务必立即拉黑,谨防诈骗。', |
| | | '下单时,请您务必准确填写完整的省市及户号信息。充值完成后,发票由运营商提供,您可登录网上营业厅下载对应的电子发票。', |
| | | CustomerServiceTips, |
| | | ]; |
| | | |
| | | const confirmDialogVisible = ref(false); |
| | |
| | | "name": "@life-payment/core-vue", |
| | | "main": "src/index.ts", |
| | | "module": "./src/index.ts", |
| | | "types": "./dist/types/index.d.ts", |
| | | "source": "./src/index.ts", |
| | | "version": "0.0.3", |
| | | "scripts": { |
| | |
| | | "name": "@life-payment/core", |
| | | "main": "src/index.ts", |
| | | "module": "./src/index.ts", |
| | | "types": "./dist/types/index.d.ts", |
| | | "source": "./src/index.ts", |
| | | "version": "0.0.2", |
| | | "scripts": { |
| | |
| | | getRechargeParValue(amount: number | string, rate: number) { |
| | | return (Number(amount) * rate).toFixed(2); |
| | | } |
| | | |
| | | MaxParValue = 300; |
| | | |
| | | filterParValueList(parValueList: string[]) { |
| | | return parValueList.filter((x) => Number(x) <= this.MaxParValue); |
| | | } |
| | | } |