# Conflicts:
#	.env
This commit is contained in:
zjf committed 2026-02-02 15:59:59 +08:00
commit 1211484463
31 files changed
+1274 -340

No files matched your search

+3 -3
View File
@@ -21,14 +21,14 @@ VITE_OAUTH2_APP_CLIENT='mini:mini'
#VITE_APP_DEV_SERVICE = http://59.202.170.152:81/api # 信创线上
# VITE_APP_DEV_SERVICE = http://192.168.101.174:9999 # 邓-本地
VITE_APP_DEV_SERVICE = http://127.0.0.1:9999 # 邓-本地
#VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
# VITE_APP_DEV_SERVICE = http://123.157.250.162:8089/api # 测试线上
# --------------------------- 开发环境 图片访问基础地址 ---------------------------
# VITE_IMAGE_DEV_PATH = https://stgl.pj.gov.cn/api # 域名线上
#VITE_IMAGE_DEV_PATH = http://59.202.170.152:81/api # 信创线上
# VITE_IMAGE_DEV_PATH = http://192.168.101.174:9999 # 邓-本地
VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
#VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
#VITE_IMAGE_DEV_PATH = http://127.0.0.1:9999
VITE_IMAGE_DEV_PATH = http://123.157.250.162:8089/api # 测试线上
# --------------------------- 生产环境 api地址 ----------------------------------
VITE_APP_PROD_SERVICE = https://stgl.pj.gov.cn/api # 域名线上
+1 -1
View File
@@ -90,4 +90,4 @@
"vite": "5.2.8",
"vue-tsc": "^1.0.24"
}
}
}
+15 -1
View File
@@ -119,6 +119,20 @@
"disableScroll": true
}
},
{
"path": "cancel-qrcode",
"style": {
"navigationBarTitleText": "活动",
"disableScroll": true
}
},
{
"path": "my-act-list",
"style": {
"navigationBarTitleText": "我参加的活动",
"disableScroll": true
}
},
{
"path": "merchant-activity",
"style": {
@@ -706,4 +720,4 @@
}
]
}
}
}
+12 -27
View File
@@ -1,23 +1,18 @@
<template>
<crud-layout bg="/static/page/blue-bg.png">
<view class="bg-white rounded-20rpx my-20rpx font-bold">
<z-tabs
:list="[
{ name: '浙政钉支付', value: 1 },
{ name: '支付宝支付', value: 2, disabled: true },
]"
bar-width="150"
:active-style="{
<z-tabs :list="[
{ name: '浙政钉支付', value: 1 },
{ name: '支付宝支付', value: 2, disabled: true },
]" bar-width="150" :active-style="{
fontSize: '30rpx',
}" :inactive-style="{
fontSize: '30rpx',
}"
:inactive-style="{
fontSize: '30rpx',
}"
@change="payMethodTabChange"
/>
}" @change="payMethodTabChange" />
</view>
<tm-sheet v-if="!state.isUseDoor && state.isUseDoorTip" borderWidth="2" :margin="[0, 20]" padding="10" color="#0094FF22">
<tm-sheet v-if="!state.isUseDoor && state.isUseDoorTip" borderWidth="2" :margin="[0, 20]" padding="10"
color="#0094FF22">
<view class="flex items-center justify-between pl-4">
<tm-text font-size="30 " color="#0779FD">{{ state.isUseDoorTip }}</tm-text>
<tm-button size="s" @click="goRecharge">去充值</tm-button>
@@ -55,18 +50,8 @@
</view>
</template>
<tm-modal
v-model:show="state.show"
:overlayClick="false"
title="你是否同意授权"
position="bottom"
:showCancel="true"
height="800rpx"
cancelText="拒绝"
confirmText="同意"
@confirm="appAuthHardDoor(1)"
@cancel="appAuthHardDoor(0)"
>
<tm-modal v-model:show="state.show" :overlayClick="false" title="你是否同意授权" position="bottom" :showCancel="true"
height="800rpx" cancelText="拒绝" confirmText="同意" @confirm="appAuthHardDoor(1)" @cancel="appAuthHardDoor(0)">
<tm-text color="#999999">{{ state.authDesc }}</tm-text>
</tm-modal>
</crud-layout>
@@ -147,7 +132,7 @@ const openDoor = async () => {
}
// 支付方式tab改变
const payMethodTabChange = (e: number) => {}
const payMethodTabChange = (e: number) => { }
// 确认或拒绝协议
const appAuthHardDoor = async (type: 1 | 0) => {
+25 -11
View File
@@ -6,7 +6,8 @@
{{ detail.title }}
</view>
<view class="meta">
<!-- <text class="type-tag" :class="getTypeClass(detail.type)">{{ getTypeLabel(detail.type) }}</text>-->
<text v-if="false" class="type-tag" :class="getTypeClass(detail.type)">{{ getTypeLabel(detail.type)
}}</text>
<text class="time">{{ formatTime(detail.createTime) }}</text>
<text class="view-count">浏览 {{ detail.viewCount }}</text>
</view>
@@ -18,7 +19,8 @@
<view v-if="detail.attachments && detail.attachments.length > 0" class="attachments">
<view class="attachment-title">附件</view>
<view v-for="(file, index) in detail.attachments" :key="index" class="attachment-item" @click="downloadFile(file)">
<view v-for="(file, index) in detail.attachments" :key="index" class="attachment-item"
@click="downloadFile(file)">
<text class="file-name">{{ file.name }}</text>
<text class="file-size">{{ formatFileSize(file.size) }}</text>
</view>
@@ -30,21 +32,33 @@
<script setup lang="ts">
import { computed, ref } from "vue"
import { onLoad } from "@dcloudio/uni-app"
import { actCancel, noticeApi } from "@/sheep/api"
import { actCancel, actComApi, noticeApi } from "@/sheep/api"
const noticeId = ref("")
const detail = ref<any>({})
const actDetail = ref<any>({})
const actDetail = ref<any>({
actId: "",
actType: "",
detail: {
onLoad(async (option: any) => {
const { id } = option
if (!id) return uni.showToast({ title: "参数错误", icon: "error" })
const { data = {} }: any = await actCancel.getDetailByNoticeId({ id })
actDetail.value = data
}
})
// 获取活动详情
const getActDetail = async () => {
if (!noticeId.value) return
try {
const { data = {} }: any = await actComApi.getActByNotifyId({ notifyId: noticeId.value })
actDetail.value = data
} catch (error) {
console.log("|获取活动详情|,以外的错误error:", error);
}
}
const goGetCoupon = () => {
uni.navigateTo({ url: `/pages/merchant/merchant-activity?actId=${actDetail.value.id}&mchId=${actDetail.value.mchId}` })
uni.navigateTo({ url: `/pages/merchant/merchant-activity?actId=${actDetail.value.actId}&actType=${actDetail.value.actType}` })
}
const nodes = computed(() => {
@@ -110,7 +124,7 @@ onLoad(async (options: any) => {
const id = options.id
if (!id) return
noticeId.value = id
getActDetail()
try {
// 增加浏览量
await noticeApi.addNoticeView(id)
+80
View File
@@ -0,0 +1,80 @@
<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 tabBarType="just-flot-back" bg="/static/page/blue-bg.png">
<view class="h-30rpx"></view>
<view class="size-full relative">
<image class="w-650rpx h-1030rpx p-10rpx rounded-12rpx" src="/static/icon/birthday_coupon.jpg"
mode="aspectFit" />
<view class="z-100 size-120px absolute left-20rpx top-600rpx 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>
@@ -0,0 +1,198 @@
<script setup lang="ts">
import { reactive, ref, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { serviceEnum } from "@@/constant"
const { actCouponTypeEnum } = serviceEnum
const emit = defineEmits(["doVisibleQrcode"])
const props = withDefaults(defineProps<{ detail: any }>(), {
detail: {},
})
const doVisibleQrcode = () => {
emit("doVisibleQrcode", { type: 'ACT_CANCEL', detail: props.detail })
}
</script>
<template>
<view class="coupon-item">
<!-- 左侧主体 -->
<view class="coupon-left">
<view class="size-140rpx rounded-8rpx flex-row-center flex-shrink-0 bg-#f0f0f0 m-r-10rpx">
<image class="size-110rpx" src="/static/icon/act_cancel.png" mode="aspectFill" />
</view>
<view class="info-box">
<view class="price-row">
<view v-if="detail.faceValue" class="flex items-center">
<text class="symbol">¥</text>
<text class="amount">{{ detail.faceValue }}</text>
</view>
<text class="name">{{ detail.actTitlel }}</text>
</view>
<view class="condition">
活动商户:{{ detail.mchName }}
</view>
<view class="scope-text flex-col">
<text>{{ actCouponTypeEnum[detail.couponType] }}</text>
<text>有限期至 {{ detail.expireTime }}</text>
</view>
</view>
</view>
<!-- 虚线分割与缺口 -->
<view class="split-line">
<view class="circle-top"></view>
<view class="dashed-line"></view>
<view class="circle-bottom"></view>
</view>
<!-- 右侧按钮 -->
<view class="coupon-right">
<view class="action-btn" @tap="doVisibleQrcode">核销码</view>
</view>
</view>
</template>
<style scoped lang="scss">
.coupon-item {
display: flex;
align-items: stretch;
background-color: #fff;
margin-bottom: 20rpx;
border-radius: 16rpx;
overflow: hidden;
position: relative;
box-shadow: 0 4rpx 16rpx rgba(0, 148, 255, 0.08);
}
/* 左侧布局 */
.coupon-left {
flex: 1;
display: flex;
align-items: center;
padding: 24rpx 0 24rpx 24rpx;
background: radial-gradient(circle at right top, transparent 12rpx, #fff 0) top left / 100% 51% no-repeat,
radial-gradient(circle at right bottom, transparent 12rpx, #fff 0) bottom left / 100% 51% no-repeat;
/* 备用背景色,防止渐变失效 */
background-color: #fff;
}
.goods-img {
width: 140rpx;
height: 140rpx;
border-radius: 8rpx;
background-color: #f0f0f0;
margin-right: 20rpx;
flex-shrink: 0;
}
.info-box {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 140rpx;
}
.price-row {
display: flex;
align-items: baseline;
color: #0094ff;
}
.symbol {
font-size: 28rpx;
font-weight: 600;
}
.amount {
font-size: 48rpx;
font-weight: bold;
margin: 0 8rpx 0 2rpx;
line-height: 1;
}
.name {
font-size: 28rpx;
color: #333;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 200rpx;
}
.condition {
font-size: 24rpx;
color: #0094ff;
opacity: 0.8;
margin-top: 4rpx;
}
.scope-text {
font-size: 22rpx;
color: #999;
margin-top: auto;
}
/* 中间分割线区域 */
.split-line {
width: 30rpx;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
}
.dashed-line {
width: 0;
height: 80%;
border-left: 2rpx dashed #0094ff44;
}
.circle-top {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #f5f5f5;
/* 假设页面背景接近此色,或者设为透明如果用 mask */
}
.circle-bottom {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%, 50%);
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #f5f5f5;
}
/* 右侧按钮区 */
.coupon-right {
width: 160rpx;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(circle at left top, transparent 12rpx, #fff 0) top left / 100% 51% no-repeat,
radial-gradient(circle at left bottom, transparent 12rpx, #fff 0) bottom left / 100% 51% no-repeat;
background-color: #fff;
}
.action-btn {
background: #0094ff;
color: #fff;
font-size: 26rpx;
padding: 10rpx 24rpx;
border-radius: 30rpx;
font-weight: 500;
}
</style>
@@ -0,0 +1,197 @@
<script setup lang="ts">
import { reactive, ref, computed } from "vue"
import { onLoad, onShow } from "@dcloudio/uni-app"
import { serviceEnum } from "@@/constant"
const { actCouponTypeEnum } = serviceEnum
const emit = defineEmits(["doVisibleQrcode"])
const props = withDefaults(defineProps<{ detail: any }>(), {
detail: {},
})
const doVisibleQrcode = () => {
emit("doVisibleQrcode", { type: 'ACT_COUPON', detail: props.detail })
}
</script>
<template>
<view class="coupon-item">
<!-- 左侧主体 -->
<view class="coupon-left">
<image class="size-140rpx rounded-8rpx flex-shrink-0 m-r-10rpx bg-#f0f0f0" src="/static/icon/act_coupon.png"
mode="aspectFill" />
<view class="info-box">
<view class="price-row">
<view v-if="detail.faceValue" class="flex items-center">
<text class="symbol">¥</text>
<text class="amount">{{ detail.faceValue }}</text>
</view>
<text class="name">{{ detail.couponName }}</text>
</view>
<view v-if="detail.minPoint" class="condition">
满{{ detail.minPoint }}可用
</view>
<view class="scope-text flex-col">
<text>{{ actCouponTypeEnum[detail.couponType] }}</text>
<text>有限期至 {{ detail.endTime }}</text>
</view>
</view>
</view>
<!-- 虚线分割与缺口 -->
<view class="split-line">
<view class="circle-top"></view>
<view class="dashed-line"></view>
<view class="circle-bottom"></view>
</view>
<!-- 右侧按钮 -->
<view class="coupon-right">
<view class="action-btn" @tap="doVisibleQrcode">核销码</view>
</view>
</view>
</template>
<style scoped lang="scss">
.coupon-item {
display: flex;
align-items: stretch;
background-color: #fff;
margin-bottom: 20rpx;
border-radius: 16rpx;
overflow: hidden;
position: relative;
box-shadow: 0 4rpx 16rpx rgba(0, 148, 255, 0.08);
}
/* 左侧布局 */
.coupon-left {
flex: 1;
display: flex;
align-items: center;
padding: 24rpx 0 24rpx 24rpx;
background: radial-gradient(circle at right top, transparent 12rpx, #fff 0) top left / 100% 51% no-repeat,
radial-gradient(circle at right bottom, transparent 12rpx, #fff 0) bottom left / 100% 51% no-repeat;
/* 备用背景色,防止渐变失效 */
background-color: #fff;
}
.goods-img {
width: 140rpx;
height: 140rpx;
border-radius: 8rpx;
background-color: #f0f0f0;
margin-right: 20rpx;
flex-shrink: 0;
}
.info-box {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
height: 140rpx;
}
.price-row {
display: flex;
align-items: baseline;
color: #0094ff;
}
.symbol {
font-size: 28rpx;
font-weight: 600;
}
.amount {
font-size: 48rpx;
font-weight: bold;
margin: 0 8rpx 0 2rpx;
line-height: 1;
}
.name {
font-size: 28rpx;
color: #333;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 200rpx;
}
.condition {
font-size: 24rpx;
color: #0094ff;
opacity: 0.8;
margin-top: 4rpx;
}
.scope-text {
font-size: 22rpx;
color: #999;
margin-top: auto;
}
/* 中间分割线区域 */
.split-line {
width: 30rpx;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
}
.dashed-line {
width: 0;
height: 80%;
border-left: 2rpx dashed #0094ff44;
}
.circle-top {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #f5f5f5;
/* 假设页面背景接近此色,或者设为透明如果用 mask */
}
.circle-bottom {
position: absolute;
bottom: 0;
left: 50%;
transform: translate(-50%, 50%);
width: 24rpx;
height: 24rpx;
border-radius: 50%;
background-color: #f5f5f5;
}
/* 右侧按钮区 */
.coupon-right {
width: 160rpx;
display: flex;
align-items: center;
justify-content: center;
background: radial-gradient(circle at left top, transparent 12rpx, #fff 0) top left / 100% 51% no-repeat,
radial-gradient(circle at left bottom, transparent 12rpx, #fff 0) bottom left / 100% 51% no-repeat;
background-color: #fff;
}
.action-btn {
background: #0094ff;
color: #fff;
font-size: 26rpx;
padding: 10rpx 24rpx;
border-radius: 30rpx;
font-weight: 500;
}
</style>
+10 -35
View File
@@ -1,35 +1,13 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
<template #top>
<tm-input
class="mt-2"
v-model="params.receiverUserName"
type="text"
height="72"
minHeight="72"
fontSize="28"
:showClear="true"
:focus="false"
placeholder="请输入领取人姓名"
style="border: 4rpx solid #0779fd; border-radius: 14rpx"
:focus-highlight="false"
color="#ECF4F9"
@clear="inputClear"
>
<tm-input class="mt-2" v-model="params.receiverUserName" type="text" height="72" minHeight="72"
fontSize="28" :showClear="true" :focus="false" placeholder="请输入领取人姓名"
style="border: 4rpx solid #0779fd; border-radius: 14rpx" :focus-highlight="false" color="#ECF4F9"
@clear="inputClear">
<template v-slot:rightIcon>
<tm-button class="mr-1 px-3 py-26rpx text-30rpx!" size="xs" @click="search">搜 索</tm-button>
</template>
@@ -39,12 +17,9 @@
</view>
</template>
<view
class="card w-full h-400rpx relative activity-card overflow-hidden mb-2 py-2"
:style="{ backgroundColor: getActStatus(item.actStatus)?.color }"
v-for="(item, index) in pageHook.list"
:key="index"
>
<view class="card w-full h-400rpx relative activity-card overflow-hidden mb-2 py-2"
:style="{ backgroundColor: getActStatus(item.actStatus)?.color }" v-for="(item, index) in pageHook.list"
:key="index">
<view class="ribbon" :style="{ backgroundColor: getActStatus(item.actStatus)?.color }">
{{ getActStatus(item.actStatus)?.name }}
</view>
+169 -55
View File
@@ -1,77 +1,142 @@
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<view v-if="state.actId" class="px-2 py-4">
<view class="card rounded-lb-0! rounded-rb-0! w-full h-400rpx relative activity-card overflow-hidden">
<view v-if="state.actType == 'CANCEL_ACT'"
class="card rounded-lb-0! rounded-rb-0! w-full h-400rpx relative activity-card overflow-hidden">
<view class="ribbon">兑换券</view>
<view class="px-8 pt-5 flex justify-between items-center font-bold">
<text class="text-32 c-#FF4F3F">限时领取</text>
<text class="text-30 c-#FF4F3F px-1 rounded-full bg-#eeeeee44">
{{ (state.couponDetail.startTime?.split(" ")[0] || "") + "~" + (state.couponDetail.expireTime?.split(" ")[0] || "") }}
{{ (state.actDetail.startTime?.split(" ")[0] || "") + "~" +
(state.actDetail.expireTime?.split(" ")[0] || "") }}
</text>
</view>
<view class="w-4/5 px-8 pt-4 text-28 c-#fff">{{ state.couponDetail.actTitle }}</view>
<view class="w-4/5 px-8 pt-4 text-28 c-#fff">{{ state.actDetail.actTitle }}</view>
<view class="absolute bottom-100 left-60 text-40 italic">
<text class="color-red mr-2">¥{{ hooks.useMoney(state.couponDetail.activeCancelPrice) }}</text>
<text class="text-30 line-through color-red">¥{{ hooks.useMoney(state.couponDetail.activeOrgPrice) }}</text>
<text class="color-red mr-2">¥{{ hooks.useMoney(state.actDetail.activeCancelPrice) }}</text>
<text class="text-30 line-through color-red">¥{{ hooks.useMoney(state.actDetail.activeOrgPrice)
}}</text>
</view>
<view class="absolute bottom-40 left-60 text-28 bg-#eeeeee44 c-#fff px-2 rounded-full">限量领取 先领先得</view>
</view>
<view v-if="state.couponInfo.actStatus == '2'" class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30">已 核 销</view>
<view class="card relative rounded-lb-0! rounded-rb-0! w-full activity-sr-card overflow-hidden"
v-if="state.actType == 'COUPON_ACT' && state.actDetail.uniqueCode === '1qRgFo'">
<image class="w-full block" src="/static/page/act_li_quan.jpg" mode="widthFix" />
<view class="absolute top-0 left-0 w-full h-full">
<view class="ribbon">{{ actCouponTypeEnum[state.actDetail.type] }}</view>
</view>
</view>
<view v-else class="card relative rounded-lb-0! rounded-rb-0! w-full activity-card overflow-hidden">
<view class="ribbon">{{ actCouponTypeEnum[state.actDetail.type] }}</view>
<view class="px-8 pt-5 flex justify-between items-center font-bold">
<text class="text-32 c-#FF4F3F">{{ state.actDetail.name }}</text>
<text class="text-30 c-#FF4F3F px-1 rounded-full bg-#eeeeee44">
<view v-if="state.actDetail.validType == 1" class="flex items-center">
<text>{{ state.actDetail.validStartTime }}</text>
<text>~</text>
<text>{{ state.actDetail.validEndTime }}</text>
</view>
</text>
</view>
<view class="w-4/5 px-8 pt-4 text-28 c-#fff">
<view v-if="state.actDetail.validType == '1'">
<text>领取后请在</text>
<text>{{ state.actDetail.validStartTime }}</text>
<text>~</text>
<text>{{ state.actDetail.validEndTime }}</text>
<text>时间段内使用</text>
</view>
<view v-if="state.actDetail.validType == '2'">
<text>领取后请在</text>
<text>{{ state.actDetail.validDays }}</text>
<text>天内使用</text>
</view>
</view>
<view v-if="state.actDetail.description"
class="m-l-20rpx m-y-20rpx w-55% text-28 bg-#eeeeee44 c-#fff p-2 rounded-16rpx">
{{ 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">
已 核 销
</view>
<template v-else>
<view v-if="!state.isGet" class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30" @tap="getCoupon">立 即 领 取</view>
<view v-if="state.isGet" class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30">已 领 取</view>
<view v-if="state.actUserReceiveStatus == '99'"
class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30" @tap="doReceive">立 即 领 取</view>
<view v-else class="text-center card rounded-lt-0! rounded-rt-0! p-3 sub-text-30">
{{ actUserReceiveEnum[state.actUserReceiveStatus] || "未知状态" }}
</view>
</template>
</view>
<template #main-bottom>
<view v-if="state.isGet" class="text-center">
<tm-button class="px-32 m-2" @click="genVerificationCode">我的核销码</tm-button>
<view class="text-center">
<tm-button class="px-32 m-2" @click="doQrcode">我的礼券</tm-button>
</view>
</template>
</crud-layout>
<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="qrcodeId" class="size-200px" />
</view>
</tm-drawer>
<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 } from "@/sheep/api"
import uqrcode from "@@/utils/uqrcode"
import * as CryptoJS from "crypto-js"
import { hooks } from "@/sheep"
import { actCancel, actComApi, actCouponApi, userApi } from "@/sheep/api"
import { hooks, router } from "@/sheep"
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: "",
mchId: "",
isGet: false, // 是否已领取
couponDetail: {}, // 优惠券详情
actType: "",
actUserReceiveStatus: "", // 是否已领取
actDetail: {}, // 优惠券详情
couponInfo: {}, // 优惠券信息
userDetail: {},
})
const showQrCodeDialog = ref(false)
onLoad((option: any) => {
const { actId, mchId } = option
if (!actId || !mchId) return uni.showToast({ title: "参数错误", icon: "error" })
const { actId, actType } = option
if (!actId || !actType) return uni.showToast({ title: "参数错误", icon: "error" })
state.actId = actId
state.mchId = mchId
getCouponDetail()
getCouponInfo()
state.actType = actType
getActDetail()
getIsEligibleForAct()
if (actType == "CANCEL_ACT") {
getCouponInfo()
}
if (actType == "COUPON_ACT") {
specialDispose()
}
})
// 获取优惠券详情
const getCouponDetail = async () => {
const getActDetail = async () => {
try {
const { data } = await actCancel.getDetailById({
id: state.actId,
mchId: state.mchId,
const { data } = await actComApi.getActDetail({
actId: state.actId,
actType: state.actType,
})
state.couponDetail = data
state.actDetail = data?.detail
} catch (error: any) {
uni.showToast({ title: error, icon: "error" })
}
}
const getIsEligibleForAct = async () => {
try {
const { data } = await actComApi.isEligibleForAct({
actId: state.actId,
actType: state.actType,
})
state.actUserReceiveStatus = data
} catch (error: any) {
uni.showToast({ title: error, icon: "error" })
}
@@ -83,11 +148,9 @@ const getCouponInfo = async () => {
uni.showLoading({ title: "加载中...", mask: true })
const { code, data }: any = await actCancel.appFindUnique({ actId: state.actId })
if (!data) {
state.isGet = false
return
}
state.couponInfo = data
state.isGet = true
} catch (error) {
uni.showToast({ title: "加载失败", icon: "none" })
} finally {
@@ -95,19 +158,31 @@ const getCouponInfo = async () => {
}
}
// 领取券
const getCoupon = async () => {
// 领取优惠券
const doReceive = () => {
// 核销活动
if (state.actType == 'CANCEL_ACT') {
getCancelReceive()
}
// 优惠券活动
if (state.actType == 'COUPON_ACT') {
getCouponReceive()
}
}
// 核销活动
const getCancelReceive = async () => {
try {
uni.showLoading({ title: "正在领取...", mask: true })
await new Promise((resolve) => setTimeout(resolve, 2_000))
const { code, msg }: any = await actCancel.appGet({
receiverUserId: uni.getStorageSync("user_info")?.sysUser?.userId,
actId: state.actId,
mchId: state.mchId,
mchId: state.actDetail.mchId,
})
if (code != 0) return uni.showToast({ title: msg || "领取失败", icon: "none", mask: true })
uni.showToast({ title: "领取成功", icon: "success" })
await getCouponInfo()
await getIsEligibleForAct()
} catch (error: any) {
uni.showToast({ title: "领取失败", icon: "none" })
} finally {
@@ -115,18 +190,49 @@ const getCoupon = async () => {
}
}
// 生成核销二维码
const genVerificationCode = async () => {
showQrCodeDialog.value = true
const words = CryptoJS.enc.Utf8.parse(JSON.stringify({ cancelId: state.couponInfo.id }))
uqrcode.make({
canvasId: "qrcodeId",
text: CryptoJS.enc.Base64.stringify(words),
size: 200,
margin: 0,
success: (res) => {},
complete: () => {},
})
// 优惠券活动
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({
couponId: state.actId,
receiveUserId: state.userDetail.userId,
})
if (code != 0) return uni.showToast({ title: msg || "领取失败", icon: "none", mask: true })
uni.showToast({ title: "领取成功", icon: "success" })
await getIsEligibleForAct()
} catch (error: any) {
uni.showToast({ title: "领取失败", icon: "none" })
} finally {
uni.hideLoading()
}
}
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")
}
</script>
@@ -139,6 +245,14 @@ const genVerificationCode = async () => {
background-color: #1879ff77;
}
.activity-sr-card {
/* background-image: url("../../static/page/act_li_quan.jpg");
background-repeat: no-repeat;
background-size: contain;
background-position: 150%;
background-color: red; */
}
.ribbon {
width: 160rpx;
height: 40rpx;
+165
View File
@@ -0,0 +1,165 @@
<script setup lang="ts">
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, 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 pageRef = ref<any>(null)
const showQrCodeDialog = ref(false)
const params = reactive({
})
const state = reactive({
tabs: [
{
id: 1,
name: "优惠券活动",
badge: {
count: 6
},
disabled: false
},
{
id: 2,
name: "核销券活动",
badge: {
count: 6
},
disabled: false
},
],
tabId: 1,
})
const dynamicPageHook = computed(() => {
if (state.tabId == 1) {
return hooks.usePage(pageRef, actCouponApi.userList, null, "data.records")
}
if (state.tabId == 2) {
return hooks.usePage(pageRef, actCancel.userList, null, "data.records")
}
})
onShow(() => {
getUserTotal()
})
const query = (page: number, pagesize: number) => {
dynamicPageHook.value?.startPage(page, pagesize, false, params)
getUserTotal()
}
const doTab = (e: any) => {
const target = state.tabs[e]
state.tabId = target.id
pageRef.value.reload(false)
getUserTotal()
}
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 })
}
}
// 用户参加活动的数量统计
const getUserTotal = async () => {
try {
const { data = {} }: any = await actComApi.userTotal({})
state.tabs[0].badge.count = data?.couponCount ?? null
state.tabs[1].badge.count = data?.cancelCount ?? null
} catch (error) {
console.log("|用户参加活动的数量统计|意外的错误error:", error);
}
}
// 生成核销二维码
const genVerificationCode = async (params: Record<string, any>) => {
showQrCodeDialog.value = true
const words = CryptoJS.enc.Utf8.parse(JSON.stringify(params))
uqrcode.make({
canvasId: "qrcodeId",
text: CryptoJS.enc.Base64.stringify(words),
size: 200,
margin: 0,
success: (res) => { },
complete: () => { },
})
}
</script>
<template>
<crud-layout mainIsScroll bg="/static/page/blue-bg.png">
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="dynamicPageHook.list" :default-page-size="10"
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false"
@scroll="dynamicPageHook.scroll">
<template #top>
<view class="h-30rpx" />
<view class="bg-white rounded-16rpx">
<z-tabs :list="state.tabs" @change="doTab" />
</view>
</template>
<view class="h-20rpx" />
<view v-if="state.tabId == 1">
<coupon-card v-for="item in dynamicPageHook.list" :key="item.id" :detail="item"
@do-visible-qrcode="doVisibleQrcode" />
</view>
<view v-if="state.tabId == 2">
<cancel-card v-for="item in dynamicPageHook.list" :key="item.id" :detail="item"
@do-visible-qrcode="doVisibleQrcode" />
</view>
</z-paging>
<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="qrcodeId" class="size-200px" />
</view>
</tm-drawer>
</crud-layout>
</template>
+40 -16
View File
@@ -1,17 +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>
@@ -21,7 +29,8 @@
</template>
<view class="mt-10rpx rounded-20rpx shadow-main p-30rpx pb-40rpx bg-white">
<view class="service_item flex items-center justify-between" v-for="(v, i) in state.menuList" :key="i" @tap="onTabMenu(v)">
<view class="service_item flex items-center justify-between" v-for="(v, i) in state.menuList" :key="i"
@tap="onTabMenu(v)">
<view class="flex-row-center">
<image class="size-40rpx" :src="v.icon" mode="aspectFill" />
<text class="sub-text-28 m-l-20rpx">{{ v.text }}</text>
@@ -31,13 +40,15 @@
</view>
<view v-if="isDevEnv()" class="flex-col-center mt-40rpx mx-30rpx">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff" @tap="doLogout">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
@tap="doLogout">
退出登录
</view>
</view>
<view class="h-30rpx" />
<view v-if="state.appInfo == APPENV.SH" class="flex-col-center mt-40rpx mx-30rpx">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff" @tap="doChangeRole">
<view class="w-full text-center sub-text-28 p-y-20rpx rounded-40rpx border-solid border border-#0094ff"
@tap="doChangeRole">
切换角色
</view>
</view>
@@ -50,7 +61,10 @@
</view>
</crud-layout>
<tm-modal :show="state.actModalShow" :showCancel="false" title="核销活动兑换券" zIndex="999" @confirm="" @cancel="" @close="">
<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>
<view class="text-center text-28">确认核销将自动对用户的 消费钱包 扣费</view>
<template #footer>
@@ -63,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"
@@ -73,11 +88,16 @@ 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: {},
menuList: [
{ text: "扫一扫", icon: "/static/icon/scan.png", path: "" },
{ text: "我参加的活动", icon: "/static/icon/act.png", path: "/pages/merchant/my-act-list" },
{ text: "我的钱包", icon: "/static/icon/service_3.png", path: "/pages/wallet/list" },
{ text: "我的人脸", icon: "/static/icon/service_5.png", path: "/pages/human-face/list" },
{ text: "车辆管理", icon: "/static/icon/service_6.png", path: "/pages/car/userCar/list" },
@@ -94,6 +114,10 @@ const STORAGE_KEYS = {
USER_INFO: constant.storageConstant.USERINFO,
}
const doUserArea = () => {
modifyUserRef.value?.open()
}
const storage = {
// 获取存储的用户信息
getUserInfo: () => {
+25 -31
View File
@@ -48,14 +48,14 @@ const pageHook = hooks.usePage(
getLaunchParam() == "canteen" // 食堂
? orderApi.caneenPage
: getLaunchParam() == "selfMerchant"
? orderApi.supPage
: getLaunchParam() == "coopMerchant"
? orderApi.supPage
: getLaunchParam() == "onlineShop"
? orderApi.supPage
: getLaunchParam() == "prosperityShop"
? orderApi.farmerSpuPage
: async () => [],
? orderApi.supPage
: getLaunchParam() == "coopMerchant"
? orderApi.supPage
: getLaunchParam() == "onlineShop"
? orderApi.supPage
: getLaunchParam() == "prosperityShop"
? orderApi.farmerSpuPage
: async () => [],
null,
"data.records",
)
@@ -71,7 +71,7 @@ const doToDetail = (v: any) => {
router.jump("/pages/order/detail", { id: v.id })
}
const doAppraise = () => {}
const doAppraise = () => { }
const doRefund = (v: any) => {
router.jump("/pages/refund/apply", { id: v.id })
@@ -80,20 +80,9 @@ const doRefund = (v: any) => {
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="10"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="10"
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
<template #top>
<view class="bg-white rounded-16rpx px-20rpx my-20rpx">
<z-tabs :list="data.tabs" @change="doTab" />
@@ -116,15 +105,15 @@ const doRefund = (v: any) => {
<view class="flex-row items-center justify-between mt-5rpx second-text-24">
<view>
<text>下单时间</text>
<text class="ml-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}") }}</text>
<text class="ml-10rpx">{{ hooks.useTime(v.createTime, "{y}-{m}-{d} {h}:{i}:{s}")
}}</text>
</view>
<view>{{ hooks.useEnum("hardwareRefundStatusEnum", v.refundStatus) }}</view>
</view>
<view class="flex-row items-center justify-end mt-1">
<text
v-if="v.carList?.length && ['5', '20'].includes(v.orderStatus) && ['1', '2'].includes(v.orderType)"
class="second-text-30 mr-2"
>
class="second-text-30 mr-2">
共 {{ v.carList.length }} 件
</text>
<text class="main-text-30 color-red!">¥ {{ hooks.useMoney(v.totalPrice) }}</text>
@@ -135,12 +124,16 @@ const doRefund = (v: any) => {
<view v-if="['5', '20'].includes(v.orderStatus) && ['1', '2'].includes(v.orderType)">
<view class="border-b-2rpx border-dashed border-#eeeeee mt-2"></view>
<tm-collapse>
<tm-collapse-item :name="i" title="详细购买" titleFontSize="28" activeColor="#000" titleHeight="80" :showBottomLine="false">
<view v-if="v.carList.length" class="flex justify-between items-center mb-2 px-3" v-for="(pV, pI) in v.carList" :key="pI">
<tm-collapse-item :name="i" title="详细购买" titleFontSize="28" activeColor="#000" titleHeight="80"
:showBottomLine="false">
<view v-if="v.carList.length" class="flex justify-between items-center mb-2 px-3"
v-for="(pV, pI) in v.carList" :key="pI">
<view class="flex items-center w-6/10">
<view class="size-100rpx">
<image v-if="v.payType == '9'" class="size-100rpx rounded-8rpx" :src="pV.productPic" mode="aspectFill" />
<image v-else class="size-100rpx rounded-8rpx" :src="filePath(pV.productPic)" mode="aspectFill" />
<image v-if="v.payType == '9'" class="size-100rpx rounded-8rpx"
:src="pV.productPic" mode="aspectFill" />
<image v-else class="size-100rpx rounded-8rpx" :src="filePath(pV.productPic)"
mode="aspectFill" />
</view>
<view class="ml-2 overflow-hidden">
<view class="sub-text-26 truncate">{{ pV.productName }}</view>
@@ -158,7 +151,8 @@ const doRefund = (v: any) => {
<view v-if="['5', '10'].includes(v.orderStatus)" class="w-full flex-row items-center justify-end my-1">
<!-- <view v-if="v.orderStatus == 5 && v.orderType == 2" class="botder_btn" @tap.stop="doRefund(v)">退款</view> -->
<view v-if="v.orderStatus === '5' && ['2', '7'].includes(v.orderType)" class="m-l-20rpx botder_btn" @tap.stop="doToDetail(v)">
<view v-if="v.orderStatus === '5' && ['2', '7'].includes(v.orderType)" class="m-l-20rpx botder_btn"
@tap.stop="doToDetail(v)">
核销码
</view>
</view>
+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>
+20 -56
View File
@@ -29,7 +29,7 @@ const freezeForm = reactive<any>({
remark: "",
})
onLoad(() => {})
onLoad(() => { })
onShow(async () => {
const isLogin = await hooks.useCheckLogin()
if (!isLogin) return
@@ -140,35 +140,22 @@ const doTransferMoney = (v: any) => {
<template>
<crud-layout bg="/static/page/blue-bg.png">
<z-paging
ref="pageRef"
height="100%"
:fixed="false"
v-model="pageHook.list"
:default-page-size="5"
safe-area-inset-bottom
:loading-more-enabled="true"
:show-scrollbar="false"
@query="query"
:auto-clean-list-when-reload="false"
:auto-scroll-to-top-when-reload="false"
@scroll="pageHook.scroll"
>
<z-paging ref="pageRef" height="100%" :fixed="false" v-model="pageHook.list" :default-page-size="5"
safe-area-inset-bottom :loading-more-enabled="true" :show-scrollbar="false" @query="query"
:auto-clean-list-when-reload="false" :auto-scroll-to-top-when-reload="false" @scroll="pageHook.scroll">
<view class="h-30rpx" />
<view
class="card flex-col rounded-20rpx p-x-30rpx p-y-20rpx m-b-30rpx"
v-for="(v, i) in pageHook.list"
:key="i"
@tap="router.jump('/pages/wallet/detail', { id: v.id })"
>
<view class="card flex-col rounded-20rpx p-x-30rpx p-y-20rpx m-b-30rpx" v-for="(v, i) in pageHook.list"
:key="i" @tap="router.jump('/pages/wallet/detail', { id: v.id })">
<view class="flex-col">
<view class="flex-row items-center justify-between">
<view class="flex-row-center">
<text v-if="v.cardNumber" class="second-text-28">卡号: {{ v.cardNumber }}</text>
</view>
<view class="second-text-50">
<text v-if="v.cardNumber" class="iconfont icon-fuzhi" @tap.stop="hooks.useCopy(v.cardNumber)" />
<text v-if="v.walletTypeUniqueCode != '2'" class="m-l-20rpx iconfont icon-erweima" @tap.stop="doPreviewQrCode(v)" />
<text v-if="v.cardNumber" class="iconfont icon-fuzhi"
@tap.stop="hooks.useCopy(v.cardNumber)" />
<text v-if="v.walletTypeUniqueCode != '2'" class="m-l-20rpx iconfont icon-erweima"
@tap.stop="doPreviewQrCode(v)" />
</view>
</view>
<view v-if="v.cardNumber" class="h-1px m-t-10rpx bg-#999 bg-opacity-5" />
@@ -191,14 +178,12 @@ const doTransferMoney = (v: any) => {
<view class="flex-row items-center justify-end space-x-20rpx m-t-10rpx">
<!-- <view v-if="v.walletTypeUniqueCode == 1 && !v.cardNumber" class="botder_btn" @tap.stop="openBindDialog(v)">绑定</view> -->
<view v-if="v.isRule == '1'" class="botder_btn" @tap.stop="doTransferMoney(v)">转账</view>
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn" @tap.stop="openFreezeDialog(v)">
<view v-if="v.walletTypeUniqueCode == 1 && v.cardNumber && v.isFreeze != 1" class="botder_btn"
@tap.stop="openFreezeDialog(v)">
申请冻结
</view>
<view
v-if="false && v.walletTypeUniqueCode == 2"
class="botder_btn"
@tap.stop="router.jump('/pages/wallet/recharge', { id: v.id })"
>
<view v-if="false && v.walletTypeUniqueCode == 2" class="botder_btn"
@tap.stop="router.jump('/pages/wallet/recharge', { id: v.id })">
去充值
</view>
</view>
@@ -206,15 +191,8 @@ const doTransferMoney = (v: any) => {
</z-paging>
</crud-layout>
<tm-drawer
z-index="100"
v-model:show="state.showBindDialog"
:overlayClick="false"
title="绑定饭卡"
:show-close="true"
position="bottom"
size="40%"
>
<tm-drawer z-index="100" v-model:show="state.showBindDialog" :overlayClick="false" title="绑定饭卡" :show-close="true"
position="bottom" size="40%">
<view class="h-50rpx" />
<tm-form ref="bindFormRef" v-model="bindForm" :rules="bindFormRules">
<tm-form-item name="cardNumber" :showLabel="false" :showBottom="false">
@@ -224,15 +202,8 @@ const doTransferMoney = (v: any) => {
<view class="h-50rpx" />
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doBind">绑定</view>
</tm-drawer>
<tm-drawer
z-index="100"
v-model:show="state.showFreezeDialog"
:overlayClick="true"
title="申请冻结"
:show-close="true"
position="bottom"
size="40%"
>
<tm-drawer z-index="100" v-model:show="state.showFreezeDialog" :overlayClick="true" title="申请冻结" :show-close="true"
position="bottom" size="40%">
<view class="h-50rpx" />
<tm-form ref="bindFormRef" v-model="freezeForm">
<tm-form-item name="remark" :showLabel="false" :showBottom="false">
@@ -242,15 +213,8 @@ const doTransferMoney = (v: any) => {
<view class="h-50rpx" />
<view class="bg-#0094ff p-y-20rpx text-center rounded-40rpx sub-text-30 color-white!" @tap="doFreeze">冻结</view>
</tm-drawer>
<tm-drawer
z-index="100"
v-model:show="state.showQrCodeDialog"
:overlayClick="false"
title="钱包二维码"
:show-close="true"
position="bottom"
size="50%"
>
<tm-drawer z-index="100" v-model:show="state.showQrCodeDialog" :overlayClick="false" title="钱包二维码"
:show-close="true" position="bottom" size="50%">
<view class="flex-col-center">
<view class="h-80rpx" />
<canvas canvas-id="qrcodeId" class="size-200px" />
+9
View File
@@ -61,4 +61,13 @@ export default {
method: "GET",
params,
}),
/**
* 用户领取核销券列表
*/
userList: (params: any) =>
request({
url: "/wallet/act/cancel-item/app/user-list",
method: "GET",
params,
}),
}
+40
View File
@@ -0,0 +1,40 @@
import request from "@/sheep/utils/request"
export default {
/**
* 根据公告id查询对应的活动
*/
getActByNotifyId: (params: any) =>
request({
url: "/wallet/act/com/app/get-act-by-notify-id",
method: "GET",
params,
}),
/**
* 获取活动详情
*/
getActDetail: (params: any) =>
request({
url: "/wallet/act/com/app/get-act-detail",
method: "GET",
params,
}),
/**
* 判断用户是否可以参加活动
*/
isEligibleForAct: (params: any) =>
request({
url: "/wallet/act/com/app/is-eligible-for-act",
method: "GET",
params,
}),
/**
* 用户参加活动的数量统计
*/
userTotal: (params: any) =>
request({
url: "/wallet/act/com/app/user-total",
method: "GET",
params,
}),
}
+22
View File
@@ -0,0 +1,22 @@
import request from "@/sheep/utils/request"
export default {
/**
* 领取优惠券
*/
receive: (data: any) =>
request({
url: "/wallet/act-coupon-record/app/receive",
method: "POST",
data,
}),
/**
* 用户领取核销券列表
*/
userList: (params: any) =>
request({
url: "/wallet/act-coupon-record/app/user-list",
method: "GET",
params,
}),
}
+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",
+2
View File
@@ -1,4 +1,6 @@
export { default as actCancel } from "./act-cancel"
export { default as actComApi } from "./act-com"
export { default as actCouponApi } from "./act-coupon"
export { default as applyApi } from "./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" style="pointer-events: none" disabled>
</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>
@@ -1,3 +1,4 @@
// #ifdef WEB
import { h, render } from "vue"
import VerifyDeviceImpModel from "./verify-device-imp-model.vue"
@@ -24,3 +25,9 @@ const showVerifyDeviceImpModel = (onClose: () => any = () => null) => {
}
export default showVerifyDeviceImpModel
// #endif
// #ifndef WEB
const showVerifyDeviceImpModel = (onClose: () => any = () => null) => {}
export default showVerifyDeviceImpModel
// #endif
+32
View File
@@ -55,6 +55,35 @@ const actCancelStatusEnum = {
"3": "已过期",
}
const actCouponLimitTypeEnum = {
"1": "活动期间一次",
"2": "每天",
"3": "每周",
"4": "每月",
"5": "每年",
}
const actCouponTypeEnum = {
"1": "满减券",
"2": "折扣券",
"3": "立减券",
"4": "兑换券",
}
// 用户活动状态
const actUserReceiveEnum = {
"1": "活动不在进行中",
"2": "活动不存在",
"3": "活动未开启",
"4": "用户参加活动已达上限",
"5": "用户不能参加此活动",
"6": "其他错误",
"99": "用户可以参加活动",
// 特殊
"-100": "请在生日当月领取",
"-101": "请填写出生日期",
}
export default {
hardwareOrderStatusEnum,
hardwareOrderTypeEnum,
@@ -64,4 +93,7 @@ export default {
hardwareRefundStatusEnum,
carTypeEnum,
actCancelStatusEnum,
actCouponLimitTypeEnum,
actCouponTypeEnum,
actUserReceiveEnum,
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

+99 -100
View File
@@ -1,103 +1,102 @@
import presetWeapp from "unocss-preset-weapp";
import {
extractorAttributify,
transformerClass,
} from "unocss-preset-weapp/transformer";
import { defineConfig } from "unocss"
import { presetWeapp } from "unocss-preset-weapp"
import { extractorAttributify, transformerClass } from "unocss-preset-weapp/transformer"
const { presetWeappAttributify, transformerAttributify } =
extractorAttributify();
const { presetWeappAttributify, transformerAttributify } = extractorAttributify()
export default {
presets: [
presetWeapp({
whRpx: true,
}),
presetWeappAttributify(),
],
shortcuts: [
{
"border-base": "border border-gray-500_10",
"flex-col-center": "flex flex-col justify-center items-center",
"flex-row-center": "flex flex-row justify-center items-center",
"flex-col": "flex flex-col",
"flex-row": "flex flex-row",
},
],
theme: {
colors: {
blue: {
DEFAULT: "#0094ff",
},
red: {
DEFAULT: "#f63a36",
},
yellow: {
DEFAULT: "#F2A817",
},
},
},
rules: [
[
/^main-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 800,
color: "#000",
"line-height": `1.4em`,
}),
],
[
/^sub-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 500,
color: "#333",
"line-height": `1.4em`,
}),
],
[
/^second-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 500,
color: "#999",
"line-height": `1.4em`,
}),
],
[
"card",
{
"background-color": "white",
"box-shadow": "0rpx 8rpx 26rpx -4rpx rgba(210,210,210,0.5)",
"border-radius": "16rpx",
},
],
[
"shadow-main",
{
"box-shadow": "0rpx 0rpx 4rpx 0rpx rgba(0, 0, 0, 0.1)",
},
],
[
/^show-line$/,
([, d]) => ({
overflow: "hidden",
"white-space": "nowrap",
"text-overflow": "ellipsis",
}),
],
[
/^show-line-(\d+)$/,
([, d]) => ({
display: "-webkit-box !important",
overflow: "hidden",
"text-overflow": "ellipsis !important",
"word-break": "break-all",
"-webkit-line-clamp": d,
"-webkit-box-orient": "vertical !important",
}),
],
],
transformers: [transformerAttributify(), transformerClass()],
};
content: {
filesystem: ["src/**/*.{vue,js,ts,jsx,tsx}"],
},
presets: [
presetWeapp({
whRpx: true,
}),
presetWeappAttributify(),
],
transformers: [transformerAttributify(), transformerClass()],
shortcuts: [
{
"border-base": "border border-gray-500_10",
"flex-col-center": "flex flex-col justify-center items-center",
"flex-row-center": "flex flex-row justify-center items-center",
"flex-col": "flex flex-col",
"flex-row": "flex flex-row",
},
],
theme: {
colors: {
blue: {
DEFAULT: "#0094ff",
},
red: {
DEFAULT: "#f63a36",
},
yellow: {
DEFAULT: "#F2A817",
},
},
},
rules: [
[
/^main-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 800,
color: "#000",
"line-height": `1.4em`,
}),
],
[
/^sub-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 500,
color: "#333",
"line-height": `1.4em`,
}),
],
[
/^second-text-(\d+)$/,
([, d]) => ({
"font-size": `${d}rpx`,
"font-weight": 500,
color: "#999",
"line-height": `1.4em`,
}),
],
[
"card",
{
"background-color": "white",
"box-shadow": "0rpx 8rpx 26rpx -4rpx rgba(210,210,210,0.5)",
"border-radius": "16rpx",
},
],
[
"shadow-main",
{
"box-shadow": "0rpx 0rpx 4rpx 0rpx rgba(0, 0, 0, 0.1)",
},
],
[
/^show-line$/,
([, d]) => ({
overflow: "hidden",
"white-space": "nowrap",
"text-overflow": "ellipsis",
}),
],
[
/^show-line-(\d+)$/,
([, d]) => ({
display: "-webkit-box !important",
overflow: "hidden",
"text-overflow": "ellipsis !important",
"word-break": "break-all",
"-webkit-line-clamp": d,
"-webkit-box-orient": "vertical !important",
}),
],
],
}