wip
This commit is contained in:
1
components.d.ts
vendored
1
components.d.ts
vendored
@@ -107,6 +107,7 @@ declare module 'vue' {
|
||||
IconIxWechatLogo: typeof import('~icons/ix/wechat-logo')['default']
|
||||
IconPhExportLight: typeof import('~icons/ph/export-light')['default']
|
||||
IconSimpleIconsWechat: typeof import('~icons/simple-icons/wechat')['default']
|
||||
IconStreamlineDiscountPercentCoupon: typeof import('~icons/streamline/discount-percent-coupon')['default']
|
||||
IconSystemUiconsImport: typeof import('~icons/system-uicons/import')['default']
|
||||
InputNumber: typeof import('./src/components/base/InputNumber.vue')['default']
|
||||
List: typeof import('./src/components/list/List.vue')['default']
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
"@iconify-json/qlementine-icons": "^1.2.11",
|
||||
"@iconify-json/ri": "^1.2.5",
|
||||
"@iconify-json/simple-icons": "^1.2.48",
|
||||
"@iconify-json/streamline": "^1.2.5",
|
||||
"@iconify-json/system-uicons": "^1.2.4",
|
||||
"@types/file-saver": "^2.0.7",
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
|
||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -96,6 +96,9 @@ importers:
|
||||
'@iconify-json/simple-icons':
|
||||
specifier: ^1.2.48
|
||||
version: 1.2.48
|
||||
'@iconify-json/streamline':
|
||||
specifier: ^1.2.5
|
||||
version: 1.2.5
|
||||
'@iconify-json/system-uicons':
|
||||
specifier: ^1.2.4
|
||||
version: 1.2.4
|
||||
@@ -538,6 +541,9 @@ packages:
|
||||
'@iconify-json/simple-icons@1.2.48':
|
||||
resolution: {integrity: sha512-EACOtZMoPJtERiAbX1De0asrrCtlwI27+03c9OJlYWsly9w1O5vcD8rTzh+kDPjo+K8FOVnq2Qy+h/CzljSKDA==}
|
||||
|
||||
'@iconify-json/streamline@1.2.5':
|
||||
resolution: {integrity: sha512-u6l9BOJoIIPjjDXWl6D/hPDzeBk5WiaEHZ+U9SbkQ14N9hgotaYyIZVMfgF175CG1TTS06j8k15D3FM2OYaFIw==}
|
||||
|
||||
'@iconify-json/system-uicons@1.2.4':
|
||||
resolution: {integrity: sha512-9WB9dmEm+TRCXI5Ml2IY8zQAPZES8euKxY0VOaf8D6E6ZaEr7ztO6DChMlGg7qWECs3m3FjFUqNgBx8ZpB+djw==}
|
||||
|
||||
@@ -4179,6 +4185,10 @@ snapshots:
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
|
||||
'@iconify-json/streamline@1.2.5':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
|
||||
'@iconify-json/system-uicons@1.2.4':
|
||||
dependencies:
|
||||
'@iconify/types': 2.0.0
|
||||
|
||||
@@ -36,3 +36,7 @@ export function orderCreate(params) {
|
||||
export function orderStatus(params) {
|
||||
return http('/member/orderStatus', null, params, 'get')
|
||||
}
|
||||
|
||||
export function couponInfo(params) {
|
||||
return http('/member/couponInfo', null, params, 'get')
|
||||
}
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import BasePage from '@/components/BasePage.vue'
|
||||
import BaseButton from '@/components/BaseButton.vue'
|
||||
import {useRouter} from 'vue-router'
|
||||
import {useUserStore} from '@/stores/auth.ts'
|
||||
import {User} from "@/apis/user.ts";
|
||||
import {computed, onMounted, onUnmounted, ref, watch} from "vue";
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useUserStore } from '@/stores/auth.ts'
|
||||
import { User } from "@/apis/user.ts";
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from "vue";
|
||||
import Header from "@/components/Header.vue";
|
||||
import {LevelBenefits, levelBenefits, orderCreate, orderStatus} from "@/apis/member.ts";
|
||||
import { couponInfo, LevelBenefits, levelBenefits, orderCreate, orderStatus } from "@/apis/member.ts";
|
||||
import Radio from "@/components/base/radio/Radio.vue";
|
||||
import RadioGroup from "@/components/base/radio/RadioGroup.vue";
|
||||
import {APP_NAME} from "@/config/env.ts";
|
||||
import { APP_NAME } from "@/config/env.ts";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
import {_dateFormat, _nextTick} from "@/utils";
|
||||
import { _dateFormat, _nextTick } from "@/utils";
|
||||
import InputNumber from "@/components/base/InputNumber.vue";
|
||||
import dayjs from "dayjs";
|
||||
import BaseInput from "@/components/base/BaseInput.vue";
|
||||
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
@@ -94,7 +95,7 @@ const totalPrice = $computed(() => (Number(duration) * Number(selectPlan?.price)
|
||||
const startDate = $computed(() => {
|
||||
if (member?.active) {
|
||||
return member.endDate
|
||||
}else {
|
||||
} else {
|
||||
return _dateFormat(Date.now())
|
||||
}
|
||||
})
|
||||
@@ -134,6 +135,9 @@ function goPurchase(plan: Plan) {
|
||||
let startLoop = $ref(false)
|
||||
let orderNo = $ref('')
|
||||
let timer: number = $ref()
|
||||
let showCouponInput = $ref(false)
|
||||
let couponCode = $ref('')
|
||||
let discount = $ref(1)
|
||||
|
||||
watch(() => startLoop, (n) => {
|
||||
if (n) {
|
||||
@@ -146,8 +150,10 @@ watch(() => startLoop, (n) => {
|
||||
userStore.init()
|
||||
startLoop = false
|
||||
selectedPlanId = undefined
|
||||
clearInterval(timer)
|
||||
}
|
||||
} else {
|
||||
startLoop = false
|
||||
Toast.error(res.msg || '付款失败')
|
||||
}
|
||||
})
|
||||
}, 1000)
|
||||
@@ -179,22 +185,33 @@ async function handlePayment() {
|
||||
loading = false
|
||||
}
|
||||
|
||||
async function handleCoupon() {
|
||||
if (showCouponInput) {
|
||||
let res = await couponInfo({couponCode})
|
||||
if (res.success) {
|
||||
discount = res.data.discount
|
||||
} else {
|
||||
Toast.error(res.msg || '优惠券无效')
|
||||
}
|
||||
} else {
|
||||
showCouponInput = true
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasePage>
|
||||
<div class="space-y-6">
|
||||
<div>
|
||||
<div class="card bg-reverse-white">
|
||||
<Header title="会员介绍"></Header>
|
||||
<div class="center">
|
||||
<div>
|
||||
<div class="text-lg flex items-center" v-for="f in data.benefits" :key="f.name">
|
||||
<IconFluentCheckmarkCircle20Regular class="mr-2 text-green-600"/>
|
||||
<span>
|
||||
<div class="grid grid-cols-3 grid-rows-3 gap-3">
|
||||
<div class="text-lg items-center" v-for="f in data.benefits" :key="f.name">
|
||||
<IconFluentCheckmarkCircle20Regular class="mr-2 text-green-600"/>
|
||||
<span>
|
||||
<span>{{ f.name }}</span>
|
||||
<span v-if="f.value !== 'true'">{{ `(${f.value}${f.unit ?? ''})` }}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -217,9 +234,9 @@ async function handlePayment() {
|
||||
<span>自动续费已开启</span>
|
||||
</div>
|
||||
<BaseButton
|
||||
size="small"
|
||||
type="info"
|
||||
@click="toggleAutoRenew">
|
||||
size="small"
|
||||
type="info"
|
||||
@click="toggleAutoRenew">
|
||||
关闭
|
||||
</BaseButton>
|
||||
</div>
|
||||
@@ -249,11 +266,11 @@ async function handlePayment() {
|
||||
开启自动续费,可随时关闭
|
||||
</div>
|
||||
<BaseButton
|
||||
class="w-full mt-4"
|
||||
size="large"
|
||||
:type="(p.id === currentPlan?.id || p.id === selectedPlanId) ? 'primary' : 'info'"
|
||||
:disabled="p.id === currentPlan?.id"
|
||||
@click="goPurchase(p)">
|
||||
class="w-full mt-4"
|
||||
size="large"
|
||||
:type="(p.id === currentPlan?.id || p.id === selectedPlanId) ? 'primary' : 'info'"
|
||||
:disabled="p.id === currentPlan?.id"
|
||||
@click="goPurchase(p)">
|
||||
{{ getPlanButtonText(p) }}
|
||||
</BaseButton>
|
||||
</div>
|
||||
@@ -269,6 +286,18 @@ async function handlePayment() {
|
||||
<p class="">选择支付方式完成订单</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="center">
|
||||
<div class="card bg-reverse-white gap-6 flex justify-between items-center w-7/10">
|
||||
<div class="center gap-2" v-if="!showCouponInput">
|
||||
<IconStreamlineDiscountPercentCoupon/>
|
||||
<span>有抵用券?</span>
|
||||
</div>
|
||||
<BaseInput v-else v-model="couponCode" placeholder="请输入优惠券" autofocus/>
|
||||
<BaseButton size="large" @click="handleCoupon">{{ showCouponInput ? '确定' : '在此兑换!' }}</BaseButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8">
|
||||
<!-- Left Card: Payment Method Selection -->
|
||||
@@ -277,11 +306,11 @@ async function handlePayment() {
|
||||
<RadioGroup v-model="selectedPaymentMethod">
|
||||
<div class="space-y-3 w-full">
|
||||
<div
|
||||
v-for="method in paymentMethods"
|
||||
:key="method.id"
|
||||
@click=" selectedPaymentMethod = method.id"
|
||||
class="flex p-4 border rounded-lg cp transition-all duration-200"
|
||||
:class="[
|
||||
v-for="method in paymentMethods"
|
||||
:key="method.id"
|
||||
@click=" selectedPaymentMethod = method.id"
|
||||
class="flex p-4 border rounded-lg cp transition-all duration-200"
|
||||
:class="[
|
||||
selectedPaymentMethod === method.id
|
||||
? 'border-blue-500 bg-blue-50'
|
||||
: 'border-gray-200 hover:border-gray-300 hover:bg-gray-50'
|
||||
@@ -339,12 +368,12 @@ async function handlePayment() {
|
||||
|
||||
<!-- Payment Button -->
|
||||
<BaseButton
|
||||
class="w-full"
|
||||
size="large"
|
||||
:loading="loading || startLoop"
|
||||
:type="!!selectedPaymentMethod ? 'primary' : 'info'"
|
||||
:disabled="!selectedPaymentMethod"
|
||||
@click="handlePayment"
|
||||
class="w-full"
|
||||
size="large"
|
||||
:loading="loading || startLoop"
|
||||
:type="!!selectedPaymentMethod ? 'primary' : 'info'"
|
||||
:disabled="!selectedPaymentMethod"
|
||||
@click="handlePayment"
|
||||
>
|
||||
付款
|
||||
</BaseButton>
|
||||
|
||||
Reference in New Issue
Block a user