feat(DetailedDataTable): 重构筛选器为层级联动选择并添加禁用状态
重构筛选器组件,将原有的独立下拉框改为基于组织架构的层级联动选择(中心领导->高级经理->经理),并添加禁用状态逻辑。当未选择上级时,下级选择器将被禁用。同时移除注释掉的代码和调试日志。
This commit is contained in:
@@ -6,10 +6,33 @@
|
||||
<div class="data-table-container">
|
||||
<!-- 筛选器 -->
|
||||
<div class="table-filters">
|
||||
<div class="filter-group"><label>中心:</label><select v-model="filters.department"><option value="">全部中心</option><option>销售一部</option><option>销售二部</option><option>销售三部</option></select></div>
|
||||
<div class="filter-group"><label>高级经理:</label><select v-model="filters.position"><option value="">全部高级经理</option><option>经理1</option><option>经理2</option><option>经理3</option></select></div>
|
||||
<div class="filter-group"><label>经理:</label><select v-model="filters.timeRange"><option value="today">经理1</option><option value="week">经理2</option><option value="month">经理3</option></select></div>
|
||||
<!-- <div class="filter-group"><label>成交状态:</label><select v-model="filters.dealStatus"><option value="">全部</option><option>已成交</option><option>跟进中</option><option>已失效</option></select></div> -->
|
||||
<div class="filter-group">
|
||||
<label>中心领导:</label>
|
||||
<select v-model="filters.centerLeader" @change="onCenterLeaderChange">
|
||||
<option value="">全部中心领导</option>
|
||||
<option v-for="leader in centerLeaders" :key="leader.name" :value="leader.name">
|
||||
{{ leader.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>高级经理:</label>
|
||||
<select v-model="filters.advancedManager" @change="onAdvancedManagerChange" :disabled="!filters.centerLeader">
|
||||
<option value="">全部高级经理</option>
|
||||
<option v-for="manager in availableAdvancedManagers" :key="manager.name" :value="manager.name">
|
||||
{{ manager.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter-group">
|
||||
<label>经理:</label>
|
||||
<select v-model="filters.manager" :disabled="!filters.advancedManager">
|
||||
<option value="">全部经理</option>
|
||||
<option v-for="manager in availableManagers" :key="manager.name" :value="manager.name">
|
||||
{{ manager.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
@@ -59,24 +82,51 @@ import { ref, computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
tableData: { type: Array, required: true },
|
||||
selectedPerson: { type: Object, default: null }
|
||||
});
|
||||
selectedPerson: { type: Object, default: null },
|
||||
levelTree: { type: Object, default: () => ({}) }
|
||||
});
|
||||
defineEmits(['update:selectedPerson']);
|
||||
|
||||
const filters = ref({ department: '', position: '', timeRange: 'month', dealStatus: '' });
|
||||
const filters = ref({ centerLeader: '', advancedManager: '', manager: '', dealStatus: '' });
|
||||
const sortField = ref('dealRate');
|
||||
const sortOrder = ref('desc');
|
||||
|
||||
const centerLeaders = computed(() => {
|
||||
return props.levelTree?.level_tree?.center_leaders || [];
|
||||
});
|
||||
|
||||
const availableAdvancedManagers = computed(() => {
|
||||
if (!filters.value.centerLeader) return [];
|
||||
const leader = centerLeaders.value.find(l => l.name === filters.value.centerLeader);
|
||||
return leader ? leader.advanced_managers || [] : [];
|
||||
});
|
||||
|
||||
const availableManagers = computed(() => {
|
||||
if (!filters.value.advancedManager) return [];
|
||||
const manager = availableAdvancedManagers.value.find(m => m.name === filters.value.advancedManager);
|
||||
return manager ? manager.managers || [] : [];
|
||||
});
|
||||
|
||||
const filteredTableData = computed(() => {
|
||||
let filtered = props.tableData;
|
||||
if (filters.value.department) filtered = filtered.filter(item => item.department === filters.value.department);
|
||||
if (filters.value.position) filtered = filtered.filter(item => item.position === filters.value.position);
|
||||
if (filters.value.centerLeader) filtered = filtered.filter(item => item.centerLeader === filters.value.centerLeader);
|
||||
if (filters.value.advancedManager) filtered = filtered.filter(item => item.advancedManager === filters.value.advancedManager);
|
||||
if (filters.value.manager) filtered = filtered.filter(item => item.manager === filters.value.manager);
|
||||
return filtered.sort((a, b) => {
|
||||
const aValue = a[sortField.value], bValue = b[sortField.value];
|
||||
return sortOrder.value === 'desc' ? bValue - aValue : aValue - bValue;
|
||||
});
|
||||
});
|
||||
|
||||
const onCenterLeaderChange = () => {
|
||||
filters.value.advancedManager = '';
|
||||
filters.value.manager = '';
|
||||
};
|
||||
|
||||
const onAdvancedManagerChange = () => {
|
||||
filters.value.manager = '';
|
||||
};
|
||||
|
||||
const sortBy = (field) => {
|
||||
if (sortField.value === field) sortOrder.value = sortOrder.value === 'desc' ? 'asc' : 'desc';
|
||||
else { sortField.value = field; sortOrder.value = 'desc'; }
|
||||
@@ -100,6 +150,7 @@ const formatDuration = (minutes) => {
|
||||
.filter-group { display: flex; flex-direction: column; gap: 4px; }
|
||||
.filter-group label { font-size: 12px; font-weight: 600; color: #4a5568; }
|
||||
.filter-group select { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; }
|
||||
.filter-group select:disabled { background-color: #f7fafc; color: #a0aec0; cursor: not-allowed; }
|
||||
.data-table { overflow-x: auto; border-radius: 8px; border: 1px solid #e2e8f0; }
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th { background: #f7fafc; padding: 12px 16px; text-align: left; font-weight: 600; color: #4a5568; border-bottom: 1px solid #e2e8f0; font-size: 12px; }
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
<div class="dashboard-row row-4">
|
||||
<DetailedDataTable
|
||||
:table-data="tableData"
|
||||
:level-tree="levelTree"
|
||||
v-model:selected-person="selectedPerson"
|
||||
/>
|
||||
<DataDetailCard :selected-person="selectedPerson" />
|
||||
@@ -674,34 +675,6 @@ async function getConversionComparison(data) {
|
||||
const res = await getCompanyConversionRateVsLast(params)
|
||||
console.log(111111,res)
|
||||
conversionComparison.value = res.data
|
||||
/**
|
||||
* "data": {
|
||||
"user_name": "赵世敬",
|
||||
"user_level": 5,
|
||||
"check_type": "month",
|
||||
"company_current_rate": {
|
||||
"线索总数": 14050,
|
||||
"加微": 3238,
|
||||
"到课": 7613,
|
||||
"付定金": 167,
|
||||
"成交": 135
|
||||
},
|
||||
"company_last_rate": {
|
||||
"线索总数": 17598,
|
||||
"加微": 3328,
|
||||
"到课": 3543,
|
||||
"付定金": 0,
|
||||
"成交": 0
|
||||
},
|
||||
"company_current_vs_last_rate": {
|
||||
"线索总数": "-20.16%",
|
||||
"加微": "-2.70%",
|
||||
"到课": "+114.87%",
|
||||
"付定金": "+∞%",
|
||||
"成交": "+∞%"
|
||||
}
|
||||
}
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error("获取转化对比失败:", error);
|
||||
}
|
||||
@@ -942,25 +915,6 @@ async function getCenterSalesRank(data) {
|
||||
const res = await getCenterPerformanceRank(params)
|
||||
console.log(1222222,res)
|
||||
centerSalesRank.value = res.data
|
||||
/**
|
||||
* "data": {
|
||||
"user_name": "赵世敬",
|
||||
"user_level": 5,
|
||||
"rank_type": "periods",
|
||||
"center_performance_periods_rank": [
|
||||
{
|
||||
"center_leader": "郭可英",
|
||||
"total_deals": 0,
|
||||
"average_deals_per_member": 0
|
||||
},
|
||||
{
|
||||
"center_leader": "刘瑞",
|
||||
"total_deals": 4,
|
||||
"average_deals_per_member": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error("获取全中心业绩排行榜失败:", error);
|
||||
}
|
||||
@@ -975,49 +929,6 @@ async function getCustomerTypeRatio(data) {
|
||||
const res = await getCustomerTypeDistribution(params)
|
||||
console.log(1222222,res)
|
||||
customerTypeRatio.value = res.data
|
||||
/**
|
||||
* data
|
||||
:
|
||||
customer_type_distribution
|
||||
:
|
||||
Array(7)
|
||||
0
|
||||
:
|
||||
{category: '初二', ratio: '37.50%'}
|
||||
1
|
||||
:
|
||||
{category: '高一', ratio: '18.75%'}
|
||||
2
|
||||
:
|
||||
{category: '初一', ratio: '12.50%'}
|
||||
3
|
||||
:
|
||||
{category: '五年级', ratio: '12.50%'}
|
||||
4
|
||||
:
|
||||
{category: '六年级', ratio: '6.25%'}
|
||||
5
|
||||
:
|
||||
{category: '三年级以下', ratio: '6.25%'}
|
||||
6
|
||||
:
|
||||
{category: '高三', ratio: '6.25%'}
|
||||
length
|
||||
:
|
||||
7
|
||||
[[Prototype]]
|
||||
:
|
||||
Array(0)
|
||||
distribution_type
|
||||
:
|
||||
"child_education"
|
||||
user_level
|
||||
:
|
||||
5
|
||||
user_name
|
||||
:
|
||||
"赵世敬"
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error("获取客户类型占比失败:", error);
|
||||
}
|
||||
@@ -1029,50 +940,6 @@ async function getCustomerUrgency() {
|
||||
const res = await getUrgentNeedToAddress()
|
||||
console.log(1222222,res)
|
||||
customerUrgency.value = res.data
|
||||
/**
|
||||
* data
|
||||
:
|
||||
company_urgent_issue_counts
|
||||
:
|
||||
回归学校
|
||||
:
|
||||
2
|
||||
少玩手机
|
||||
:
|
||||
6
|
||||
心理健康
|
||||
:
|
||||
0
|
||||
成绩提升
|
||||
:
|
||||
8
|
||||
[[Prototype]]
|
||||
:
|
||||
Object
|
||||
company_urgent_issue_ratio
|
||||
:
|
||||
回归学校
|
||||
:
|
||||
"12.50%"
|
||||
少玩手机
|
||||
:
|
||||
"37.50%"
|
||||
心理健康
|
||||
:
|
||||
"0.00%"
|
||||
成绩提升
|
||||
:
|
||||
"50.00%"
|
||||
[[Prototype]]
|
||||
:
|
||||
Object
|
||||
user_level
|
||||
:
|
||||
5
|
||||
user_name
|
||||
:
|
||||
"赵世敬"
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error("获取客户迫切解决的问题排行榜失败:", error);
|
||||
}
|
||||
@@ -1084,6 +951,55 @@ async function CusotomGetLevelTree() {
|
||||
const res = await getLevelTree()
|
||||
console.log(1222222,res)
|
||||
levelTree.value = res.data
|
||||
/**
|
||||
* "data": {
|
||||
"user_name": "赵世敬",
|
||||
"user_level": 5,
|
||||
"level_tree": {
|
||||
"center_leaders": [
|
||||
{
|
||||
"name": "郭可英",
|
||||
"advanced_managers": [
|
||||
{
|
||||
"name": "李小燕",
|
||||
"managers": []
|
||||
},
|
||||
{
|
||||
"name": "郭子奇",
|
||||
"managers": [
|
||||
{
|
||||
"name": "杨朵朵"
|
||||
},
|
||||
{
|
||||
"name": "张明起"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "刘瑞",
|
||||
"advanced_managers": [
|
||||
{
|
||||
"name": "陈盼良",
|
||||
"managers": [
|
||||
{
|
||||
"name": "马然"
|
||||
},
|
||||
{
|
||||
"name": "杨启晨"
|
||||
},
|
||||
{
|
||||
"name": "韦少杰"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error("获取级别树失败:", error);
|
||||
}
|
||||
@@ -1110,9 +1026,9 @@ onMounted(async() => {
|
||||
// await getConversionComparison('month')
|
||||
// await getCompanySalesRank('red')
|
||||
// await getCenterSalesRank('periods')
|
||||
await getCustomerTypeRatio('child_education')
|
||||
await getCustomerUrgency()
|
||||
|
||||
// await getCustomerTypeRatio('child_education')
|
||||
// await getCustomerUrgency()
|
||||
await CusotomGetLevelTree()
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user