Skip to content

Commit

Permalink
✨ feat(project): add countdown and payment
Browse files Browse the repository at this point in the history
  • Loading branch information
ishareme committed Jan 11, 2023
1 parent ed2db00 commit f669865
Show file tree
Hide file tree
Showing 19 changed files with 531 additions and 4 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"ali-oss": "^6.17.1",
"axios": "^1.2.2",
"cropperjs": "^1.5.13",
"dayjs": "^1.11.7",
"driver.js": "^0.9.8",
"file-saver": "^2.0.5",
"gsap": "^3.11.4",
Expand Down
9 changes: 9 additions & 0 deletions src/api/pay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Request from '@/utils/request';

const request = new Request();

export const getVipPayList = () => {
return request({
url: '/user/vip/pay/list',
});
};
Binary file added src/assets/images/alipay.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 89 additions & 0 deletions src/libs/Countdown/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<template>
<div>
<slot>
<p class="text-sm">
{{ showTime }}
</p>
</slot>
</div>
</template>

<script>
// 倒计时结束
const EMIT_FINISH = 'finish';
// 倒计时改变
const EMIT_CHANGE = 'change';
const INTERVAL_COUNT = 1000;
</script>
<script setup>
import { ref, watch, computed, onUnmounted } from 'vue';
import dayjs from './utils';
const props = defineProps({
// 毫秒 时间戳
time: {
type: Number,
required: true,
},
// 遵循dayjs 标准
format: {
type: String,
default: 'HH:mm:ss',
},
});
const emits = defineEmits([EMIT_FINISH, EMIT_CHANGE]);
// 倒计时时长
const duration = ref(0);
// 开始倒计时
let iterval = null;
const start = () => {
// 开始前结束下
close();
iterval = setInterval(() => {
durationFn();
}, INTERVAL_COUNT);
};
// 倒计时执行
const durationFn = () => {
duration.value -= INTERVAL_COUNT;
emits(EMIT_CHANGE, duration);
// 结束
if (duration.value <= 0) {
duration.value = 0;
emits(EMIT_FINISH);
close();
}
};
// 倒计时结束
const close = () => {
iterval && clearInterval(iterval);
};
// 显示时间
const showTime = computed(() => {
return dayjs.duration(duration.value).format(props.format);
});
// 开始
watch(
() => props.time,
(val) => {
duration.value = val;
start();
},
{ immediate: true }
);
// 组件销毁时候清理倒计时
onUnmounted(() => {
close();
});
</script>

<style lang="scss" scoped></style>
9 changes: 9 additions & 0 deletions src/libs/Countdown/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import duration from 'dayjs/plugin/duration';

dayjs.locale('zh');

dayjs.extend(duration);

export default dayjs;
7 changes: 5 additions & 2 deletions src/libs/TransitionRouterView/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@
<keep-alive :include="virtualTaskStack">
<component
:is="Component"
:class="{ 'fixed top-0 left-0 w-screen z-50': isAnimation }"
class="fixed top-0 left-0 w-screen"
:class="{
'fixed top-0 left-0 w-screen z-50': isMobileTerminal,
}"
:key="$route.fullPath"
/>
</keep-alive>
Expand All @@ -22,6 +25,7 @@
<script>
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { isMobileTerminal } from '@/utils/flexible.js';
// 无需监听路由的各种状态(在 PC 端下)
const NONE = 'none';
Expand Down Expand Up @@ -70,7 +74,6 @@ const transitionName = ref('');
router.beforeEach((to, from) => {
// 定义当前动画名称
transitionName.value = props.routerType;
console.log('[ transitionName.value ]', transitionName.value);
if (props.routerType === PUSH) {
// 入栈
virtualTaskStack.value.push(to.name);
Expand Down
8 changes: 8 additions & 0 deletions src/router/modules/mobile-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,12 @@ export default [
user: true,
},
},
{
path: '/member',
name: 'member',
component: () => import('@/views/member'),
meta: {
user: true,
},
},
];
8 changes: 8 additions & 0 deletions src/router/modules/pc-routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,14 @@ export default [
user: true,
},
},
{
path: '/member',
name: 'member',
component: () => import('@/views/member'),
meta: {
user: true,
},
},
],
},
{
Expand Down
2 changes: 1 addition & 1 deletion src/views/layout/components/header/profile/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const profileMenu = [
id: 1,
icon: 'vip-profile',
title: '升级VIP',
path: '/profile',
path: '/member',
},
{
id: 2,
Expand Down
2 changes: 2 additions & 0 deletions src/views/main/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import { useScroll } from '@vueuse/core';
import { ref, onActivated } from 'vue';
console.log('[ home组件渲染 ]');
const store = useStore();
const router = useRouter();
const onVipClick = () => {
store.commit('app/changeRouterType', 'push');
router.push('/member');
};
const onMyClick = () => {
store.commit('app/changeRouterType', 'push');
Expand Down
78 changes: 78 additions & 0 deletions src/views/member/components/PayMenuItem/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<!-- 单个的支付项 -->
<div
class="flex-none flex flex-col items-center w-[100px] mt-2 mr-2 py-3 border-[1px] hover:bg-orange-50 hover:border-orange-300 rounded-md relative cursor-pointer xl:w-[150px] xl:py-2"
:class="[
select
? 'bg-orange-50 dark:bg-orange-50/10 border-orange-300 '
: 'bg-white dark:bg-zinc-900 border-zinc-300 dark:border-zinc-500',
]"
@click="onItemClick"
>
<!-- 标题 -->
<p
class="text-base"
:class="[
select
? 'text-yellow-800 dark:text-orange-300'
: 'text-yellow-800 dark:text-zinc-300',
]"
>
{{ data.title }}
</p>
<!-- 价格 -->
<p
class="text-[32px] tracking-tighter font-sans font-bold"
:class="[
select
? 'text-yellow-800 dark:text-orange-300'
: 'text-yellow-800 dark:text-zinc-300',
]"
>
<span class="text-base">¥</span>
{{ data.price }}
</p>
<!-- 原价 -->
<p class="text-xs text-yellow-500 line-through">
¥{{ data.oldPrice }}
</p>
<!-- 热销 -->
<div
v-if="hot"
class="absolute right-[-1px] top-[-12px] h-[22px] w-[48px] leading-[22px] text-center text-yellow-700 bg-gradient-to-r from-orange-300 to-orange-100 text-[12px] rounded-tr-[10px] rounded-bl-[10px]"
>
热销
</div>
</div>
</template>

<script>
const EMITS_CLICK = 'click';
</script>

<script setup>
const props = defineProps({
// 数据源
data: {
type: Object,
required: true,
},
// 是否热选
hot: {
type: Boolean,
},
// 是否被选中
select: {
type: Boolean,
default: false,
},
});
const emits = defineEmits([EMITS_CLICK]);
const onItemClick = () => {
emits(EMITS_CLICK, props.data);
};
</script>

<style lang="scss" scoped></style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<div class="py-2 h-[80vh] flex flex-col">
<h2
class="text-xl text-zinc-900 dark:text-zinc-200 font-bold mb-2 px-1"
>
选择支付方式
</h2>
<!-- 支付宝 -->
<div
class="flex items-center px-2 py-2 border-b border-b-zinc-200 dark:border-b-zinc-600 active:bg-zinc-200 dark:active:bg-zinc-900"
@click="onAlipay"
>
<img class="w-4 h-4" src="@/assets/images/alipay.png" alt="" />
<p class="text-xl ml-1 text-zinc-800 dark:text-zinc-200">支付宝</p>
</div>
</div>
</template>

<script setup>
// import { alipay } from '@/utils/pay';
// const props = defineProps({
// payData: {
// required: true,
// type: Object,
// },
// });
const onAlipay = () => {
// alipay(props.payData.title, props.payData.desc);
};
</script>
48 changes: 48 additions & 0 deletions src/views/member/components/Payment/MobilePayment/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<template>
<div
class="fixed left-0 bottom-0 w-screen text-center bg-white dark:bg-zinc-800 xl:hidden"
>
<!-- 特惠提示 -->
<Discounts />
<!-- 支付 -->
<div class="flex justify-between text-xs px-1 py-0.5">
<div class="text-left text-zinc-900 dark:text-zinc-200">
<p class="">
券后合计:<span
class="text-red-600 text-[16px] font-sans font-medium"
>¥</span
><span
class="text-red-600 text-[22px] font-sans font-medium"
>9</span
>
</p>
<p class="text-red-600">优惠券:限时立减 ¥10</p>
</div>
<HButton
class="w-[120px]"
:isActiveAnim="false"
@click="onConfirmClick"
>
立即开通
</HButton>
</div>
<!-- TODO: popup -->
<Popup v-model="isOpenPopup" class="rounded-tl rounded-tr">
<!-- <mobile-pay-select-vue :payData="payData" /> -->
<MobilePaymentSelect />
</Popup>
</div>
</template>

<script setup>
import { ref } from 'vue';
import Discounts from '../discounts.vue';
import MobilePaymentSelect from './MobilePaymentSelect';
const isOpenPopup = ref(false);
const onConfirmClick = () => {
isOpenPopup.value = true;
};
</script>

<style lang="scss" scoped></style>
Loading

0 comments on commit f669865

Please sign in to comment.