This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '收益明细'
|
||||
})
|
||||
48
miniprogram/src/subpackages/distributor/earnings.scss
Normal file
48
miniprogram/src/subpackages/distributor/earnings.scss
Normal file
@@ -0,0 +1,48 @@
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
}
|
||||
.item {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 30px;
|
||||
margin-bottom: 20px;
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
.type {
|
||||
font-size: 30px;
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
.amount {
|
||||
font-size: 32px;
|
||||
color: #ff9800;
|
||||
font-weight: bold;
|
||||
}
|
||||
.source {
|
||||
font-size: 24px;
|
||||
color: #666;
|
||||
}
|
||||
.status {
|
||||
font-size: 24px;
|
||||
color: #00b96b;
|
||||
}
|
||||
}
|
||||
.time {
|
||||
font-size: 22px;
|
||||
color: #999;
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
padding: 100px 0;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 28px;
|
||||
}
|
||||
55
miniprogram/src/subpackages/distributor/earnings.tsx
Normal file
55
miniprogram/src/subpackages/distributor/earnings.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { View, Text } from '@tarojs/components'
|
||||
import Taro, { useLoad } from '@tarojs/taro'
|
||||
import { useState } from 'react'
|
||||
import { distributorEarnings } from '../../api'
|
||||
import './earnings.scss'
|
||||
|
||||
export default function Earnings() {
|
||||
const [list, setList] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useLoad(() => {
|
||||
fetchData()
|
||||
})
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const res: any = await distributorEarnings()
|
||||
// Pagination support check? The backend returns { count, next, previous, results } or just list if no pagination
|
||||
if (res.results) {
|
||||
setList(res.results)
|
||||
} else if (Array.isArray(res)) {
|
||||
setList(res)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
Taro.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='page-container'>
|
||||
{list.length > 0 ? (
|
||||
list.map((item: any) => (
|
||||
<View className='item' key={item.id}>
|
||||
<View className='row'>
|
||||
<Text className='type'>{item.level === 1 ? '直接推广' : '团队奖励'}</Text>
|
||||
<Text className='amount'>+{item.amount}</Text>
|
||||
</View>
|
||||
<View className='row'>
|
||||
<Text className='source'>
|
||||
{item.order_info?.customer_name} - 订单金额 ¥{item.order_info?.total_price}
|
||||
</Text>
|
||||
<Text className='status'>{item.status === 'settled' ? '已结算' : '待结算'}</Text>
|
||||
</View>
|
||||
<Text className='time'>{item.created_at?.replace('T', ' ').substring(0, 19)}</Text>
|
||||
</View>
|
||||
))
|
||||
) : (
|
||||
<View className='empty'>暂无收益记录</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -30,7 +30,9 @@ export default function DistributorIndex() {
|
||||
|
||||
const goInvite = () => Taro.navigateTo({ url: '/subpackages/distributor/invite' })
|
||||
const goWithdraw = () => Taro.navigateTo({ url: '/subpackages/distributor/withdraw' })
|
||||
const showComingSoon = () => Taro.showToast({ title: '功能开发中', icon: 'none' })
|
||||
const goTeam = () => Taro.navigateTo({ url: '/subpackages/distributor/team' })
|
||||
const goEarnings = () => Taro.navigateTo({ url: '/subpackages/distributor/earnings' })
|
||||
const goOrders = () => Taro.navigateTo({ url: '/subpackages/distributor/orders' })
|
||||
|
||||
if (loading) return <View>Loading...</View>
|
||||
if (!info) return <View>Error</View>
|
||||
@@ -61,15 +63,19 @@ export default function DistributorIndex() {
|
||||
<View className='menu-list'>
|
||||
<View className='menu-item' onClick={goInvite}>
|
||||
<Text>推广二维码</Text>
|
||||
<Text className='arrow'>></Text>
|
||||
<Text className='arrow'>{'>'}</Text>
|
||||
</View>
|
||||
<View className='menu-item' onClick={showComingSoon}>
|
||||
<View className='menu-item' onClick={goTeam}>
|
||||
<Text>我的团队</Text>
|
||||
<Text className='arrow'>></Text>
|
||||
<Text className='arrow'>{'>'}</Text>
|
||||
</View>
|
||||
<View className='menu-item' onClick={showComingSoon}>
|
||||
<Text>提现记录</Text>
|
||||
<Text className='arrow'>></Text>
|
||||
<View className='menu-item' onClick={goEarnings}>
|
||||
<Text>收益明细</Text>
|
||||
<Text className='arrow'>{'>'}</Text>
|
||||
</View>
|
||||
<View className='menu-item' onClick={goOrders}>
|
||||
<Text>分销订单</Text>
|
||||
<Text className='arrow'>{'>'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
3
miniprogram/src/subpackages/distributor/orders.config.ts
Normal file
3
miniprogram/src/subpackages/distributor/orders.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '分销订单'
|
||||
})
|
||||
65
miniprogram/src/subpackages/distributor/orders.scss
Normal file
65
miniprogram/src/subpackages/distributor/orders.scss
Normal file
@@ -0,0 +1,65 @@
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
padding: 20px;
|
||||
}
|
||||
.item {
|
||||
background: #fff;
|
||||
border-radius: 12px;
|
||||
padding: 24px;
|
||||
margin-bottom: 20px;
|
||||
.row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
border-bottom: 1px solid #f5f5f5;
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 16px;
|
||||
.order-no {
|
||||
font-size: 24px;
|
||||
color: #666;
|
||||
}
|
||||
.status {
|
||||
font-size: 24px;
|
||||
color: #00b96b;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
margin-bottom: 16px;
|
||||
.img {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 8px;
|
||||
background: #eee;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.title {
|
||||
font-size: 28px;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
}
|
||||
.price {
|
||||
font-size: 32px;
|
||||
color: #ff9800;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
.footer {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 24px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
padding: 100px 0;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 28px;
|
||||
}
|
||||
58
miniprogram/src/subpackages/distributor/orders.tsx
Normal file
58
miniprogram/src/subpackages/distributor/orders.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { View, Text, Image } from '@tarojs/components'
|
||||
import Taro, { useLoad } from '@tarojs/taro'
|
||||
import { useState } from 'react'
|
||||
import { distributorOrders } from '../../api'
|
||||
import './orders.scss'
|
||||
|
||||
export default function Orders() {
|
||||
const [list, setList] = useState<any[]>([])
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useLoad(() => {
|
||||
fetchData()
|
||||
})
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const res: any = await distributorOrders()
|
||||
if (res.results) {
|
||||
setList(res.results)
|
||||
} else if (Array.isArray(res)) {
|
||||
setList(res)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
Taro.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<View className='page-container'>
|
||||
{list.length > 0 ? (
|
||||
list.map((item: any) => (
|
||||
<View className='item' key={item.id}>
|
||||
<View className='row'>
|
||||
<Text className='order-no'>订单号: {item.wechat_trade_no || item.id}</Text>
|
||||
<Text className='status'>{item.status === 'paid' ? '已支付' : item.status}</Text>
|
||||
</View>
|
||||
<View className='content'>
|
||||
<Image className='img' src={item.config_image || ''} mode='aspectFill' />
|
||||
<View className='info'>
|
||||
<Text className='title'>{item.config_name || item.course_title || '商品'}</Text>
|
||||
<Text className='price'>¥{item.total_price}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className='footer'>
|
||||
<Text className='customer'>买家: {item.customer_name}</Text>
|
||||
<Text className='time'>{item.created_at?.split('T')[0]}</Text>
|
||||
</View>
|
||||
</View>
|
||||
))
|
||||
) : (
|
||||
<View className='empty'>暂无分销订单</View>
|
||||
)}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
3
miniprogram/src/subpackages/distributor/team.config.ts
Normal file
3
miniprogram/src/subpackages/distributor/team.config.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default definePageConfig({
|
||||
navigationBarTitleText: '我的团队'
|
||||
})
|
||||
72
miniprogram/src/subpackages/distributor/team.scss
Normal file
72
miniprogram/src/subpackages/distributor/team.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
.page-container {
|
||||
min-height: 100vh;
|
||||
background: #f5f5f5;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
.header {
|
||||
background: #fff;
|
||||
padding: 30px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
margin-bottom: 20px;
|
||||
.stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
.val {
|
||||
font-size: 36px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
.lbl {
|
||||
font-size: 24px;
|
||||
color: #999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list {
|
||||
background: #fff;
|
||||
.list-header {
|
||||
padding: 20px 30px;
|
||||
font-size: 28px;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 20px 30px;
|
||||
border-bottom: 1px solid #eee;
|
||||
.avatar {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
margin-right: 20px;
|
||||
background: #eee;
|
||||
}
|
||||
.info {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.name {
|
||||
font-size: 28px;
|
||||
color: #333;
|
||||
}
|
||||
.time {
|
||||
font-size: 22px;
|
||||
color: #999;
|
||||
margin-top: 6px;
|
||||
}
|
||||
}
|
||||
.level {
|
||||
font-size: 24px;
|
||||
color: #ff9800;
|
||||
}
|
||||
}
|
||||
.empty {
|
||||
padding: 50px;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
62
miniprogram/src/subpackages/distributor/team.tsx
Normal file
62
miniprogram/src/subpackages/distributor/team.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import { View, Text, Image } from '@tarojs/components'
|
||||
import Taro, { useLoad } from '@tarojs/taro'
|
||||
import { useState } from 'react'
|
||||
import { distributorTeam } from '../../api'
|
||||
import './team.scss'
|
||||
|
||||
export default function Team() {
|
||||
const [data, setData] = useState<any>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
|
||||
useLoad(() => {
|
||||
fetchData()
|
||||
})
|
||||
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const res = await distributorTeam()
|
||||
setData(res)
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
Taro.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (loading) return <View className='page-container'>Loading...</View>
|
||||
if (!data) return <View className='page-container'>Error</View>
|
||||
|
||||
return (
|
||||
<View className='page-container'>
|
||||
<View className='header'>
|
||||
<View className='stat'>
|
||||
<Text className='val'>{data.children_count}</Text>
|
||||
<Text className='lbl'>直推人数</Text>
|
||||
</View>
|
||||
<View className='stat'>
|
||||
<Text className='val'>¥{data.second_level_earnings}</Text>
|
||||
<Text className='lbl'>团队贡献收益</Text>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='list'>
|
||||
<View className='list-header'>我的团队成员</View>
|
||||
{data.children?.length > 0 ? (
|
||||
data.children.map((item: any) => (
|
||||
<View className='item' key={item.id}>
|
||||
<Image className='avatar' src={item.user_info?.avatar_url || ''} />
|
||||
<View className='info'>
|
||||
<Text className='name'>{item.user_info?.nickname || '用户'}</Text>
|
||||
<Text className='time'>加入时间: {item.created_at?.split('T')[0]}</Text>
|
||||
</View>
|
||||
<Text className='level'>Lv.{item.level}</Text>
|
||||
</View>
|
||||
))
|
||||
) : (
|
||||
<View className='empty'>暂无成员</View>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user