feat(topOne): 添加各中心营期阶段组件并优化API调用
- 新增PeriodStage组件展示各中心营期阶段信息 - 移除任务管理相关代码,替换为营期阶段展示 - 修改API端点路径,优化优秀录音文件接口调用 - 调整TeamAlerts组件样式,减小最大高度
This commit is contained in:
@@ -65,12 +65,12 @@ export const getDetailedDataTable = (params) => {
|
|||||||
return https.post('/api/v1/level_five/overview/detailed_data_table', params)
|
return https.post('/api/v1/level_five/overview/detailed_data_table', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下发任务 /api/v1/level_five/overview/assign_tasks
|
// 获取各中心营期阶段 /api/v1/level_five/overview/get_period_stage
|
||||||
export const assignTasks = (params) => {
|
export const getPeriodStage = (params) => {
|
||||||
return https.post('http://192.168.15.60:8890/api/v1/level_five/overview/assign_tasks', params)
|
return https.get('/api/v1/level_five/overview/get_period_stage', params)
|
||||||
}
|
}
|
||||||
// 获取优秀录音文件 /api/v1/level_four/overview/get_excellent_record_file
|
// 获取优秀录音文件 /api/v1/level_four/overview/get_excellent_record_file
|
||||||
export const getExcellentRecordFile = (params) => {
|
export const getExcellentRecordFile = (params) => {
|
||||||
return https.post('/api/v1/level_four/overview/get_excellent_record_file', params)
|
return https.post('/api/v1/common/get_excellent_record_file', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const aggregatedAlerts = computed(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.75rem;
|
gap: 0.75rem;
|
||||||
max-height: 300px;
|
max-height: 270px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
// 自定义滚动条样式
|
// 自定义滚动条样式
|
||||||
|
|||||||
287
my-vue-app/src/views/topOne/components/PeriodStage.vue
Normal file
287
my-vue-app/src/views/topOne/components/PeriodStage.vue
Normal file
@@ -0,0 +1,287 @@
|
|||||||
|
<template>
|
||||||
|
<div class="period-stage-container">
|
||||||
|
<div class="period-stage-header">
|
||||||
|
<h3>各中心营期阶段</h3>
|
||||||
|
<div class="stage-legend">
|
||||||
|
<span class="legend-item">
|
||||||
|
<span class="legend-dot active"></span>
|
||||||
|
进行中
|
||||||
|
</span>
|
||||||
|
<span class="legend-item">
|
||||||
|
<span class="legend-dot completed"></span>
|
||||||
|
已完成
|
||||||
|
</span>
|
||||||
|
<span class="legend-item">
|
||||||
|
<span class="legend-dot pending"></span>
|
||||||
|
未开始
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="period-stage-content">
|
||||||
|
<div class="center-list">
|
||||||
|
<div
|
||||||
|
v-for="(center, index) in periodStageData"
|
||||||
|
:key="index"
|
||||||
|
class="center-item"
|
||||||
|
>
|
||||||
|
<div class="center-info">
|
||||||
|
<div class="center-name">{{ center.center_name }}</div>
|
||||||
|
<div class="center-leader">负责人:{{ center.center_leader_name }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="stage-badge" :class="getStageClass(center.period_stage)">
|
||||||
|
{{ center.period_stage }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { getPeriodStage } from '@/api/top'
|
||||||
|
|
||||||
|
// 营期阶段数据
|
||||||
|
const periodStageData = ref([])
|
||||||
|
|
||||||
|
// 获取营期阶段数据
|
||||||
|
const fetchPeriodStageData = async () => {
|
||||||
|
try {
|
||||||
|
console.log('开始获取营期阶段数据...')
|
||||||
|
const res = await getPeriodStage()
|
||||||
|
console.log('API响应:', res)
|
||||||
|
if (res && res.data) {
|
||||||
|
periodStageData.value = res.data.period_stage
|
||||||
|
console.log('数据设置成功:', periodStageData.value)
|
||||||
|
} else {
|
||||||
|
console.log('API响应无数据,使用默认数据')
|
||||||
|
setDefaultData()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取营期阶段数据失败:', error)
|
||||||
|
setDefaultData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置默认数据
|
||||||
|
const setDefaultData = () => {
|
||||||
|
periodStageData.value = [
|
||||||
|
{
|
||||||
|
center_name: '一中心',
|
||||||
|
center_leader_name: '张三丰',
|
||||||
|
period_stage: '接数据'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
center_name: '二中心',
|
||||||
|
center_leader_name: '朱一航',
|
||||||
|
period_stage: '未知阶段'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
center_name: '三中心',
|
||||||
|
center_leader_name: '程琦',
|
||||||
|
period_stage: '课1'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
console.log('已设置默认数据:', periodStageData.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取阶段状态样式类
|
||||||
|
const getStageClass = (stage) => {
|
||||||
|
const stageMap = {
|
||||||
|
'接数据': 'stage-data',
|
||||||
|
'课1': 'stage-course1',
|
||||||
|
'课2': 'stage-course2',
|
||||||
|
'课3': 'stage-course3',
|
||||||
|
'课4': 'stage-course4',
|
||||||
|
'休息': 'stage-rest',
|
||||||
|
'未知阶段': 'stage-unknown'
|
||||||
|
}
|
||||||
|
return stageMap[stage] || 'stage-default'
|
||||||
|
}
|
||||||
|
|
||||||
|
// 组件挂载时获取数据
|
||||||
|
onMounted(() => {
|
||||||
|
fetchPeriodStageData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.period-stage-container {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.period-stage-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding-bottom: 16px;
|
||||||
|
border-bottom: 1px solid #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.period-stage-header h3 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-legend {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-dot {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-dot.active {
|
||||||
|
background-color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-dot.completed {
|
||||||
|
background-color: #52c41a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.legend-dot.pending {
|
||||||
|
background-color: #d9d9d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.period-stage-content {
|
||||||
|
margin-top: 16px;
|
||||||
|
max-height: 250px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: 6px;
|
||||||
|
background: #f8fafc;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-item:hover {
|
||||||
|
background: #f1f5f9;
|
||||||
|
border-color: #cbd5e1;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-info {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #1e293b;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.center-leader {
|
||||||
|
font-size: 14px;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-badge {
|
||||||
|
padding: 6px 12px;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-data {
|
||||||
|
background: #dbeafe;
|
||||||
|
color: #1e40af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-course1 {
|
||||||
|
background: #dcfce7;
|
||||||
|
color: #166534;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-course2 {
|
||||||
|
background: #fef3c7;
|
||||||
|
color: #92400e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-course3 {
|
||||||
|
background: #fed7d7;
|
||||||
|
color: #c53030;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-course4 {
|
||||||
|
background: #e9d5ff;
|
||||||
|
color: #7c3aed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-rest {
|
||||||
|
background: #f3f4f6;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-unknown {
|
||||||
|
background: #fecaca;
|
||||||
|
color: #dc2626;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-default {
|
||||||
|
background: #e5e7eb;
|
||||||
|
color: #374151;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 响应式设计 */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.period-stage-container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.period-stage-header {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-legend {
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-item {
|
||||||
|
padding-left: 32px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-timeline::before {
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-dot {
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,19 +7,14 @@
|
|||||||
<UserDropdown />
|
<UserDropdown />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 第一行:核心业绩指标、销售实时进度、下发任务 -->
|
<!-- 第一行:核心业绩指标、销售实时进度 -->
|
||||||
<div class="dashboard-row row-1">
|
<div class="dashboard-row row-1">
|
||||||
<!-- 核心业绩指标 -->
|
<!-- 核心业绩指标 -->
|
||||||
<kpi-metrics :kpi-data="totalDeals" :format-number="formatNumber" />
|
<kpi-metrics :kpi-data="totalDeals" :format-number="formatNumber" />
|
||||||
<!-- 销售实时进度 -->
|
<!-- 销售实时进度 -->
|
||||||
<sales-progress :sales-data="realTimeProgress" />
|
<sales-progress :sales-data="realTimeProgress" />
|
||||||
<!-- 下发任务 -->
|
<!-- 各中心营期阶段 -->
|
||||||
<task-list
|
<period-stage />
|
||||||
:tasks="tasks"
|
|
||||||
:format-date="formatDate"
|
|
||||||
:get-task-status-text="getTaskStatusText"
|
|
||||||
@show-task-modal="showTaskModal = true"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 第二行 -->
|
<!-- 第二行 -->
|
||||||
<div class="dashboard-row row-3">
|
<div class="dashboard-row row-3">
|
||||||
@@ -69,59 +64,7 @@
|
|||||||
@filter-change="handleFilterChange"
|
@filter-change="handleFilterChange"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- 新建任务模态框 -->
|
|
||||||
<div
|
|
||||||
v-if="showTaskModal"
|
|
||||||
class="modal-overlay"
|
|
||||||
@click="showTaskModal = false"
|
|
||||||
>
|
|
||||||
<div class="modal-content" @click.stop>
|
|
||||||
<div class="modal-header">
|
|
||||||
<h3>新建任务</h3>
|
|
||||||
<button class="close-btn" @click="showTaskModal = false">×</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<div class="form-group">
|
|
||||||
<label>任务标题</label>
|
|
||||||
<input
|
|
||||||
v-model="newTask.title"
|
|
||||||
type="text"
|
|
||||||
placeholder="请输入任务标题"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>分配给</label>
|
|
||||||
<select v-model="newTask.assignee">
|
|
||||||
<option value="">请选择员工</option>
|
|
||||||
<option
|
|
||||||
v-for="employee in assigneeOptions"
|
|
||||||
:key="employee.wechat_id"
|
|
||||||
:value="employee.wechat_id"
|
|
||||||
>
|
|
||||||
{{ employee.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>截止日期</label>
|
|
||||||
<input v-model="newTask.deadline" type="date" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label>任务描述</label>
|
|
||||||
<textarea
|
|
||||||
v-model="newTask.description"
|
|
||||||
placeholder="请输入任务描述"
|
|
||||||
></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="cancel-btn" @click="showTaskModal = false">
|
|
||||||
取消
|
|
||||||
</button>
|
|
||||||
<button class="confirm-btn" @click="createTask">创建任务</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -144,7 +87,6 @@ import axios from "axios";
|
|||||||
import UserDropdown from "@/components/UserDropdown.vue";
|
import UserDropdown from "@/components/UserDropdown.vue";
|
||||||
import KpiMetrics from "./components/KpiMetrics.vue";
|
import KpiMetrics from "./components/KpiMetrics.vue";
|
||||||
import SalesProgress from "./components/SalesProgress.vue";
|
import SalesProgress from "./components/SalesProgress.vue";
|
||||||
import TaskList from "./components/TaskList.vue";
|
|
||||||
import FunnelChart from "./components/FunnelChart.vue";
|
import FunnelChart from "./components/FunnelChart.vue";
|
||||||
import CustomerProfile from "./components/CustomerProfile.vue";
|
import CustomerProfile from "./components/CustomerProfile.vue";
|
||||||
import CustomerType from "./components/CustomerType.vue";
|
import CustomerType from "./components/CustomerType.vue";
|
||||||
@@ -157,8 +99,10 @@ import QualityCalls from "./components/QualityCalls.vue";
|
|||||||
import DataDetail from "./components/DataDetail.vue";
|
import DataDetail from "./components/DataDetail.vue";
|
||||||
import CampManagement from "./components/CampManagement.vue";
|
import CampManagement from "./components/CampManagement.vue";
|
||||||
import DetailedDataTable from "./components/DetailedDataTable.vue";
|
import DetailedDataTable from "./components/DetailedDataTable.vue";
|
||||||
|
import PeriodStage from "./components/PeriodStage.vue";
|
||||||
import { getOverallCompanyPerformance,getCompanyDepositConversionRate,getCompanyTotalCallCount,getCompanyNewCustomer,getCompanyConversionRate,getCompanyRealTimeProgress
|
import { getOverallCompanyPerformance,getCompanyDepositConversionRate,getCompanyTotalCallCount,getCompanyNewCustomer,getCompanyConversionRate,getCompanyRealTimeProgress
|
||||||
,getCompanyConversionRateVsLast,getSalesMonthlyPerformance,getCustomerTypeDistribution,getUrgentNeedToAddress,getLevelTree,getDetailedDataTable,assignTasks } from "@/api/top";
|
,getCompanyConversionRateVsLast,getSalesMonthlyPerformance,getCustomerTypeDistribution,getUrgentNeedToAddress,getLevelTree,getDetailedDataTable,getExcellentRecordFile } from "@/api/top";
|
||||||
|
import { useUserStore } from "@/stores/user.js";
|
||||||
|
|
||||||
const rankingPeriod = ref("month");
|
const rankingPeriod = ref("month");
|
||||||
const rankingData = ref([
|
const rankingData = ref([
|
||||||
@@ -173,131 +117,8 @@ const sortField = ref("dealRate");
|
|||||||
const sortOrder = ref("desc");
|
const sortOrder = ref("desc");
|
||||||
const selectedPerson = ref(null);
|
const selectedPerson = ref(null);
|
||||||
|
|
||||||
const tasks = ref([]);
|
const userStore = useUserStore();
|
||||||
|
|
||||||
const employees = ref([
|
|
||||||
{ id: 1, name: "张三" }
|
|
||||||
]);
|
|
||||||
|
|
||||||
const showTaskModal = ref(false);
|
|
||||||
const newTask = reactive({
|
|
||||||
title: "",
|
|
||||||
assignee: "",
|
|
||||||
deadline: "",
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
// 获取任务列表
|
|
||||||
const getTaskList = async () => {
|
|
||||||
try {
|
|
||||||
const res = await axios.post('http://192.168.15.60:8890/api/v1/level_five/overview/view_tasks', {}, {
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer ' + localStorage.getItem('token')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
console.log(888888,res)
|
|
||||||
if (res.data.code === 200) {
|
|
||||||
const apiTasks = res.data.data.tasks || res.data.data
|
|
||||||
// 将API数据格式转换为TaskList组件期望的格式
|
|
||||||
tasks.value = apiTasks.map(task => ({
|
|
||||||
id: task.task_id,
|
|
||||||
title: task.task_title,
|
|
||||||
assignee: task.assignee || '未分配',
|
|
||||||
deadline: task.expiration_date,
|
|
||||||
status: task.state === '待处理' ? 'pending' : task.state === '正在处理' ? 'in-progress' : 'completed',
|
|
||||||
description: task.task_content,
|
|
||||||
created_at: task.created_at
|
|
||||||
}))
|
|
||||||
console.log(777777,tasks.value)
|
|
||||||
/**
|
|
||||||
* tasks
|
|
||||||
:
|
|
||||||
[,…]
|
|
||||||
0
|
|
||||||
:
|
|
||||||
{task_id: "1755748690560728_22d55cc618784537973481228a15956a", task_title: "55", task_content: "222",…}
|
|
||||||
created_at
|
|
||||||
:
|
|
||||||
"2025-08-21 11:58:10"
|
|
||||||
expiration_date
|
|
||||||
:
|
|
||||||
"20250808"
|
|
||||||
state
|
|
||||||
:
|
|
||||||
"待处理"
|
|
||||||
task_content
|
|
||||||
:
|
|
||||||
"222"
|
|
||||||
task_id
|
|
||||||
:
|
|
||||||
"1755748690560728_22d55cc618784537973481228a15956a"
|
|
||||||
task_title
|
|
||||||
:
|
|
||||||
"55"
|
|
||||||
1
|
|
||||||
:
|
|
||||||
{task_id: "1755745331126891_650206e5b6d345699de3e3e406a2600e", task_title: "测试任务",…}
|
|
||||||
created_at
|
|
||||||
:
|
|
||||||
"2025-08-21 11:02:11"
|
|
||||||
expiration_date
|
|
||||||
:
|
|
||||||
"121221"
|
|
||||||
state
|
|
||||||
:
|
|
||||||
"待处理"
|
|
||||||
task_content
|
|
||||||
:
|
|
||||||
"测试任务"
|
|
||||||
task_id
|
|
||||||
:
|
|
||||||
"1755745331126891_650206e5b6d345699de3e3e406a2600e"
|
|
||||||
task_title
|
|
||||||
:
|
|
||||||
"测试任务"
|
|
||||||
2
|
|
||||||
:
|
|
||||||
{task_id: "1755745330094989_528dd87dc13a4a5bb33c9c272fb1a482", task_title: "测试任务",…}
|
|
||||||
created_at
|
|
||||||
:
|
|
||||||
"2025-08-21 11:02:10"
|
|
||||||
expiration_date
|
|
||||||
:
|
|
||||||
"121221"
|
|
||||||
state
|
|
||||||
:
|
|
||||||
"已完成"
|
|
||||||
task_content
|
|
||||||
:
|
|
||||||
"测试任务"
|
|
||||||
task_id
|
|
||||||
:
|
|
||||||
"1755745330094989_528dd87dc13a4a5bb33c9c272fb1a482"
|
|
||||||
task_title
|
|
||||||
:
|
|
||||||
"测试任务"
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取任务列表失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 下拉框人员
|
|
||||||
const assigneeOptions = ref([]);
|
|
||||||
async function name() {
|
|
||||||
try {
|
|
||||||
console.log('开始获取下属人员列表...');
|
|
||||||
const res = await axios.get('http://192.168.15.60:8890/api/v1/level_five/overview/get_subordinates',{
|
|
||||||
headers: {
|
|
||||||
'Authorization': 'Bearer ' + localStorage.getItem('token')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
assigneeOptions.value = res.data.data;
|
|
||||||
|
|
||||||
console.log('assigneeOptions设置后:', assigneeOptions.value);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('获取下属人员列表失败:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 计算属性
|
// 计算属性
|
||||||
const filteredTableData = computed(() => {
|
const filteredTableData = computed(() => {
|
||||||
let filtered = tableData.value;
|
let filtered = tableData.value;
|
||||||
@@ -418,14 +239,7 @@ const selectPerson = (person) => {
|
|||||||
selectedPerson.value = person;
|
selectedPerson.value = person;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTaskStatusText = (status) => {
|
|
||||||
const statusMap = {
|
|
||||||
pending: "待处理",
|
|
||||||
"in-progress": "进行中",
|
|
||||||
completed: "已完成",
|
|
||||||
};
|
|
||||||
return statusMap[status] || status;
|
|
||||||
};
|
|
||||||
|
|
||||||
const playCall = (callId) => {
|
const playCall = (callId) => {
|
||||||
console.log("播放通话录音:", callId);
|
console.log("播放通话录音:", callId);
|
||||||
@@ -435,51 +249,7 @@ const downloadCall = (callId) => {
|
|||||||
console.log("下载通话录音:", callId);
|
console.log("下载通话录音:", callId);
|
||||||
};
|
};
|
||||||
|
|
||||||
const createTask = async () => {
|
|
||||||
if (!newTask.title || !newTask.assignee || !newTask.deadline) {
|
|
||||||
alert("请填写完整信息");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 构造API请求参数
|
|
||||||
const params = {
|
|
||||||
task_title: newTask.title,
|
|
||||||
task_assignee: [newTask.assignee], // 转换为数组格式
|
|
||||||
expiration_date: newTask.deadline.replace(/-/g, ''), // 移除日期中的横线
|
|
||||||
task_content: newTask.description || newTask.title
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调用API
|
|
||||||
const response = await assignTasks(params);
|
|
||||||
console.log('任务创建成功:', response);
|
|
||||||
|
|
||||||
// 创建本地任务对象用于显示
|
|
||||||
const task = {
|
|
||||||
id: Date.now(),
|
|
||||||
title: newTask.title,
|
|
||||||
assignee: newTask.assignee,
|
|
||||||
deadline: newTask.deadline,
|
|
||||||
status: "pending",
|
|
||||||
};
|
|
||||||
|
|
||||||
tasks.value.unshift(task);
|
|
||||||
|
|
||||||
// 重置表单
|
|
||||||
Object.assign(newTask, {
|
|
||||||
title: "",
|
|
||||||
assignee: "",
|
|
||||||
deadline: "",
|
|
||||||
description: "",
|
|
||||||
});
|
|
||||||
|
|
||||||
showTaskModal.value = false;
|
|
||||||
alert('任务创建成功!');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('创建任务失败:', error);
|
|
||||||
alert('创建任务失败,请重试');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 核心数据
|
// 核心数据
|
||||||
const totalDeals = ref({});
|
const totalDeals = ref({});
|
||||||
@@ -505,6 +275,9 @@ async function getTotalDeals() {
|
|||||||
}
|
}
|
||||||
// 实时进度
|
// 实时进度
|
||||||
const realTimeProgress = ref({});
|
const realTimeProgress = ref({});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
async function getRealTimeProgress() {
|
async function getRealTimeProgress() {
|
||||||
try {
|
try {
|
||||||
const res = await getCompanyRealTimeProgress()
|
const res = await getCompanyRealTimeProgress()
|
||||||
@@ -706,7 +479,6 @@ async function getDetailData(params) {
|
|||||||
console.error("获取详细数据表格失败:", error);
|
console.error("获取详细数据表格失败:", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理筛选器变化
|
// 处理筛选器变化
|
||||||
@@ -714,19 +486,31 @@ const handleFilterChange = (filterParams) => {
|
|||||||
console.log('筛选器变化:', filterParams)
|
console.log('筛选器变化:', filterParams)
|
||||||
getDetailData(filterParams)
|
getDetailData(filterParams)
|
||||||
}
|
}
|
||||||
|
// 优秀录音
|
||||||
|
const excellentRecord = ref({});
|
||||||
|
async function CenterExcellentRecord() {
|
||||||
|
const params={
|
||||||
|
user_level:userStore.userInfo.user_level.toString(),
|
||||||
|
user_name:userStore.userInfo.username
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await getExcellentRecordFile(params)
|
||||||
|
excellentRecord.value = res.data
|
||||||
|
} catch (error) {
|
||||||
|
console.error("获取优秀录音失败:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
onMounted(async() => {
|
onMounted(async() => {
|
||||||
// 页面初始化逻辑
|
// 页面初始化逻辑
|
||||||
await getRealTimeProgress()
|
await getRealTimeProgress()
|
||||||
await getTotalDeals()
|
await getTotalDeals()
|
||||||
await getTaskList()
|
|
||||||
await getConversionComparison('month')
|
await getConversionComparison('month')
|
||||||
await getCompanySalesRank('red')
|
await getCompanySalesRank('red')
|
||||||
await getCustomerTypeRatio('child_education')
|
await getCustomerTypeRatio('child_education')
|
||||||
await getCustomerUrgency()
|
await getCustomerUrgency()
|
||||||
await CusotomGetLevelTree()
|
await CusotomGetLevelTree()
|
||||||
await getDetailData()
|
await getDetailData()
|
||||||
await name() // 获取下属人员列表
|
await CenterExcellentRecord()
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user