Browse Source

feat: 分销页面;

pull/1/head
Fox-33 1 month ago
parent
commit
75654a9084
4 changed files with 458 additions and 38 deletions
  1. +117
    -0
      components/base/suspendDropdown.vue
  2. +1
    -1
      pages/index/center.vue
  3. +12
    -35
      pages/index/record.vue
  4. +328
    -2
      pages_order/mine/team.vue

+ 117
- 0
components/base/suspendDropdown.vue View File

@ -0,0 +1,117 @@
<template>
<view class="drop-down">
<button class="btn-simple" plain @click="openPicker" >
<slot>
<image src="../../static/image/record/filter.png" style="width: 30rpx; height: 30rpx; margin: 10rpx;"></image>
</slot>
</button>
<template v-if="popupVisible">
<view class="drop-down-overlay" @click="closePicker"></view>
<view class="card drop-down-popup">
<view
v-for="item in options"
class="drop-down-option"
:class="[item.value === value ? 'is-active' : '']"
:key="item.value"
@click="onSelect(item.value)"
>
<text>{{ item.label }}</text>
</view>
</view>
</template>
</view>
</template>
<script>
export default {
props: {
value: {
type: String | Number,
default: null,
},
options: {
type: Array,
default() {
return []
}
}
},
data() {
return {
popupVisible: false,
}
},
methods: {
openPicker() {
this.popupVisible = true
},
closePicker() {
this.popupVisible = false
},
onSelect(val) {
const selected = this.value
const newVal = selected === val ? null : val
this.$emit('input', newVal)
this.$emit('change', newVal)
},
},
}
</script>
<style scoped lang="scss">
.drop-down {
position: relative;
clear: both;
&-overlay {
position: fixed;
width: 100vw;
height: calc(100vh - #{$navbar-height} - var(--status-bar-height) - 20rpx);
background: transparent;
bottom: 0;
left: 0;
font-size: 0;
}
&-popup {
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
padding: 16rpx 40rpx;
position: absolute;
z-index: 99;
right: -14rpx;
margin-top: 28rpx;
&:before {
content: ' ';
position: absolute;
top: -28rpx;
right: 14rpx;
width: 0;
height: 0;
border: 14rpx solid transparent;
border-bottom-color: #FFFFFF;
}
}
&-option {
color: #999999;
font-size: 28rpx;
white-space: nowrap;
&.is-active {
color: #1B1B1B;
font-weight: 700;
}
& + & {
margin-top: 16rpx;
}
}
}
</style>

+ 1
- 1
pages/index/center.vue View File

@ -95,7 +95,7 @@
:icon="false"
fontSize="28rpx"
:customStyle="{
padding: 0,
padding: '6rpx 0',
}"
></uv-notice-bar>
</view>


+ 12
- 35
pages/index/record.vue View File

@ -5,7 +5,7 @@
<view class="content">
<view class="card" style="padding-left: 0;">
<view class="card" style="padding-left: 0; padding-right: 10rpx;">
<uv-tabs :list="tabs"
:inactiveStyle="{
color: '#999999',
@ -26,33 +26,11 @@
@click="clickTabs"
>
<template v-slot:right>
<view>
<uv-popup
ref="popup"
:overlayOpacity="0"
:customStyle="{
backgroundColor: 'transparent',
position: 'fixed',
top: '300rpx',
right: '20rpx'
}"
>
<view class="card popup-options">
<view
class="popup-option"
:class="{ 'is-active': item.value === queryParams.auditStatus }"
v-for="item in auditStatusOptions"
:key="item.value"
@click="onSelectAuditStatus(item.value)"
>
<text>{{ item.label }}</text>
</view>
</view>
</uv-popup>
<button class="btn-simple" plain @click="openPicker" >
<image src="../../static/image/record/filter.png" style="width: 30rpx; height: 30rpx;"></image>
</button>
</view>
<suspendDropdown
v-model="queryParams.auditStatus"
:options="auditStatusOptions"
@change="onAuditStatusChange"
></suspendDropdown>
</template>
</uv-tabs>
</view>
@ -93,6 +71,7 @@
<script>
import tabber from '@/components/base/tabbar.vue'
import suspendDropdown from '@/components/base/suspendDropdown.vue'
import { mapGetters } from 'vuex'
const URL_MAPPING = { // state -> url
@ -105,6 +84,7 @@
export default {
components : {
tabber,
suspendDropdown,
},
computed : {
...mapGetters(['userShop']),
@ -225,13 +205,10 @@
this.queryParams.pageSize = 10
this.orderPage()
},
openPicker() {
this.$refs.popup.open();
},
onSelectAuditStatus(val) {
const selected = this.queryParams.auditStatus
this.queryParams.auditStatus = selected === val ? null : val
onAuditStatusChange(auditStatus) {
// todo
// fetch list
},
//
toSharingDetail(id) {


+ 328
- 2
pages_order/mine/team.vue View File

@ -1,18 +1,344 @@
<template>
<view>
<view class="page">
<navbar title="分销" leftClick @leftClick="$utils.navigateBack" />
<view class="content">
<view class="overview">
<view class="title">我的推荐人</view>
<view class="card flex referrer">
<!-- todo: 换回接口提供的 -->
<image class="avatar" src="../static/temp-avatar.png"></image>
<view class="referrer-info">
<view>
<view class="nick-name">裂变星1号</view>
<view>{{ `ID:${12345678}` }}</view>
</view>
<view>
<view class="phone-label">手机号</view>
<view>15234567891</view>
</view>
</view>
</view>
<view class="summary">
<image class="bg" src="../static/center/overview-bg.png"></image>
<view class="flex flex-column summary-info">
<!-- todo: 换回接口提供的 -->
<view class="flex summary-info-total">
<view class="flex flex-column">
<view class="value">100</view>
<view class="label">推荐总人数</view>
</view>
</view>
<view class="flex summary-info-detail">
<view class="flex flex-column">
<view class="label">直接推荐</view>
<view class="value">90</view>
</view>
<view class="flex flex-column">
<view class="label">间接推荐</view>
<view class="value">10</view>
</view>
</view>
</view>
</view>
</view>
<view class="card" style="padding: 20rpx 10rpx 11rpx 0;">
<uv-tabs :list="tabs"
:inactiveStyle="{
color: '#999999',
fontSize: '30rpx',
fontWeight: 500,
whiteSpace: 'nowrap',
}"
:activeStyle="{
color: '#1B1B1B',
fontSize: '38rpx',
fontWeight: 900,
whiteSpace: 'nowrap',
}"
lineHeight="13rpx"
lineWidth="77rpx"
:lineColor="`url('../../static/image/record/slider.png') 100% 100%`"
:scrollable="false"
@click="clickTabs"
>
<template v-slot:right>
<suspendDropdown
v-model="queryParams.role"
:options="roleOptions"
@change="onRoleChange"
></suspendDropdown>
</template>
</uv-tabs>
</view>
<view class="card flex list-item"
v-for="item in recordList.records"
:key="item.id"
>
<image class="avatar" :src="item.avatarUrl"></image>
<view class="flex" style="flex: 1; justify-content: space-between;">
<view class="flex flex-column left">
<view class="highlight">{{ item.nickName }}</view>
<view>{{ item.roleName }}</view>
</view>
<view class="flex flex-column right">
<view>{{ item.createTime }}</view>
<view>{{ item.createDate }}</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import suspendDropdown from '@/components/base/suspendDropdown.vue'
export default {
components: {
suspendDropdown,
},
data() {
return {
tabs: [{
name: '直接推荐'
},
{
name: '间接推荐'
},
],
roleOptions: [
{
label: '普通会员',
value: 0,
},
{
label: '代理商',
value: 1,
},
],
recordList: {
records: [
{
id: '001',
avatarUrl: '../static/temp-avatar.png',
nickName: '裂变星1号',
roleName: '普通会员',
createDate: '2025年2月15日',
createTime: '12:56:48',
},
{
id: '002',
avatarUrl: '../static/temp-avatar.png',
nickName: '裂变星1号',
roleName: '代理商',
createDate: '2025年2月15日',
createTime: '12:56:48',
},
{
id: '003',
avatarUrl: '../static/temp-avatar.png',
nickName: '裂变星1号',
roleName: '普通会员',
createDate: '2025年2月15日',
createTime: '12:56:48',
},
{
id: '004',
avatarUrl: '../static/temp-avatar.png',
nickName: '裂变星1号',
roleName: '代理商',
createDate: '2025年2月15日',
createTime: '12:56:48',
},
{
id: '005',
avatarUrl: '../static/temp-avatar.png',
nickName: '裂变星1号',
roleName: '普通会员',
createDate: '2025年2月15日',
createTime: '12:56:48',
},
],
total: 0,
},
// recordList: {
// records: [],
// total: 0,
// },
state: -1,
queryParams: {
pageNo: 1,
pageSize: 10,
role: null,
},
}
}
},
onShow() {
this.orderPage()
},
//
onReachBottom() {
if(this.queryParams.pageSize < this.recordList.total){
this.queryParams.pageSize += 10
this.orderPage()
}
},
methods: {
orderPage(){
// todo
return
let queryParams = {
...this.queryParams,
}
if(this.state != -1){
queryParams.state = this.state
}
this.$api('orderPage', queryParams, res => {
if(res.code == 200){
this.recordList = res.result
}
})
},
//tab
clickTabs(index) {
if (index == 0) {
this.state = -1;
} else {
this.state = index - 1;
}
this.queryParams.pageSize = 10
this.orderPage()
},
onRoleChange(role) {
// todo
// fetch list
}
},
}
</script>
<style scoped lang="scss">
.page {
background-color: $uni-bg-color;
}
.content {
padding: 20rpx;
}
.overview {
& > .title {
color: #1B1B1B;
font-size: 24rpx;
}
.referrer {
color: #999999;
font-size: 24rpx;
padding: 20rpx;
margin-top: 20rpx;
.avatar {
width: 84rpx;
height: 84rpx;
border-radius: 50%;
margin-right: 20rpx;
}
&-info {
flex: 1;
display: inline-flex;
align-items: center;
justify-content: space-between;
}
.nick-name {
color: #1B1B1B;
font-size: 32rpx;
font-weight: 700;
}
.phone-label {
color: #1B1B1B;
text-align: right;
}
}
.summary {
margin-top: 20rpx;
position: relative;
width: 100%;
height: 373rpx;
color: #04D6A3;
& > .bg {
width: 100%;
height: 100%;
}
&-info {
position: absolute;
top: 0;
left: 0;
justify-content: space-between;
width: 100%;
height: 100%;
padding: 32rpx 78rpx;
box-sizing: border-box;
&-detail {
width: 100%;
justify-content: space-between;
}
}
.label {
font-size: 24rpx;
font-weight: 500;
}
.value {
font-size: 78rpx;
font-weight: 900;
}
}
}
.card {
margin-top: 20rpx;
}
.list {
&-item {
color: #999999;
font-size: 24rpx;
.left {
align-items: flex-start;
}
.right {
align-items: flex-end;
}
.highlight {
color: #1B1B1B;
font-size: 32rpx;
font-weight: 800;
}
.avatar {
width: 84rpx;
height: 84rpx;
border-radius: 50%;
margin-right: 20rpx;
}
}
}
</style>

Loading…
Cancel
Save