| | |
| | | h5: { |
| | | publicPath: '/', |
| | | staticDirectory: 'static', |
| | | router: { |
| | | mode: 'browser', |
| | | }, |
| | | postcss: { |
| | | autoprefixer: { |
| | | enable: true, |
| | |
| | | 'registerForm/registerForm', |
| | | ], |
| | | }, |
| | | { |
| | | root: 'subpackages/recharge', |
| | | pages: ['phoneBillRecharge/phoneBillRecharge'], |
| | | }, |
| | | ], |
| | | // preloadRule: { |
| | | // 'pages/mine/index': { |
| | |
| | | import Taro from '@tarojs/taro'; |
| | | import { VueQueryPlugin, VueQueryPluginOptions } from '@tanstack/vue-query'; |
| | | import { myClient } from '@/constants/query'; |
| | | import { VueLifeRechargePlugin, BlLifeRecharge } from '@life-payment/components'; |
| | | |
| | | window.uni = Taro; |
| | | |
| | |
| | | |
| | | App.use(VueQueryPlugin, vueQueryPluginOptions); |
| | | |
| | | const blLifeRecharge = new BlLifeRecharge(); |
| | | |
| | | App.use(VueLifeRechargePlugin, { |
| | | blLifeRecharge, |
| | | }); |
| | | |
| | | export default App; |
| | |
| | | registerForm = '/subpackages/login/registerForm/registerForm', |
| | | home = '/pages/home/index', |
| | | mine = '/pages/mine/index', |
| | | |
| | | phoneBillRecharge = '/subpackages/recharge/phoneBillRecharge/phoneBillRecharge', |
| | | } |
| | |
| | | <!DOCTYPE html> |
| | | <html> |
| | | <head> |
| | | <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| | | <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport"> |
| | | <meta name="apple-mobile-web-app-capable" content="yes"> |
| | | <meta name="apple-touch-fullscreen" content="yes"> |
| | | <meta name="format-detection" content="telephone=no,address=no"> |
| | | <meta name="apple-mobile-web-app-status-bar-style" content="white"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" > |
| | | <title>vue-mini</title> |
| | | <script><%= htmlWebpackPlugin.options.script %></script> |
| | | </head> |
| | | <body> |
| | | <div id="app"></div> |
| | | </body> |
| | | <head> |
| | | <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> |
| | | <meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport" /> |
| | | <meta name="apple-mobile-web-app-capable" content="yes" /> |
| | | <meta name="apple-touch-fullscreen" content="yes" /> |
| | | <meta name="format-detection" content="telephone=no,address=no" /> |
| | | <meta name="apple-mobile-web-app-status-bar-style" content="white" /> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> |
| | | <title>生活缴费</title> |
| | | <script> |
| | | <%= htmlWebpackPlugin.options.script %> |
| | | </script> |
| | | </head> |
| | | <body> |
| | | <div id="app"></div> |
| | | </body> |
| | | </html> |
| | |
| | | <template> |
| | | <PageLayoutWithBg class="index-page-wrapper" :title="'生活缴费'" :need-auth="false"> |
| | | <ContentView> |
| | | <RechargeGrid /> |
| | | <RechargeGrid @phoneBillRecharge="goPhoneBillRecharge" /> |
| | | </ContentView> |
| | | </PageLayoutWithBg> |
| | | </template> |
| | |
| | | import { useUser, useInfiniteLoading } from '@/hooks'; |
| | | import { useUserStore } from '@/stores/modules/user'; |
| | | import Taro from '@tarojs/taro'; |
| | | import _ from 'lodash'; |
| | | import IconLogo from '@/assets/home/icon-logo.png'; |
| | | import { OrderInputType } from '@life-payment/constants'; |
| | | import { RechargeGrid } from '@life-payment/components'; |
| | | |
| | | const { locationCity } = useUser(); |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | const queryState = reactive({}); |
| | | |
| | | const list = ref([ |
| | | 'https://storage.360buyimg.com/jdc-article/NutUItaro34.jpg', |
| | | 'https://storage.360buyimg.com/jdc-article/NutUItaro2.jpg', |
| | | 'https://storage.360buyimg.com/jdc-article/welcomenutui.jpg', |
| | | 'https://storage.360buyimg.com/jdc-article/fristfabu.jpg', |
| | | ]); |
| | | |
| | | const selectItem = ref(); |
| | | function goPhoneBillRecharge() { |
| | | Taro.navigateTo({ |
| | | url: RouterPath.phoneBillRecharge, |
| | | }) |
| | | .then(() => { |
| | | console.log('Navigate successfully'); |
| | | }) |
| | | .catch((err) => { |
| | | console.error('Navigation failed:', err); |
| | | }); |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss"> |
New file |
| | |
| | | <template> |
| | | <ContentScrollView :paddingH="false"> |
| | | <PhoneBillRecharge /> |
| | | </ContentScrollView> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { PhoneBillRecharge } from '@life-payment/components'; |
| | | |
| | | defineOptions({ |
| | | name: 'InnerPage', |
| | | }); |
| | | </script> |
New file |
| | |
| | | export default definePageConfig({ |
| | | disableScroll: true, |
| | | }); |
New file |
| | |
| | | <template> |
| | | <PageLayout title="话费充值" class="phoneBillRecharge-page-wrapper" hasBorder :need-auth="false"> |
| | | <InnerPage /> |
| | | </PageLayout> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { PageLayout } from '@/components'; |
| | | import InnerPage from './InnerPage.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'phoneBillRecharge', |
| | | }); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <nut-dialog title="请核对充值信息并支付" v-model:visible="visible"> |
| | | <div class="confirm-dialog-content"> |
| | | <div class="confirm-dialog-content-tips"> |
| | | 该产品为慢充模式,0-24小时内到账,介意请勿付款! 充值前请仔细阅读充值须知! |
| | | </div> |
| | | <div class="confirm-dialog-content-info"> |
| | | <slot name="info"></slot> |
| | | </div> |
| | | </div> |
| | | </nut-dialog> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'ConfirmDialog', |
| | | }); |
| | | |
| | | // type Props = {}; |
| | | |
| | | // const props = withDefaults(defineProps<Props>(), {}); |
| | | |
| | | const visible = defineModel<boolean>('visible'); |
| | | </script> |
New file |
| | |
| | | <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-content">{{ content }}</div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'ConfirmDialogInfoItem', |
| | | }); |
| | | |
| | | type Props = { |
| | | label?: string; |
| | | content?: string; |
| | | danger?: boolean; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), {}); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <Radio class="bl-radio"> |
| | | <template #default><slot /> </template> |
| | | <template #checkedIcon> |
| | | <IconFont name="checked" color="var(--bole-color-primary)" /> |
| | | </template> |
| | | </Radio> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { IconFont } from '@nutui/icons-vue-taro'; |
| | | import { Radio } from '@nutui/nutui-taro'; |
| | | |
| | | defineOptions({ |
| | | name: 'bl-radio', |
| | | }); |
| | | </script> |
New file |
| | |
| | | <template> |
| | | <div class="recharge-tips-view"> |
| | | <div class="recharge-tips-title">充值须知</div> |
| | | <div class="recharge-tips-content"> |
| | | <div class="recharge-tips-top"> |
| | | *同一号码充值期间【切勿多平台重复充值】!!!在下单前,请务必仔细阅读公告内容!!!若接到陌生来电,请勿轻信!!! |
| | | </div> |
| | | <div class="recharge-tips-list"> |
| | | <div class="recharge-tips-item" v-for="(item, index) in props.tips" :key="index"> |
| | | {{ index + 1 }}.{{ item }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | defineOptions({ |
| | | name: 'RechargeTipsView', |
| | | }); |
| | | |
| | | type Props = { |
| | | tips: string[]; |
| | | }; |
| | | |
| | | const props = withDefaults(defineProps<Props>(), {}); |
| | | </script> |
New file |
| | |
| | | export enum IspCode { |
| | | /**中国移动 */ |
| | | yidong = 'yidong', |
| | | /**中国电信 */ |
| | | dianxin = 'dianxin', |
| | | /**中国联通 */ |
| | | liantong = 'liantong', |
| | | } |
| | | |
| | | export const IspCodeText = { |
| | | [IspCode.yidong]: '中国移动', |
| | | [IspCode.dianxin]: '中国电信', |
| | | [IspCode.liantong]: '中国联通', |
| | | }; |
| | |
| | | export { default as RechargeGrid } from './views/RechargeGrid/RechargeGrid.vue'; |
| | | export { default as PhoneBillRecharge } from './views/PhoneBillRecharge/PhoneBillRecharge.vue'; |
| | | export * from './utils'; |
New file |
| | |
| | | /*postcss-pxtransform disable*/ |
| | | @use './common.scss' as *; |
| | | |
| | | .recharge-tips-view { |
| | | padding: 16px; |
| | | border-radius: 12px; |
| | | background: linear-gradient(0deg, rgba(10, 90, 255, 0.04), rgba(10, 90, 255, 0.04)), #fff; |
| | | |
| | | .recharge-tips-title { |
| | | color: #1f2229; |
| | | font-size: 14px; |
| | | font-weight: 700; |
| | | line-height: 18px; |
| | | padding: 4px 0 12px 0; |
| | | border-bottom: 1px solid boleGetCssVar('color', 'primary'); |
| | | } |
| | | |
| | | .recharge-tips-content { |
| | | color: boleGetCssVar('text-color', 'regular'); |
| | | font-size: 13px; |
| | | font-weight: 400; |
| | | line-height: 21px; |
| | | padding-top: 16px; |
| | | |
| | | .recharge-tips-top { |
| | | color: #e03e2d; |
| | | font-size: 18px; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .confirm-dialog-content { |
| | | .confirm-dialog-content-tips { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .confirm-dialog-content-info { |
| | | padding: 12px; |
| | | border-radius: 8px; |
| | | background: #f0f3fa; |
| | | |
| | | .confirm-dialog-content-info-item { |
| | | display: flex; |
| | | margin-bottom: 10px; |
| | | |
| | | &:last-child { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .confirm-dialog-content-info-item-label { |
| | | color: boleGetCssVar('text-color', 'regular'); |
| | | margin-right: 6px; |
| | | } |
| | | |
| | | .confirm-dialog-content-info-item-content { |
| | | flex: 1; |
| | | min-width: 0; |
| | | @include ellipsis; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | text-align: left; |
| | | } |
| | | |
| | | &.danger { |
| | | .confirm-dialog-content-info-item-content { |
| | | color: boleGetCssVar('color', 'danger'); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | @use 'sass:map'; |
| | | @use './var.scss' as *; |
| | | @use './function.scss' as *; |
| | | @use './nut.scss' as *; |
| | | @use './layout.scss' as *; |
| | | @use './rechargeGrid.scss' as *; |
| | | @use './components.scss' as *; |
| | | |
| | | :root, |
| | | page { |
New file |
| | |
| | | /*postcss-pxtransform disable*/ |
| | | |
| | | @use './function.scss' as *; |
| | | @use './hairline.scss' as *; |
| | | |
| | | :root, |
| | | page { |
| | | .category-searchbar-container { |
| | | padding: 30px; |
| | | } |
| | | |
| | | .h5-view.nut-popup.nut-popup--bottom { |
| | | padding-bottom: constant(safe-area-inset-bottom); |
| | | padding-bottom: env(safe-area-inset-bottom); |
| | | } |
| | | |
| | | .nut-button.dark-btn { |
| | | color: boleGetCssVar('text-color', 'primary') !important; |
| | | } |
| | | |
| | | .nut-form { |
| | | .nut-cell-group__wrap { |
| | | margin-top: 0; |
| | | border-radius: 0; |
| | | box-shadow: none; |
| | | } |
| | | |
| | | .nut-cell.bole-form-item { |
| | | --nut-form-item-label-width: 120px; |
| | | &:not(.alignTop) { |
| | | align-items: center !important; |
| | | } |
| | | |
| | | &.labelTop { |
| | | display: block; |
| | | } |
| | | |
| | | padding: 30rpx; |
| | | |
| | | &::after { |
| | | border-bottom: 1px solid #f0f0f0; |
| | | left: 30rpx; |
| | | right: 30rpx; |
| | | display: none; |
| | | } |
| | | |
| | | .nut-form-item__body__tips { |
| | | position: absolute; |
| | | bottom: 0; |
| | | } |
| | | &:not(.bole-form-item-phone) { |
| | | .nut-form-item__body__tips { |
| | | right: 30rpx; |
| | | } |
| | | } |
| | | |
| | | .nut-form-item__label { |
| | | font-size: 28rpx; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | } |
| | | |
| | | &.vertical { |
| | | flex-direction: column; |
| | | align-items: flex-start !important; |
| | | } |
| | | |
| | | .nut-form-item__label.required::before { |
| | | position: absolute; |
| | | left: 12rpx; |
| | | } |
| | | |
| | | .nut-radio-group--horizontal { |
| | | .nut-radio { |
| | | margin-bottom: 0; |
| | | vertical-align: middle; |
| | | } |
| | | } |
| | | |
| | | .nut-rate { |
| | | vertical-align: middle; |
| | | } |
| | | |
| | | &.hidden-label { |
| | | .nut-form-item__label { |
| | | opacity: 0; |
| | | } |
| | | } |
| | | |
| | | .bole-uploader { |
| | | padding-top: 16rpx; |
| | | |
| | | &.nopaddingtop { |
| | | padding-top: 0; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .bole-form-item-phone { |
| | | padding: 24rpx 30rpx; |
| | | } |
| | | |
| | | .nut-uploader { |
| | | // justify-content: flex-end; |
| | | } |
| | | |
| | | .nut-form-item__top { |
| | | .nut-form-item__label { |
| | | margin-right: 0; |
| | | } |
| | | |
| | | .nut-form-item__body { |
| | | width: 100%; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .bole-input-text:not(.nut-input--disabled) { |
| | | .h5-input { |
| | | color: boleGetCssVar('text-color', 'primary') !important; |
| | | display: block; |
| | | font-size: 26rpx; |
| | | } |
| | | |
| | | .input-placeholder { |
| | | color: boleGetCssVar('text-color', 'placeholder') !important; |
| | | font-size: 26rpx; |
| | | } |
| | | } |
| | | |
| | | .bole-input-textarea:not(.nut-input--disabled) { |
| | | color: boleGetCssVar('text-color', 'primary') !important; |
| | | height: 100rpx; |
| | | } |
| | | |
| | | .bole-input-text-placeholder { |
| | | color: boleGetCssVar('text-color', 'placeholder') !important; |
| | | font-size: 26rpx; |
| | | line-height: 20rpx; |
| | | } |
| | | |
| | | .form-item-divider { |
| | | margin: 0 28px; |
| | | width: calc(100% - 56px); |
| | | color: #f0f0f0; |
| | | } |
| | | |
| | | // .nut-overlay { |
| | | // z-index: 20022221 !important; |
| | | // } |
| | | |
| | | // .nut-popup { |
| | | // z-index: 2222222222 !important; |
| | | // } |
| | | |
| | | .nut-tabs__titles-item__smile { |
| | | // display: none; |
| | | opacity: 0; |
| | | transition: width 0.3s ease; |
| | | } |
| | | |
| | | .nut-tabs__titles.smile .nut-tabs__titles-item.active .nut-tabs__titles-item__smile { |
| | | // display: block; |
| | | opacity: 1; |
| | | } |
| | | |
| | | .nut-toast { |
| | | z-index: 99999999999; |
| | | } |
| | | |
| | | .pro-form-item-tips { |
| | | word-break: break-all; |
| | | } |
| | | } |
New file |
| | |
| | | /*postcss-pxtransform disable*/ |
| | | @use './common.scss' as *; |
| | | |
| | | .recharge-grid-wrapper { |
| | | padding-left: 0 !important; |
| | | margin-top: 20px; |
| | | |
| | | .recharge-grid-item { |
| | | .nut-grid-item__text { |
| | | font-size: 18px; |
| | | color: boleGetCssVar('text-color', 'primary'); |
| | | } |
| | | } |
| | | } |
| | | |
| | | .common-content { |
| | | padding: 0 boleGetCssVar('size', 'body-padding-h2'); |
| | | } |
| | | |
| | | .parValue-radio-group { |
| | | width: 100%; |
| | | display: grid; |
| | | grid-template-columns: repeat(3, 1fr); |
| | | grid-gap: 10px; |
| | | |
| | | .parValue-item { |
| | | margin-right: 0; |
| | | |
| | | .nut-radio__button { |
| | | width: 100%; |
| | | padding: 8px 0; |
| | | background-color: transparent; |
| | | border: 0.5px solid #e2e5eb; |
| | | text-align: center; |
| | | border-radius: 4px; |
| | | position: relative; |
| | | } |
| | | |
| | | .nut-radio__button--active { |
| | | color: #fb5100; |
| | | border-color: #fb5100; |
| | | overflow: hidden; |
| | | |
| | | &::after { |
| | | border-radius: 4px; |
| | | background-color: rgba(251, 81, 0, 0.08); |
| | | opacity: 1; |
| | | } |
| | | |
| | | .parValue-item-inner { |
| | | .discountTag { |
| | | display: block; |
| | | } |
| | | } |
| | | } |
| | | |
| | | .parValue-item-inner { |
| | | width: 100%; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | |
| | | .amount-wrapper { |
| | | display: flex; |
| | | align-items: flex-end; |
| | | margin-bottom: 2px; |
| | | |
| | | .amount { |
| | | font-size: 20px; |
| | | font-weight: 400; |
| | | line-height: 22px; |
| | | } |
| | | .unit { |
| | | font-size: 12px; |
| | | font-weight: 400; |
| | | line-height: 16px; |
| | | } |
| | | } |
| | | |
| | | .price-wrapper { |
| | | display: flex; |
| | | color: #858d98; |
| | | font-size: 12px; |
| | | font-weight: 400; |
| | | line-height: 16px; |
| | | |
| | | .price { |
| | | color: #fb5100; |
| | | margin-left: 3px; |
| | | } |
| | | } |
| | | |
| | | .discountTag { |
| | | display: none; |
| | | position: absolute; |
| | | padding: 1px 4px; |
| | | border-radius: 0px 0 10px 0; |
| | | border: 0.5px solid #fb5100; |
| | | background: linear-gradient( |
| | | 186deg, |
| | | rgba(255, 129, 45, 0.08) 14.82%, |
| | | rgba(238, 67, 67, 0.08) 91.5% |
| | | ); |
| | | color: #fb5100; |
| | | font-size: 11px; |
| | | font-weight: 700; |
| | | line-height: 14px; |
| | | position: absolute; |
| | | top: -1px; |
| | | left: -1px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .phone-bill-recharge { |
| | | .recharge-button { |
| | | width: 100%; |
| | | margin: 20px 0; |
| | | |
| | | .recharge-button-inner { |
| | | display: flex; |
| | | .recharge-button-text { |
| | | margin-left: 10px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | $bole-size: map.deep-merge( |
| | | ( |
| | | 'body-padding-h': 28px, |
| | | 'body-padding-h2': 14px, |
| | | ), |
| | | $bole-size |
| | | ); |
New file |
| | |
| | | export * from './lifeRecharge'; |
| | | export * from './plugin'; |
New file |
| | |
| | | export class BlLifeRecharge { |
| | | getRechargeParValue(amount: number, rate: number) { |
| | | return (amount * rate).toFixed(2); |
| | | } |
| | | } |
New file |
| | |
| | | import { BlLifeRecharge } from './lifeRecharge'; |
| | | import { inject, shallowReactive } from 'vue'; |
| | | import type { InjectionKey, UnwrapNestedRefs, Ref } from 'vue'; |
| | | |
| | | export type LifeRechargeContext = { |
| | | blLifeRecharge: UnwrapNestedRefs<BlLifeRecharge>; |
| | | }; |
| | | |
| | | const clientKey: InjectionKey<LifeRechargeContext> = Symbol('blLifeRecharge'); |
| | | |
| | | export type VueLifeRechargePluginOptions = { |
| | | blLifeRecharge: BlLifeRecharge; |
| | | }; |
| | | |
| | | export const VueLifeRechargePlugin = { |
| | | install: (app: any, { blLifeRecharge }: VueLifeRechargePluginOptions) => { |
| | | app.provide(clientKey, { |
| | | blLifeRecharge: shallowReactive(blLifeRecharge), |
| | | }); |
| | | }, |
| | | }; |
| | | |
| | | export function useLifeRechargeContext() { |
| | | return inject(clientKey); |
| | | } |
New file |
| | |
| | | <template> |
| | | <Form |
| | | :model-value="form" |
| | | ref="formRef" |
| | | :rules="rules" |
| | | label-position="top" |
| | | class="phone-bill-recharge" |
| | | > |
| | | <FormItem label="选择运营商:" class="bole-form-item" prop="ispCode" required> |
| | | <RadioGroup v-model="form.ispCode" direction="horizontal"> |
| | | <BlRadio :label="key" v-for="(val, key) in IspCodeText" :key="key">{{ val }}</BlRadio> |
| | | </RadioGroup> |
| | | </FormItem> |
| | | <FormItem label="充值手机号" class="bole-form-item" prop="phone" required> |
| | | <Input |
| | | v-model.trim="form.phone" |
| | | class="bole-input-text" |
| | | placeholder="请填写您需要充值的手机号码" |
| | | type="text" |
| | | /> |
| | | </FormItem> |
| | | <FormItem label="选择充值金额" class="bole-form-item" prop="parValue" required> |
| | | <RadioGroup v-model="form.parValue" direction="horizontal" class="parValue-radio-group"> |
| | | <Radio |
| | | :label="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, rate) }}元</div> |
| | | </div> |
| | | <div class="discountTag">{{ rate * 100 }}折</div> |
| | | </div> |
| | | </Radio> |
| | | </RadioGroup> |
| | | </FormItem> |
| | | <div class="common-content"> |
| | | <nut-button class="recharge-button" type="primary" @click="recharge"> |
| | | <div class="recharge-button-inner"> |
| | | <div>¥{{ form.parValue }}</div> |
| | | <div class="recharge-button-text">立即充值</div> |
| | | </div> |
| | | </nut-button> |
| | | <RechargeTipsView :tips="tips" /> |
| | | </div> |
| | | <ConfirmDialog v-model:visible="confirmDialogVisible"> |
| | | <template #info> |
| | | <ConfirmDialogInfoItem label="充值账号" content="18858418480" /> |
| | | <ConfirmDialogInfoItem label="充值金额" :content="`¥${form.parValue}`" danger /> |
| | | <ConfirmDialogInfoItem label="优惠金额" :content="`¥${discountParValue}`" /> |
| | | <ConfirmDialogInfoItem label="实付金额" :content="`¥${realParValue}`" danger /> |
| | | </template> |
| | | </ConfirmDialog> |
| | | </Form> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { Form, FormItem, RadioGroup, Radio, Input, 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 { IspCodeText, IspCode } from '../../constants'; |
| | | import { useLifeRechargeContext } from '../../utils'; |
| | | import RechargeTipsView from '../../components/RechargeTipsView/RechargeTipsView.vue'; |
| | | import ConfirmDialog from '../../components/Dialog/ConfirmDialog.vue'; |
| | | import ConfirmDialogInfoItem from '../../components/Dialog/ConfirmDialogInfoItem.vue'; |
| | | |
| | | defineOptions({ |
| | | name: 'PhoneBillRecharge', |
| | | }); |
| | | |
| | | const form = reactive({ |
| | | ispCode: IspCode.yidong, |
| | | phone: '', |
| | | parValue: 100, |
| | | }); |
| | | |
| | | const rate = 0.96; |
| | | |
| | | const parValueList = [50, 100, 200]; |
| | | |
| | | const realParValue = computed(() => blLifeRecharge.getRechargeParValue(form.parValue, rate)); |
| | | const discountParValue = computed(() => form.parValue - Number(realParValue.value)); |
| | | |
| | | const { blLifeRecharge } = useLifeRechargeContext(); |
| | | |
| | | const rules = reactive<FormRules>({}); |
| | | |
| | | const formRef = ref<any>(null); |
| | | |
| | | function handleSubmit() { |
| | | if (!formRef.value) return; |
| | | formRef.value.validate().then(({ valid, errors }: any) => { |
| | | if (valid) { |
| | | } |
| | | }); |
| | | } |
| | | |
| | | const tips = [ |
| | | '平台提供慢充服务,订单提交后,话费将于0 - 24小时内到账。若未能按时到账,系统将自动发起退款。', |
| | | '充值期间,若同一号码款项未到账,请勿在其他平台重复充值;主副卡不可同时充值。因上述操作导致的资金损失,由用户自行承担。', |
| | | '本平台话费充值服务不适用于已停机号码。电信号码若有欠费,也无法完成充值。电信已完成维护的区域包括:广东、江苏、湖北、四川、江西、河北、河南、福建、辽宁。其它区域正在分批次进行维护中,在此期间可能会出现充值不成功并自动退款的情况,请您谅解。', |
| | | '如接到陌生来电,对方以缴费或误操作等理由要求处理款项,务必立即拉黑,谨防诈骗。', |
| | | '售后服务期为充值完成之日起3天。申请售后服务时,需提供录屏证据,请确认接受此要求后再下单,逾期平台不再受理售后申请。', |
| | | '充值发票由运营商提供,您可登录网上营业厅下载电子发票。', |
| | | ]; |
| | | |
| | | const confirmDialogVisible = ref(false); |
| | | |
| | | function recharge() { |
| | | confirmDialogVisible.value = true; |
| | | } |
| | | </script> |
| | |
| | | <template> |
| | | <MainCell title="生活缴费"> |
| | | <Grid square :gutter="20" :column-num="2"> |
| | | <GridItem class="publish-circle-friend-file-grid-item" text="话费"> |
| | | <Grid square :gutter="20" :column-num="2" class="recharge-grid-wrapper"> |
| | | <GridItem class="recharge-grid-item" text="话费" @click="emit('phoneBillRecharge')"> |
| | | <Dongdong /> |
| | | </GridItem> |
| | | <GridItem class="publish-circle-friend-file-grid-item" text="电费"> |
| | | <GridItem class="recharge-grid-item" text="电费" @click="emit('electricityBillRecharge')"> |
| | | <Dongdong /> |
| | | </GridItem> |
| | | </Grid> |
| | |
| | | |
| | | <script setup lang="ts"> |
| | | import MainCell from '../../components/Layout/MainCell.vue'; |
| | | // import Grid from '../../components/Grid/Grid.vue'; |
| | | import { Grid, GridItem } from '@nutui/nutui-taro'; |
| | | import { Dongdong } from '@nutui/icons-vue-taro'; |
| | | |
| | |
| | | // type Props = {}; |
| | | |
| | | // const props = withDefaults(defineProps<Props>(), {}); |
| | | |
| | | const emit = defineEmits<{ |
| | | (e: 'phoneBillRecharge'): void; |
| | | (e: 'electricityBillRecharge'): void; |
| | | }>(); |
| | | </script> |