565 lines
11 KiB
Vue
565 lines
11 KiB
Vue
<template>
|
||
<view class="quota-manage-container">
|
||
<!-- 页面标题 -->
|
||
<view class="page-header">
|
||
<view class="header-left" @click="goBack">
|
||
<view class="back-icon">←</view>
|
||
</view>
|
||
<view class="header-title">赠会员额度分配</view>
|
||
<view class="header-right" @click="saveQuota">
|
||
<view class="save-btn">保存</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 筛选条件 -->
|
||
<view class="filter-section">
|
||
<view class="filter-row">
|
||
<view class="filter-item">
|
||
<view class="filter-label">选择月份</view>
|
||
<view class="filter-control">
|
||
<picker
|
||
mode="date"
|
||
fields="month"
|
||
:value="currentMonth"
|
||
start="2026-01"
|
||
end="2026-12"
|
||
@change="onMonthChange"
|
||
class="picker"
|
||
>
|
||
<view class="picker-text">{{ currentMonthDisplay }}</view>
|
||
</picker>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 总额度设置 -->
|
||
<view class="total-quota-section">
|
||
<view class="section-title">总额度设置</view>
|
||
<view class="quota-card">
|
||
<view class="quota-item">
|
||
<view class="quota-label">月度赠会员总额度</view>
|
||
<view class="quota-control">
|
||
<view class="quota-value">{{ totalQuota }}</view>
|
||
<view class="quota-unit">个</view>
|
||
</view>
|
||
</view>
|
||
<view class="quota-hint">
|
||
• 总额度将分配给所有分销员
|
||
• 单个分销员最高可分配额度为总额度的50%
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 分销员额度分配 -->
|
||
<view class="distributor-quota-section">
|
||
<view class="section-title">分销员额度分配</view>
|
||
<view class="quota-list">
|
||
<view
|
||
v-for="(distributor, index) in distributors"
|
||
:key="distributor.id"
|
||
class="quota-item"
|
||
>
|
||
<view class="distributor-info">
|
||
<view class="distributor-name">{{ distributor.distributorName }}</view>
|
||
<view class="distributor-id">ID: {{ distributor.distributorId }}</view>
|
||
</view>
|
||
<view class="quota-control">
|
||
<input
|
||
v-model="distributor.num"
|
||
type="number"
|
||
class="quota-input"
|
||
placeholder="0"
|
||
min="0"
|
||
:max="maxDistributorQuota(distributor.num)"
|
||
/>
|
||
<view class="quota-unit">个</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 配额统计 -->
|
||
<view class="quota-stats">
|
||
<view class="stats-item">
|
||
<view class="stats-label">已分配额度:</view>
|
||
<view class="stats-value">{{ allocatedQuota }} 个</view>
|
||
</view>
|
||
<view class="stats-item">
|
||
<view class="stats-label">剩余额度:</view>
|
||
<view class="stats-value" :class="{ 'warning': remainingQuota < 0 }">
|
||
{{ remainingQuota }} 个
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed, onMounted } from "vue"
|
||
import { getQuotaInfoWithUser, saveQuotaInfo, getQuotaList } from "@/api/member/quota"
|
||
|
||
// 当前月份
|
||
const currentMonth = ref(new Date().toISOString().substring(0, 7))
|
||
const currentMonthDisplay = ref(new Date().toISOString().substring(0, 7))
|
||
|
||
// 总额度
|
||
const totalQuota = ref(100)
|
||
|
||
// 分销员列表
|
||
const distributors = ref([])
|
||
|
||
const loadCurrentMonthQuota = () => {
|
||
getQuotaInfoWithUser({
|
||
year: currentMonth.value.split('-')[0],
|
||
month: currentMonth.value.split('-')[1]
|
||
}).then(res => {
|
||
totalQuota.value = res.data.num || 0
|
||
})
|
||
|
||
getQuotaList({
|
||
year: currentMonth.value.split('-')[0],
|
||
month: currentMonth.value.split('-')[1]
|
||
}).then(res => {
|
||
distributors.value = res.data || []
|
||
})
|
||
}
|
||
|
||
// 计算已分配额度
|
||
const allocatedQuota = computed(() => {
|
||
return distributors.value.reduce((sum, distributor) => {
|
||
return sum + parseInt(distributor.num || 0)
|
||
}, 0)
|
||
})
|
||
|
||
// 计算剩余额度
|
||
const remainingQuota = computed(() => {
|
||
return totalQuota.value - allocatedQuota.value
|
||
})
|
||
|
||
const maxDistributorQuota = (count) => {
|
||
return remainingQuota.value ? count + remainingQuota.value : count
|
||
}
|
||
|
||
// 返回上一页
|
||
function goBack() {
|
||
uni.navigateBack({ delta: 1 })
|
||
}
|
||
|
||
// 月份变更
|
||
function onMonthChange(e) {
|
||
currentMonth.value = e.detail.value
|
||
const date = new Date(e.detail.value)
|
||
currentMonthDisplay.value = new Date(date).toISOString().substring(0, 7)
|
||
loadCurrentMonthQuota()
|
||
}
|
||
|
||
// 保存配额
|
||
function saveQuota() {
|
||
if (!totalQuota.value || totalQuota.value <= 0) {
|
||
uni.showToast({
|
||
title: '请设置有效的总额度',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
if (remainingQuota.value < 0) {
|
||
uni.showToast({
|
||
title: '已分配额度超过总额度',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
uni.showLoading({ title: '保存中...' })
|
||
|
||
saveQuotaInfo({
|
||
year: currentMonth.value.split('-')[0],
|
||
month: currentMonth.value.split('-')[1],
|
||
nums: distributors.value.map(distributor => {
|
||
return {
|
||
distributorId: distributor.distributorId,
|
||
num: distributor.num
|
||
}
|
||
})
|
||
}).then(() => {
|
||
uni.hideLoading()
|
||
uni.showToast({
|
||
title: '保存成功',
|
||
icon: 'success'
|
||
})
|
||
})
|
||
}
|
||
|
||
onMounted(() => {
|
||
loadCurrentMonthQuota()
|
||
})
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
/* #ifndef APP-NVUE */
|
||
page {
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
background-color: #f5f7fa;
|
||
min-height: 100%;
|
||
height: auto;
|
||
}
|
||
|
||
view {
|
||
font-size: 14px;
|
||
line-height: inherit;
|
||
}
|
||
/* #endif */
|
||
|
||
.quota-manage-container {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 页面头部 */
|
||
.page-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
height: 120rpx;
|
||
background-color: #fff;
|
||
padding: 0 32rpx;
|
||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||
}
|
||
|
||
.header-left {
|
||
width: 60rpx;
|
||
}
|
||
|
||
.back-icon {
|
||
font-size: 40rpx;
|
||
color: #303133;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.header-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
}
|
||
|
||
.header-right {
|
||
width: 60rpx;
|
||
text-align: right;
|
||
}
|
||
|
||
.save-btn {
|
||
font-size: 28rpx;
|
||
color: #409eff;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
}
|
||
|
||
/* 筛选条件 */
|
||
.filter-section {
|
||
padding: 24rpx 32rpx;
|
||
background-color: #fff;
|
||
margin: 16rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.filter-row {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.filter-item {
|
||
flex: 1;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.filter-control {
|
||
background-color: #f9f9f9;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 8rpx;
|
||
padding: 16rpx;
|
||
}
|
||
|
||
.picker {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.picker-text {
|
||
font-size: 24rpx;
|
||
color: #303133;
|
||
}
|
||
|
||
/* 通用部分样式 */
|
||
.total-quota-section,
|
||
.distributor-quota-section {
|
||
padding: 32rpx;
|
||
background-color: #fff;
|
||
margin: 0 16rpx 16rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
margin-bottom: 24rpx;
|
||
padding-left: 12rpx;
|
||
border-left: 8rpx solid #409eff;
|
||
line-height: 1.2;
|
||
}
|
||
|
||
/* 总额度设置 */
|
||
.quota-card {
|
||
background-color: #f9f9f9;
|
||
border-radius: 12rpx;
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.quota-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.quota-label {
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
}
|
||
|
||
.quota-control {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.quota-input {
|
||
width: 120rpx;
|
||
height: 60rpx;
|
||
background-color: #fff;
|
||
border: 1rpx solid #dcdfe6;
|
||
border-radius: 8rpx;
|
||
padding: 0 16rpx;
|
||
text-align: center;
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.quota-unit {
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
}
|
||
|
||
.quota-hint {
|
||
font-size: 20rpx;
|
||
color: #909399;
|
||
margin-top: 16rpx;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
/* 分销员额度分配 */
|
||
.quota-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.distributor-info {
|
||
flex: 1;
|
||
margin-right: 24rpx;
|
||
}
|
||
|
||
.distributor-name {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
color: #303133;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.distributor-id {
|
||
font-size: 20rpx;
|
||
color: #909399;
|
||
}
|
||
|
||
/* 配额统计 */
|
||
.quota-stats {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
padding: 24rpx;
|
||
background-color: #fff;
|
||
margin: 0 16rpx 32rpx;
|
||
border-radius: 16rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||
}
|
||
|
||
.stats-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
}
|
||
|
||
.stats-label {
|
||
font-size: 24rpx;
|
||
color: #606266;
|
||
}
|
||
|
||
.stats-value {
|
||
font-size: 28rpx;
|
||
font-weight: bold;
|
||
color: #303133;
|
||
}
|
||
|
||
.stats-value.warning {
|
||
color: #f56c6c;
|
||
}
|
||
|
||
/* 平板和大屏响应式 */
|
||
@media screen and (min-width: 768px) {
|
||
.quota-manage-container {
|
||
max-width: 900px;
|
||
margin: 0 auto;
|
||
width: 100%;
|
||
}
|
||
|
||
.filter-section {
|
||
margin: 32rpx 24rpx;
|
||
padding: 32rpx;
|
||
}
|
||
|
||
.total-quota-section,
|
||
.distributor-quota-section {
|
||
margin: 0 32rpx 24rpx;
|
||
padding: 40rpx;
|
||
}
|
||
|
||
.quota-stats {
|
||
margin: 0 32rpx 32rpx;
|
||
padding: 32rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 36rpx;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.picker-text {
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.filter-control {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.quota-item {
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.quota-label {
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.quota-input {
|
||
width: 180rpx;
|
||
height: 80rpx;
|
||
font-size: 28rpx;
|
||
padding: 0 20rpx;
|
||
}
|
||
|
||
.quota-unit {
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.quota-hint {
|
||
font-size: 22rpx;
|
||
}
|
||
|
||
.distributor-name {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.distributor-id {
|
||
font-size: 22rpx;
|
||
}
|
||
|
||
.stats-label {
|
||
font-size: 26rpx;
|
||
}
|
||
|
||
.stats-value {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.quota-list {
|
||
gap: 24rpx;
|
||
}
|
||
}
|
||
|
||
/* 大屏设备响应式 */
|
||
@media screen and (min-width: 1024px) {
|
||
.quota-manage-container {
|
||
max-width: 1000px;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 40rpx;
|
||
}
|
||
|
||
.filter-label {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.picker-text {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.quota-label {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.quota-input {
|
||
width: 200rpx;
|
||
height: 90rpx;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.quota-unit {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.quota-hint {
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.distributor-name {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.distributor-id {
|
||
font-size: 24rpx;
|
||
}
|
||
|
||
.stats-label {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.stats-value {
|
||
font-size: 36rpx;
|
||
}
|
||
}
|
||
</style> |