From 88c095a266a4fe3792ee50997b55af48ba68d061 Mon Sep 17 00:00:00 2001 From: dzl <786316265@qq.com> Date: Fri, 12 Sep 2025 16:54:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9=E9=83=A8=E5=88=86=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Agents.vue | 167 ++++++++++++++++++++++++++++++++++++---- src/views/Dashboard.vue | 14 ++-- 2 files changed, 162 insertions(+), 19 deletions(-) diff --git a/src/views/Agents.vue b/src/views/Agents.vue index 0c9c60d..cc0ae13 100644 --- a/src/views/Agents.vue +++ b/src/views/Agents.vue @@ -49,7 +49,7 @@
- + @@ -57,26 +57,33 @@ - - - - + - - + /> + + + + 查询 +
+ + 重置 + 刷新 @@ -525,12 +532,14 @@ import { ref, reactive, onMounted, computed } from 'vue' import { ElMessage, ElMessageBox } from 'element-plus' import { Search, Refresh } from '@element-plus/icons-vue' import api from '@/utils/api' +import axios from 'axios' // 响应式数据 const loading = ref(false) const agents = ref([]) const stats = ref({}) const cities = ref([]) +const regionOptions = ref([]) const showDetailDialog = ref(false) const showPasswordDialog = ref(false) const selectedAgent = ref(null) @@ -542,6 +551,7 @@ const passwordFormRef = ref() const filters = reactive({ status: '', city: '', + region: [], search: '' }) @@ -611,12 +621,25 @@ const passwordRules = { const loadAgents = async () => { loading.value = true try { + // 从级联选择器中提取省市区信息 + const [provinceName, cityName, districtName] = filters.region || [] + + // 调试信息 + console.log('filters.region:', filters.region) + console.log('解析后的省市区:', { provinceName, cityName, districtName }) + const params = { page: pagination.page, limit: pagination.limit, - ...filters + status: filters.status, + city: cityName || '', + province: provinceName || '', + district: districtName || '', + search: filters.search } + console.log('发送到后端的参数:', params) + const { data } = await api.get('/admin/agents', { params }) agents.value = data.data.agents pagination.total = data.data.total @@ -1079,9 +1102,125 @@ const getTransferTypeType = (type) => { return types[type] || 'info' } +// 地区相关函数 +const loadRegionOptions = async () => { + try { + // 获取所有省份 + const provincesResponse = await api.get('/regions/provinces') + console.log('获取省份数据:', provincesResponse) + if (!provincesResponse.data.success) { + throw new Error(provincesResponse.data.message || '获取省份数据失败') + } + + // 转换数据格式为级联选择器需要的格式 + const provinces = provincesResponse.data.data || [] + regionOptions.value = provinces.map(province => ({ + value: province.label, // 使用label作为value + label: province.label, + children: (province.children || []).map(city => ({ + value: city.label, + label: city.label, + children: (city.children || []).map(district => ({ + value: district.label, + label: district.label + })) + })) + })) + + console.log('转换后的地区数据:', regionOptions.value) + + } catch (error) { + console.error('获取省市区数据失败:', error) + ElMessage.error(error.message || '获取省市区数据失败') + + // 如果API获取失败,使用浙江省数据作为默认数据 + await loadFallbackRegionData() + } +} + +// 回退方案:加载浙江省数据 +const loadFallbackRegionData = async () => { + try { + const zhejiangResponse = await api.get('/regions/zhejiang') + if (zhejiangResponse.data.success) { + const zhejiangData = zhejiangResponse.data.data || [] + // 将浙江省数据转换为级联选择器格式 + const cityMap = new Map() + + zhejiangData.forEach(item => { + if (!cityMap.has(item.city_name)) { + cityMap.set(item.city_name, { + value: item.city_name, + label: item.city_name, + children: [] + }) + } + + // 添加区县数据 + if (item.district_name) { + cityMap.get(item.city_name).children.push({ + value: item.district_name, + label: item.district_name + }) + } + }) + + regionOptions.value = [{ + value: '浙江省', + label: '浙江省', + children: Array.from(cityMap.values()) + }] + console.log('已加载浙江省地区数据作为默认选项') + } else { + throw new Error('获取浙江省数据也失败') + } + } catch (fallbackError) { + console.error('浙江省数据获取失败,使用硬编码数据:', fallbackError) + // 最终回退到硬编码数据 + regionOptions.value = [ + { + value: '浙江省', + label: '浙江省', + children: [ + { + value: '宁波市', + label: '宁波市', + children: [ + { value: '鄞州区', label: '鄞州区' }, + { value: '海曙区', label: '海曙区' }, + { value: '江北区', label: '江北区' }, + { value: '北仑区', label: '北仑区' } + ] + }, + { + value: '杭州市', + label: '杭州市', + children: [ + { value: '西湖区', label: '西湖区' }, + { value: '上城区', label: '上城区' }, + { value: '拱墅区', label: '拱墅区' }, + { value: '余杭区', label: '余杭区' } + ] + } + ] + } + ] + } +} + +// 重置筛选器 +const resetFilters = () => { + filters.status = '' + filters.city = '' + filters.region = [] + filters.search = '' + loadAgents() +} + // 生命周期 onMounted(() => { - loadAgents() + loadRegionOptions() + loadAgents() // 页面初始化时加载代理数据 }) diff --git a/src/views/Dashboard.vue b/src/views/Dashboard.vue index 25eb06b..8b87d89 100644 --- a/src/views/Dashboard.vue +++ b/src/views/Dashboard.vue @@ -309,6 +309,7 @@ const statsData = ref({ activeUsers: 0, activeRate: 0, avgTransferAmount: 0, + avgTransferAmount_to_lastmonth: 0, avgAmountChange: 0, successRate: 0, monthlySuccessCount: 0 @@ -393,7 +394,7 @@ const stats = computed(() => [ value: `¥${(statsData.value.avgTransferAmount || 0).toLocaleString()}`, icon: 'ShoppingBag', class: 'stat-warning', - change: `较上月 ${statsData.value.avgAmountChange > 0 ? '+' : ''}${statsData.value.avgAmountChange || 0}%`, + change: `较上月 ${ statsData.value.avgTransferAmount_to_lastmonth || 0}%`, changeClass: (statsData.value.avgAmountChange || 0) >= 0 ? 'positive' : 'negative', changeIcon: (statsData.value.avgAmountChange || 0) >= 0 ? 'ArrowUp' : 'ArrowDown' }, @@ -684,10 +685,11 @@ const fetchDashboardData = async () => { todayUsers: userStats.value.todayUsers || 0, yesterdayUsers: userStats.value.yesterdayUsers || 0, activeUsers: userStats.value.activeUsers || Math.floor((userStats.value.totalUsers || 100) * 0.3), - activeRate: userStats.value.activeRate || Math.floor(Math.random() * 30) + 60, - avgTransferAmount: transferStats.value.total?.participated_transfers > 0 ? Math.floor((transferStats.value.total?.pending || 0) / transferStats.value.total.participated_transfers) : 0, + activeRate: userStats.value.activeRate || 0, + avgTransferAmount: transferStats.value.total?.participated_transfers > 0 ? transferStats.value.total.participated_transfers : 0, + avgTransferAmount_to_lastmonth: (transferStats.value.lastMonth.participated_transfers / transferStats.value.lastMonth.transfers * 100).toFixed(2), avgAmountChange: (() => { - const currentAvg = transferStats.value.total?.participated_transfers > 0 ? Math.floor((transferStats.value.total?.pending || 0) / transferStats.value.total.participated_transfers) : 0; + const currentAvg = transferStats.value.total?.participated_transfers > 0 ? transferStats.value.total.participated_transfers : 0; const lastMonthAvg = transferStats.value.lastMonth?.participated_transfers > 0 ? Math.floor((transferStats.value.lastMonth?.amount || 0) / transferStats.value.lastMonth.participated_transfers) : 0; if (lastMonthAvg === 0) return 0; return Math.round(((currentAvg - lastMonthAvg) / lastMonthAvg) * 100); @@ -749,7 +751,9 @@ const fetchChartData = async () => { // 使用真实的用户类型分布数据 userTypeData.value = [ { name: '普通用户', value: userStats.value.regularUsers || 0, itemStyle: { color: '#409eff' } }, - // { name: '管理员', value: userStats.value.adminUsers || 0, itemStyle: { color: '#e6a23c' } } + { name: '直营', value: userStats.value.directly_operated || 0, itemStyle: { color: '#e6a23c' } }, + { name: '代理', value: userStats.value.agent || 0, itemStyle: { color: '#909399' } }, + { name: '直营代理', value: userStats.value.agent_directly || 0, itemStyle: { color: '#67c23a' } } ] } catch (error) {