新增营销系统、分销系统、会员功能、门店、提现功能
This commit is contained in:
171
root/user/components/GridCard.vue
Normal file
171
root/user/components/GridCard.vue
Normal file
@ -0,0 +1,171 @@
|
||||
<!--
|
||||
@name: GridCard
|
||||
@author: kahu4
|
||||
@date: 2023-11-09 15:09
|
||||
@description:GridCard
|
||||
@update: 2023-11-09 15:09
|
||||
-->
|
||||
<script setup>
|
||||
import { toRefs } from "vue";
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { useInterface } from "@/hooks/useInterface";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useMainStore } from "@/store/store";
|
||||
import { useService } from "@/hooks/useService";
|
||||
|
||||
const props = defineProps({
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => ([])
|
||||
},
|
||||
dotInfo: {
|
||||
type: Object
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
buttonText: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const {list, title, buttonText, dotInfo} = toRefs(props)
|
||||
const emits = defineEmits(['buttonClick'])
|
||||
const {push} = useRouter();
|
||||
const {toast} = useInterface();
|
||||
const mainStore = useMainStore();
|
||||
const {user} = storeToRefs(mainStore);
|
||||
|
||||
async function toLink(listItem) {
|
||||
if (!user.value) return toast({title: '请先登录'})
|
||||
if (!listItem.path) return toast({title: ' 暂未开放 '})
|
||||
if (listItem.path === 'kf') {
|
||||
const {getServiceData,openService} = useService();
|
||||
await getServiceData()
|
||||
await openService()
|
||||
return
|
||||
}
|
||||
push({url: listItem.path}, listItem?.params ?? {})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="grid-container">
|
||||
<view
|
||||
class="title-row"
|
||||
v-if="title || buttonText"
|
||||
>
|
||||
<view>
|
||||
{{ title }}
|
||||
</view>
|
||||
<view
|
||||
class="right"
|
||||
@click="emits('buttonClick')"
|
||||
>
|
||||
{{ buttonText }}
|
||||
<uv-icon
|
||||
v-if="buttonText"
|
||||
name="arrow-right"
|
||||
color="#ccc"
|
||||
size="12"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon-box">
|
||||
<view
|
||||
class="icon-item"
|
||||
v-for="item in list"
|
||||
:key="item"
|
||||
@click="toLink(item)"
|
||||
>
|
||||
|
||||
<template v-if="item&&item.rightTopDot">
|
||||
<view
|
||||
class="dot"
|
||||
v-if="dotInfo && dotInfo[item.dotField] && dotInfo[item.dotField]>0"
|
||||
>
|
||||
{{ dotInfo[item.dotField] < 100 ? dotInfo[item.dotField] : `${ dotInfo[item.dotField] }+` }}
|
||||
</view>
|
||||
</template>
|
||||
<image
|
||||
class="icon"
|
||||
:src="item.icon"
|
||||
/>
|
||||
<view class="text">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style
|
||||
scoped
|
||||
lang="scss"
|
||||
>
|
||||
.grid-container {
|
||||
width: 100%;
|
||||
background: $white-color;
|
||||
border-radius: 15rpx;
|
||||
margin: 20rpx 0;
|
||||
|
||||
.title-row {
|
||||
@include useFlex(space-between, center);
|
||||
@include usePadding(30, 30);
|
||||
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
font-weight: 500;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
|
||||
.right {
|
||||
@include useFlex(space-between, center);
|
||||
font-size: 24rpx;
|
||||
color: $tips-color;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.icon-box {
|
||||
@include usePadding(30, 20);
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
|
||||
.icon-item {
|
||||
@include useFlex(space-between, center, column);
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
color: #333333;
|
||||
position: relative;
|
||||
|
||||
.dot {
|
||||
z-index: 99;
|
||||
position: absolute;
|
||||
background: #EE6D46;
|
||||
color: #fff;
|
||||
right: 20%;
|
||||
top: 0;
|
||||
transform: translateY(-20%);
|
||||
font-size: 18rpx;
|
||||
width: 38rpx;
|
||||
height: 38rpx;
|
||||
text-align: center;
|
||||
line-height: 38rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #ffffff;
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 14rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
172
root/user/index.data.js
Normal file
172
root/user/index.data.js
Normal file
@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @name: index.data
|
||||
* @author: kahu4
|
||||
* @date: 2023-11-09 15:21
|
||||
* @description:index.data
|
||||
* @update: 2023-11-09 15:21
|
||||
* */
|
||||
|
||||
import {
|
||||
myScan,
|
||||
toDZIcon,
|
||||
toFHIcon,
|
||||
toKFIcon,
|
||||
toKJIcon,
|
||||
toPayIcon,
|
||||
toPJIcon,
|
||||
toSCIcon,
|
||||
toSHIcon,
|
||||
toSHOIcon,
|
||||
toTGIcon,
|
||||
toYHQIcon,
|
||||
toZBIcon,
|
||||
toZHIcon,
|
||||
toZJIcon
|
||||
} from "@/utils/images";
|
||||
import { useJump } from "@/hooks/useJump";
|
||||
|
||||
const {goIntegral, goBalance, goCoupon} = useJump()
|
||||
export const orderIconList = [
|
||||
{
|
||||
id: 1,
|
||||
label: '待付款',
|
||||
icon: toPayIcon,
|
||||
rightTopDot: true,
|
||||
dotField: 'unpaidCount',
|
||||
path: '/pages/orderList/orderList',
|
||||
params: {data: {type: 0}}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '待发货',
|
||||
icon: toFHIcon,
|
||||
rightTopDot: true,
|
||||
dotField: 'unshippedCount',
|
||||
path: '/pages/orderList/orderList',
|
||||
params: {data: {type: 1}}
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '待收货',
|
||||
icon: toSHIcon,
|
||||
rightTopDot: true,
|
||||
dotField: 'receivedCount',
|
||||
path: '/pages/orderList/orderList',
|
||||
params: {data: {type: 2}}
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: '待评价',
|
||||
icon: toPJIcon,
|
||||
rightTopDot: true,
|
||||
dotField: 'evaluatedCount',
|
||||
path: '/pages/orderList/orderList',
|
||||
params: {data: {type: 3}}
|
||||
},
|
||||
]
|
||||
|
||||
export const cardOneList = [
|
||||
{
|
||||
id: 1,
|
||||
label: '我的足迹',
|
||||
icon: toZJIcon,
|
||||
path: '/pages/footprint/footprint',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '优惠券',
|
||||
icon: toYHQIcon,
|
||||
path: '/pages/discountCoupon/index',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '我的收藏',
|
||||
icon: toSCIcon,
|
||||
rightTopDot: false,
|
||||
dotField: 'receivedCount',
|
||||
path: '/pages/collect/collect',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: '开启直播',
|
||||
icon: toZBIcon,
|
||||
rightTopDot: false,
|
||||
dotField: 'evaluatedCount',
|
||||
path: '',
|
||||
params: {data: {type: 3}}
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
label: '我的推广',
|
||||
icon: toTGIcon,
|
||||
path: '/views/distribution/center/index',
|
||||
params: {}
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
label: '砍价记录',
|
||||
icon: toKJIcon,
|
||||
path: '',
|
||||
params: {data: {type: 1}}
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
label: '售后记录',
|
||||
icon: toSHOIcon,
|
||||
rightTopDot: false,
|
||||
dotField: 'receivedCount',
|
||||
path: '/pages/refundList/refundList',
|
||||
params: {data: {type: -1}}
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
label: '联系客服',
|
||||
icon: toKFIcon,
|
||||
rightTopDot: false,
|
||||
dotField: 'evaluatedCount',
|
||||
path: 'kf',
|
||||
params: {data: {type: 3}}
|
||||
},
|
||||
]
|
||||
|
||||
export const cardTwoList = [
|
||||
{
|
||||
id: 1,
|
||||
label: '地址管理',
|
||||
icon: toDZIcon,
|
||||
path: '/pages/address/address',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '账号管理',
|
||||
icon: toZHIcon,
|
||||
path: '/pages/userInfo/index',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '订单核销',
|
||||
icon: myScan,
|
||||
path: '/views/activity/afterVerification/index',
|
||||
},
|
||||
]
|
||||
|
||||
export const accountList = [
|
||||
{
|
||||
id: 1,
|
||||
label: '我的余额',
|
||||
field: 'nowMoney',
|
||||
path: goBalance
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: '我的积分',
|
||||
field: 'integral',
|
||||
path: goIntegral
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: '优惠券',
|
||||
field: 'couponNumber',
|
||||
path: goCoupon
|
||||
}
|
||||
]
|
388
root/user/user.vue
Normal file
388
root/user/user.vue
Normal file
@ -0,0 +1,388 @@
|
||||
<template>
|
||||
<view class="mine-container">
|
||||
|
||||
<Header :show-return="false">我的</Header>
|
||||
<!-- user info -->
|
||||
<view class="userinfo-box">
|
||||
<!-- 未登录 -->
|
||||
<view
|
||||
class="userinfo-box__inner no-login"
|
||||
v-if="!(user && user.id)"
|
||||
@click="toLogin"
|
||||
>
|
||||
<view class="flex flex-ai__center">
|
||||
<image
|
||||
class="head"
|
||||
:src="defaultAvatarIcon"
|
||||
/>
|
||||
<view class="user-info">
|
||||
点击登录
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 已登录 -->
|
||||
<view
|
||||
class="userinfo-box__inner"
|
||||
@click="toUserCenter"
|
||||
v-else
|
||||
>
|
||||
<view class="flex flex-ai__center">
|
||||
<image
|
||||
class="head"
|
||||
:src="user.avatar"
|
||||
/>
|
||||
<view class="user-info">
|
||||
{{ user.nickname }}
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="sign-box"
|
||||
@click.stop="goSignIn">
|
||||
<image :src="mySignIn" />
|
||||
签到
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 账户信息 -->
|
||||
<view class="account-box">
|
||||
<template
|
||||
v-for="item in accountList"
|
||||
:key="item.id">
|
||||
<view
|
||||
v-if="user"
|
||||
class="account-item"
|
||||
@click.stop="handleJump(item)">
|
||||
<view class="count">
|
||||
{{ user[item.field] || 0 }}
|
||||
</view>
|
||||
<view class="title">
|
||||
{{ item.label }}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
</view>
|
||||
|
||||
<!-- VIP 信息 未激活 -->
|
||||
<view
|
||||
class="vip-box vip-none"
|
||||
@click="goMemberCenter"
|
||||
v-if="!memberLeverInfo.currentLevel">
|
||||
<view
|
||||
class="vip-box__inner flex flex-ai__center flex-jc__sb"
|
||||
:style="{backgroundImage:`url(${myVip1})`}">
|
||||
<image
|
||||
class="icon"
|
||||
:src="noneVip" />
|
||||
<view class="vip-text">
|
||||
开通享更多特权,省钱又省心
|
||||
</view>
|
||||
<view class="vip-button">
|
||||
立即激活
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- VIP 信息 激活 -->
|
||||
<view
|
||||
class="vip-box"
|
||||
@click="goMemberCenter"
|
||||
v-else>
|
||||
<view
|
||||
class="vip-box__inner "
|
||||
:style="{backgroundImage:`url(${myVip1})`}">
|
||||
<view class="flex flex-ai__center flex-jc__sb">
|
||||
<image
|
||||
class="icon"
|
||||
:src="memberLeverInfo.currentLevel.iconUrl" />
|
||||
<view class="vip-text flex flex-ai__center">
|
||||
{{ memberLeverInfo.currentLevel.levelName }}
|
||||
<view class="process">
|
||||
<view
|
||||
class="schedule"
|
||||
:style="{width: `${memberLeverInfo.needGrowthValue/memberLeverInfo.nextLevel.growthValue}%`}"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="vip-button">
|
||||
查看权益 >
|
||||
</view>
|
||||
</view>
|
||||
<view class="tips">
|
||||
再获取{{ memberLeverInfo.needGrowthValue }}经验,可升级为{{ memberLeverInfo.nextLevel.levelName }}会员
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 大卡片 -->
|
||||
<view class="big-card">
|
||||
<!-- order card -->
|
||||
<GridCard
|
||||
:list="orderIconList"
|
||||
:dot-info="orderUserCountData"
|
||||
title="我的订单"
|
||||
button-text="查看所有订单"
|
||||
@button-click="toAllOrder"
|
||||
/>
|
||||
|
||||
<!-- footprint card -->
|
||||
<GridCard
|
||||
:list="cardOneList"
|
||||
:dot-info="orderUserCountData"
|
||||
/>
|
||||
|
||||
<GridCard
|
||||
:list="filterCardTwo"
|
||||
:dot-info="orderUserCountData"
|
||||
/>
|
||||
</view>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue'
|
||||
import Header from '@/components/Header/index.vue'
|
||||
|
||||
import { orderUserCount } from '@/api/order'
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { useMainStore } from '@/store/store'
|
||||
import { useRouter } from "@/hooks/useRouter";
|
||||
import { storeToRefs } from "pinia";
|
||||
import GridCard from "@/root/user/components/GridCard.vue";
|
||||
import { accountList, cardOneList, cardTwoList, orderIconList } from "@/root/user/index.data";
|
||||
import { defaultAvatarIcon, mySignIn, myVip1, myVipNone, noneVip } from "@/utils/images";
|
||||
import { useInterface } from "@/hooks/useInterface";
|
||||
import { useJump } from "@/hooks/useJump";
|
||||
import { getUserMemberLevel } from "@/api/member";
|
||||
|
||||
const mainStore = useMainStore()
|
||||
const {user} = storeToRefs(mainStore);
|
||||
const {push} = useRouter()
|
||||
const {toast} = useInterface();
|
||||
const {goSignIn, goMemberCenter} = useJump()
|
||||
const orderUserCountData = ref(null)
|
||||
|
||||
const filterCardTwo = computed(() => {
|
||||
if (!user.value) return []
|
||||
// 判断是否又核销权限
|
||||
if (user.value.writeOffAuthority) {
|
||||
return cardTwoList
|
||||
} else {
|
||||
return cardTwoList.filter(item => item.label !== '订单核销')
|
||||
}
|
||||
})
|
||||
|
||||
function toAllOrder() {
|
||||
if (!user.value) return toast({title: '请先登录'})
|
||||
push({url: '/pages/orderList/orderList'}, {data: {type: -1}})
|
||||
}
|
||||
|
||||
function toUserCenter() {
|
||||
if (!user.value) return toast({title: '请先登录'})
|
||||
push({url: '/pages/userInfo/index'})
|
||||
}
|
||||
|
||||
function toLogin() {
|
||||
push({url: '/pages/login/guid'})
|
||||
}
|
||||
|
||||
const handleOrderUserCount = async () => {
|
||||
orderUserCountData.value = await orderUserCount()
|
||||
}
|
||||
|
||||
// =============================== 会员信息 ====================================
|
||||
const memberLeverInfo = ref({
|
||||
currentGrowthValue: 0,
|
||||
currentLevel: null,
|
||||
needGrowthValue: 0,
|
||||
nextLevel: null
|
||||
})
|
||||
|
||||
async function doGetUserMemberLevel() {
|
||||
memberLeverInfo.value = await getUserMemberLevel()
|
||||
}
|
||||
|
||||
function handleJump(item) {
|
||||
if (!item.path) return toast({title: '暂未开放~'})
|
||||
if (typeof item.path === 'function') {
|
||||
item.path()
|
||||
}
|
||||
}
|
||||
|
||||
onShow(() => {
|
||||
mainStore.getUserInfo()
|
||||
handleOrderUserCount()
|
||||
doGetUserMemberLevel()
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style
|
||||
lang="scss"
|
||||
scoped
|
||||
>
|
||||
.mine-container {
|
||||
background: linear-gradient(to bottom, #fff 0%, #fff 28%, #b0b0b0 40%, #fff 41%);
|
||||
|
||||
.userinfo-box {
|
||||
@include usePadding(32, 0);
|
||||
width: 100%;
|
||||
margin: 50rpx 0 0 0;
|
||||
|
||||
&__inner {
|
||||
@include useFlex(space-between, center);
|
||||
|
||||
.head {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
border-radius: 50%;
|
||||
border: 5rpx solid #fff;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
@include useFlex(space-between, center);
|
||||
padding-left: 30rpx;
|
||||
font-size: 34rpx;
|
||||
}
|
||||
|
||||
.sign-box {
|
||||
@include useFlex(center, center);
|
||||
@include usePadding(16, 12);
|
||||
border: 1rpx solid #E5E5E5;
|
||||
font-weight: bold;
|
||||
font-size: 24rpx;
|
||||
border-radius: 50rpx;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&.no-login {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.account-box {
|
||||
width: 100%;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
margin: 32rpx 0;
|
||||
|
||||
.account-item {
|
||||
@include useFlex(center, center, column);
|
||||
font-weight: bold;
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
position: relative;
|
||||
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 1rpx;
|
||||
height: 50%;
|
||||
background: $tips-color;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:after {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $tips-color;
|
||||
font-size: 24rpx;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vip-box {
|
||||
width: 100%;
|
||||
height: 132rpx;
|
||||
@include usePadding(32, 0);
|
||||
|
||||
&__inner {
|
||||
@include usePadding(32, 25);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 100%;
|
||||
|
||||
.icon {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
}
|
||||
|
||||
.vip-text {
|
||||
width: 60%;
|
||||
color: #FFF8E8;
|
||||
font-weight: bold;
|
||||
font-size: 28rpx;
|
||||
|
||||
.process {
|
||||
flex-grow: 1;
|
||||
height: 10rpx;
|
||||
margin-left: 12rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
position: relative;
|
||||
|
||||
.schedule {
|
||||
height: 100%;
|
||||
background: #FFF8E8;
|
||||
border-radius: 10rpx;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vip-button {
|
||||
@include usePadding(0, 10);
|
||||
color: #FFF8E8;
|
||||
font-size: 24rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.tips {
|
||||
margin-top: 10rpx;
|
||||
color: #FFF8E8;
|
||||
font-size: 20rpx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.vip-none {
|
||||
.vip-button {
|
||||
@include usePadding(24, 10);
|
||||
background: linear-gradient(45deg, #FAEECB, #F2D7A9);
|
||||
color: #272A3F;
|
||||
font-size: 24rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.big-card {
|
||||
width: 100%;
|
||||
background: #f6f6f6;
|
||||
border-radius: 30rpx;
|
||||
@include usePadding(32, 32);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
Reference in New Issue
Block a user