feat:生日弹框

This commit is contained in:
dzc committed 2026-01-30 20:38:04 +08:00
1 parent a1e7774f3e
commit 26a6077dd7
11 files changed
+288 -33

No files matched your search

+7
View File
@@ -119,6 +119,13 @@
"disableScroll": true
}
},
{
"path": "cancel-qrcode",
"style": {
"navigationBarTitleText": "活动",
"disableScroll": true
}
},
{
"path": "my-act-list",
"style": {
+79
View File
@@ -0,0 +1,79 @@
<script setup lang="ts">
import { reactive, ref, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import uqrcode from "@@/utils/uqrcode"
import { applyApi } from "@@/api"
const showQrCodeDialog = ref(false)
const state = reactive({
actId: ''
})
onLoad((options: any) => {
state.actId = options.actId
getQrcodeDetail()
})
const getQrcodeDetail = async () => {
const { data = {} } = await applyApi.getCodeById({ id: state.actId })
if (!data.shortCode) {
uni.showToast({ title: "优惠券错误", icon: "none" })
return
}
uqrcode.make({
canvasId: "qrcodeId",
text: data.shortCode,
size: 100,
margin: 0,
success: (res) => { },
complete: () => { },
})
}
const doViewQrcode = async () => {
const { data = {} } = await applyApi.getCodeById({ id: state.actId })
if (!data.shortCode) {
uni.showToast({ title: "优惠券错误", icon: "none" })
return
}
showQrCodeDialog.value = true
uqrcode.make({
canvasId: "viewQrcodeId",
text: data.shortCode,
size: 200,
margin: 0,
success: (res) => { },
complete: () => { },
})
}
</script>
<template>
<crud-layout mainIsScroll tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<view class="size-full flex-row-center relative">
<image class="w-650rpx h-1030rpx bg-white p-10rpx rounded-12rpx" src="/static/icon/birthday_coupon.jpg"
mode="widthFix" />
<view class="z-100 size-120px absolute left-50rpx top-760rpx flex-row-center bg-white p-20rpx rounded-12rpx"
@tap="doViewQrcode">
<canvas canvas-id="qrcodeId" class="size-100px" />
</view>
</view>
<tm-drawer z-index="100" v-model:show="showQrCodeDialog" title="兑换券核销二维码" :show-close="true" position="bottom"
size="60%">
<view class="flex-col-center">
<view class="h-80rpx" />
<canvas canvas-id="viewQrcodeId" class="size-200px" />
</view>
</tm-drawer>
</crud-layout>
</template>
<style lang="scss">
.layout_main {
padding: 0 !important;
}
</style>
+35 -6
View File
@@ -52,8 +52,6 @@
{{ state.actDetail.description }}
</view>
</view>
<view v-if="state.couponInfo.actStatus == '2'"
class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30">
已 核 销
@@ -66,30 +64,35 @@
</view>
</template>
</view>
<template #main-bottom>
<view class="text-center">
<tm-button class="px-32 m-2" @click="doQrcode">我的核销码</tm-button>
</view>
</template>
</crud-layout>
<modify-user ref="modifyUserRef" warnText="填写出生日期即可领取生日兑换券" />
</template>
<script setup lang="ts">
import { reactive, ref } from "vue"
import { reactive, ref, nextTick } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { actCancel, actComApi, actCouponApi } from "@/sheep/api"
import { actCancel, actComApi, actCouponApi, userApi } from "@/sheep/api"
import { hooks, router } from "@/sheep"
import { serviceEnum } from "@@/constant"
import { serviceEnum, storageConstant } from "@@/constant"
import ModifyUser from "@@/components/modify-user.vue"
const { actUserReceiveEnum, actCouponTypeEnum } = serviceEnum
const modifyUserRef = ref<any>(null)
const state = reactive<any>({
actId: "",
actType: "",
actUserReceiveStatus: "", // 是否已领取
actDetail: {}, // 优惠券详情
couponInfo: {}, // 优惠券信息
userDetail: {},
})
onLoad((option: any) => {
@@ -102,6 +105,9 @@ onLoad((option: any) => {
if (actType == "CANCEL_ACT") {
getCouponInfo()
}
if (actType == "COUPON_ACT") {
specialDispose()
}
})
// 获取优惠券详情
@@ -179,6 +185,12 @@ const getCancelReceive = async () => {
// 优惠券活动
const getCouponReceive = async () => {
// 特殊处理
if (state.actDetail.uniqueCode == "1qRgFo") {
// 判断用户有没有输入生日
const isEligible = await specialDispose()
if (!isEligible) return
}
try {
uni.showLoading({ title: "正在领取...", mask: true })
const { code, msg }: any = await actCouponApi.receive({
@@ -194,6 +206,23 @@ const getCouponReceive = async () => {
}
}
const specialDispose = async (): Promise<boolean> => {
await getUserInfo()
if (!state.userDetail.birthday) {
nextTick(() => {
modifyUserRef.value.open()
})
return false
}
return true
}
const getUserInfo = async () => {
const { data: userData } = await userApi.userInfo()
state.userDetail = userData?.sysUser ?? {}
uni.setStorageSync(storageConstant.USERINFO, userData)
}
const doQrcode = () => {
router.jump("/pages/merchant/my-act-list")
}
+33 -14
View File
@@ -2,28 +2,22 @@
import { reactive, ref, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { router } from "@/sheep"
import uqrcode from "@@/utils/uqrcode"
import * as CryptoJS from "crypto-js"
import { actCancel, actComApi, actCouponApi } from "@@/api"
import { actCancel, actComApi, actCouponApi, applyApi } from "@@/api"
import { hooks } from "@/sheep"
import { serviceEnum } from "@@/constant"
import zTabs from "@@/components/other/z-tabs/z-tabs.vue"
import CancelCard from "./components/cancel-card.vue"
import CouponCard from "./components/coupon-card.vue"
const { actCouponTypeEnum } = serviceEnum
const data = {
coupons: [
{ id: "c1", name: "食堂生日券", faceValue: 89, minPoint: 445, scope: "指定商品", btn: "立即领取", picUrl: "https://images.unsplash.com/photo-1511699443500-9e3e0bbfa3a6?w=240&q=80" },
{ id: "c2", name: "健康惊喜券", faceValue: 40, minPoint: 400, scope: "指定分类", btn: "立即领取", picUrl: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=240&q=80" },
{ id: "c3", name: "商品优惠券", faceValue: 72, minPoint: 399, scope: "指定商户", btn: "立即领取", picUrl: "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?w=240&q=80" },
{ id: "c4", name: "店铺优惠券", faceValue: 55, minPoint: 350, scope: "指定商户", btn: "立即领取", picUrl: "https://images.unsplash.com/photo-1471357674240-e1a485acb3e1?w=240&q=80" },
],
}
const pageRef = ref<any>(null)
const showQrCodeDialog = ref(false)
@@ -76,11 +70,36 @@ const doTab = (e: any) => {
getUserTotal()
}
const doVisibleQrcode = (detail: any) => {
const doVisibleQrcode = async (detail: any) => {
const { type, detail: actDetail } = detail
console.log("生成二维码:", type, actDetail);
// 查询优惠券对应的短码
if (type == "ACT_COUPON") {
// 特殊情况
// 1. 生日
if (actDetail.actUniquecode == "1qRgFo") {
// 生日活动,直接跳转
router.jump("/pages/merchant/cancel-qrcode", { actId: actDetail.id })
return
}
try {
const { data = {} } = await applyApi.getCodeById({ id: actDetail.id })
if (!data.shortCode) {
uni.showToast({ title: "优惠券错误", icon: "none" })
return
}
showQrCodeDialog.value = true
uqrcode.make({
canvasId: "qrcodeId",
text: data.shortCode,
size: 200,
margin: 0,
success: (res) => { },
complete: () => { },
})
} catch (error) {
console.log("|查询优惠券对应的短码|意外的错误error:", error);
}
}
if (type == "ACT_CANCEL") {
genVerificationCode({ cancelId: actDetail.id })
@@ -91,8 +110,8 @@ const doVisibleQrcode = (detail: any) => {
const getUserTotal = async () => {
try {
const { data = {} }: any = await actComApi.userTotal({})
state.tabs[0].badge.count = data.couponCount || 0
state.tabs[1].badge.count = data.cancelCount || 0
state.tabs[0].badge.count = data?.couponCount ?? null
state.tabs[1].badge.count = data?.cancelCount ?? null
} catch (error) {
console.log("|用户参加活动的数量统计|意外的错误error:", error);
}
+31 -9
View File
@@ -1,14 +1,25 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<template #main-top>
<view class="flex items-center py-3 px-5">
<image v-if="state.userInfo?.sysUser?.avatar" class="size-100rpx rounded-full"
:src="filePath(state.userInfo.sysUser.avatar)" mode="aspectFill" />
<image v-else class="w-100rpx h-100rpx rounded-full" src="/static/icon/default-avatar.png"
mode="aspectFill" />
<view class="ml-30rpx" v-if="state.userInfo?.sysUser?.userId">
<view class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</view>
<view class="sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</view>
<view class="flex items-center py-3 px-5" @tap="doUserArea">
<view class="flex items-center" v-if="state.userInfo?.sysUser?.userId">
<image v-if="state.userInfo?.sysUser?.avatar" class="size-100rpx rounded-full"
:src="filePath(state.userInfo.sysUser.avatar)" mode="aspectFill" />
<image v-else class="w-100rpx h-100rpx rounded-full" src="/static/icon/default-avatar.png"
mode="aspectFill" />
<view class="ml-30rpx">
<view class="flex items-center">
<view class="sub-text-30">{{ state.userInfo?.sysUser?.name }}</view>
<view v-if="state.userInfo?.sysUser?.birthday"
class="ml-20rpx flex items-center bg-#FFFFFF px-16rpx py-6rpx rounded-full shadow-sm">
<image class="size-32rpx mr-8rpx" src="/static/icon/birthday.png" mode="aspectFit" />
<text class="text-24rpx color-blue font-bold lh-1">
{{ dayjs(state.userInfo.sysUser.birthday).format("MM-DD") }}
</text>
</view>
</view>
<view class="m-t-5rpx sub-text-26">ID {{ state.userInfo?.sysUser?.userId }}</view>
</view>
</view>
<view v-else class="flex items-center ml-30rpx" @tap="onTabLogin">
<text class="sub-text-32">请先登录</text>
@@ -50,6 +61,8 @@
</view>
</crud-layout>
<modify-user ref="modifyUserRef" warnText="填写出生日期即可领取生日兑换券" @close="storage.getUserInfo" />
<tm-modal :show="state.actModalShow" :showCancel="false" title="核销活动兑换券" zIndex="999" @confirm="" @cancel=""
@close="">
<view class="text-center text-28">是否核销该活动兑换券?</view>
@@ -64,7 +77,8 @@
</template>
<script setup lang="ts">
import { reactive } from "vue"
import { reactive, ref } from "vue"
import dayjs from "dayjs"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { isEmpty } from "radash"
import { filePath } from "@@/utils/file"
@@ -74,6 +88,10 @@ import { actCancel, userApi } from "@@/api"
import { isDevEnv } from "@/sheep/utils/app"
import { APPENV } from "@/sheep/constant"
import ModifyUser from "@@/components/modify-user.vue"
const modifyUserRef = ref<any>()
const state = reactive<any>({
wallet: [],
userInfo: {},
@@ -96,6 +114,10 @@ const STORAGE_KEYS = {
USER_INFO: constant.storageConstant.USERINFO,
}
const doUserArea = () => {
modifyUserRef.value?.open()
}
const storage = {
// 获取存储的用户信息
getUserInfo: () => {
+2 -4
View File
@@ -62,11 +62,9 @@ const doSubmit = async () => {
</tm-form-item>
</tm-form>
</view>
<view
v-if="state.detailType != 'view'"
<view v-if="state.detailType != 'view'"
class="bg-#0094ff p-y-20rpx text-center rounded-40rpx m-x-30rpx m-t-60rpx sub-text-30 color-white!"
@tap="doSubmit"
>
@tap="doSubmit">
登录
</view>
</crud-layout>
+6
View File
@@ -19,6 +19,12 @@ export default {
method: "GET",
params,
}),
getCodeById: (params: any) =>
request({
url: "wallet/wallet-code-use/app/user-code",
method: "GET",
params,
}),
foreignApply: (data: any) =>
request({
url: "wallet/wallet-foreign/app/apply",
+7
View File
@@ -91,4 +91,11 @@ export default {
method: "POST",
data,
}),
// 用户修改个人资料
appModifyUser: (data: any) =>
request({
url: "/admin/user/app/modify",
method: "POST",
data,
}),
}
+88
View File
@@ -0,0 +1,88 @@
<script setup lang="ts">
import { reactive, ref, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { storageConstant } from "@@/constant"
import { userApi } from '@@/api'
const emit = defineEmits(["close"])
type ModifyUserProps = {
warnText?: string
}
const props = withDefaults(defineProps<ModifyUserProps>(), {
warnText: ''
})
const formRef = ref<any>(null)
const showQrCodeDialog = ref(false)
const form = reactive({
birthday: ""
})
const rules = {
birthday: [{ required: true, message: '请输入生日' }],
}
// 修改用户信息
const doFormSubmit = async () => {
formRef.value.submit()
const { isPass } = formRef.value.validate()
if (!isPass) return
uni.showLoading({ title: "修改中...", mask: true })
try {
const res: any = await userApi.appModifyUser({ ...form })
if (res.code != 0) {
uni.showToast({ title: res.msg ?? "修改失败", icon: "none" })
return
}
uni.showToast({ title: "修改成功", icon: "success" })
// 存入缓存
const { data: userData } = await userApi.userInfo()
uni.setStorageSync(storageConstant.USERINFO, userData)
showQrCodeDialog.value = false
setTimeout(() => uni.hideLoading(), 1000);
} catch (error) {
console.log("|修改用户信息|意外的错误error:", error);
uni.hideLoading()
}
}
const open = () => {
const user = uni.getStorageSync(storageConstant.USERINFO)
if (user && user.sysUser) {
form.birthday = user.sysUser.birthday
}
showQrCodeDialog.value = true
}
defineExpose({
open
})
</script>
<template>
<tm-drawer z-index="100" v-model:show="showQrCodeDialog" title="编辑个人资料" :show-close="true" position="bottom"
size="50%" @close="emit('close')">
<view v-if="warnText" class="py-20rpx">
<tm-alert status="warn" :showClose="false" :margin="[]">{{ warnText }}</tm-alert>
</view>
<view class="card p-x-30rpx p-y-40rpx">
<view class="h-30rpx" />
<tm-form ref="formRef" v-model="form" :rules="rules">
<tm-form-item name="birthday" label="出生日期" :show-bottom="false">
<tm-picker-date v-model="form.birthday" v-model:model-str="form.birthday" format="YYYY-MM-DD"
start="1950-1-1" end="2030-12-31">
<tm-input v-model="form.birthday" show-clear>
</tm-input>
</tm-picker-date>
</tm-form-item>
<view class="h-30rpx" />
<tm-button block @tap="doFormSubmit">修改</tm-button>
</tm-form>
</view>
</tm-drawer>
</template>
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB