2023-08-30 20:15:31 +08:00

508 lines
14 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!--
* @Author: Kane
* @Date: 2023-03-03 14:38:07
* @LastEditors: Kane
* @FilePath: /task_schedule/src/views/DesktopArchievement.vue
* @Description: 桌面霸屏的主组件
*
* Copyright (c) ${2022} by Kane, All Rights Reserved.
-->
<template>
<div
v-if="ui.showUI"
class="view-wrapper"
tabindex="0"
@keyup.esc="logoutDesktopArchievement()"
>
<div class="center-wrapper">
<span class="slogan">对标先进&nbsp;比学赶超</span>
<div class="total-archievement-wrapper">
<span>我的车险业绩</span>
<span>{{ getTotalArchievement }}</span>
</div>
<div class="archievement-wrapper">
<div class="total-archievement-rate-wrapper">
<ArchievementCompleteRateComponent
indicator="续保完成率"
:percentage="ui.insurance_renewal_rate"
/>
<ArchievementCompleteRateComponent
indicator="车非渗透率"
:percentage="ui.attaching_rate"
/>
</div>
<div class="total-archievement-charts-wrapper">
<ArchievementChart :chart-data="ui.chartData" />
</div>
</div>
<div class="reward-wrapper">
<HonorListComponent
:month="ui.currentMonth"
:leading-reward="ui.leading_reward_gainers"
:advance-reward="ui.advance_reward_gainers"
/>
<DishonorListComponent
:month="ui.currentMonth"
:dishonor-persons="ui.dishonorPersons"
/>
</div>
</div>
<div class="right-wrapper">
<h1>本大爷</h1>
<div class="carousel-item">
<el-carousel
arrow="never"
indicator-position="none"
:interval="4000"
>
<el-carousel-item :key="1">
<RankingListComponent :ranking-list="ui.attachingRankingList" />
</el-carousel-item>
<el-carousel-item :key="2">
<RankingListComponent :ranking-list="ui.renewalRankingList" />
</el-carousel-item>
</el-carousel>
</div>
<div class="carousel-item">
<el-carousel
arrow="never"
indicator-position="none"
:interval="4000"
>
<el-carousel-item :key="1">
<RankingListComponent :ranking-list="ui.attachingRankingList" />
</el-carousel-item>
<el-carousel-item :key="2">
<RankingListComponent :ranking-list="ui.renewalRankingList" />
</el-carousel-item>
</el-carousel>
</div>
</div>
</div>
</template>
<script lang="ts">
import { computed, reactive, onBeforeMount, onUnmounted } from "vue";
import { useRouter } from "vue-router";
import { getCallerInfo } from "@/utils/api/localStorage.js";
import { ElMessage } from "element-plus";
import
{
type DepartmentArchievement,
type CallerArchievement,
queryDepartmentArchievement,
queryCallerArchievement
} from "@/utils/archievement.js";
import { RankingListItem } from "@/types/cpicxim/RankingListItem.js";
import
{
type RankingListRequest,
type RankingListResponse,
requestRankingList
} from "@/utils/ranking.js";
import { type Department } from "@/types/cpicxim/Department";
import ArchievementChart from "@/components/ArchievementChartComponent.vue";
import ArchievementCompleteRateComponent from "@/components/ArchievementCompleteRateComponent.vue";
import HonorListComponent from "@/components/HonorListComponent.vue";
import DishonorListComponent from "@/components/DishonorListComponent.vue";
import RankingListComponent from "@/components/RankingListComponent.vue";
import { logout } from "@/utils/account.js";
import { type TelSaler } from "@/types/cpicxim/TelSaler";
interface ui
{
currentMonth: string;
chartData: number[];
totalArchievement: number;
attaching_rate: string;
insurance_renewal_rate: string; // 续保率
leading_reward_gainers: string[]; // 领跑奖
advance_reward_gainers: string[]; // 飞跃奖
dishonorPersons: string[];
showUI: boolean; // 用来刷新页面的开关
attachingRankingList: RankingListItem[]; // 坐席车非渗透率榜单
renewalRankingList: RankingListItem[];
}
export default {
name: "DesktopArchievement",
components: {
ArchievementChart,
ArchievementCompleteRateComponent,
HonorListComponent,
DishonorListComponent,
RankingListComponent,
},
setup()
{
const monthIndex = new Date();
const thisMonth: number = monthIndex.getMonth() + 1; // getMonth返回值从0开始。
const thisMonthString = thisMonth > 10 ? String( thisMonth ): "0" + String( thisMonth );
const thisYear: number = monthIndex.getFullYear();
const thisYearString: string = String( thisYear );
const numInChinese = [
"一",
"二",
"三",
"四",
"五",
"六",
"七",
"八",
"九",
"十",
"十一",
"十二",
];
const router = useRouter();
const callerInfo: TelSaler = getCallerInfo();
const ui: ui = reactive({
currentMonth: numInChinese[monthIndex.getMonth() - 1],
chartData: [0,], // 业绩表
totalArchievement: 0, // 总业绩
attaching_rate: "", // 车非渗透率
insurance_renewal_rate: "", // 续保率
leading_reward_gainers: ["",], // 领跑奖
advance_reward_gainers: ["",], // 飞跃奖
dishonorPersons: ["",],
showUI: true, // 用来刷新页面的开关
attachingRankingList: [], // 坐席车非渗透率榜单
renewalRankingList: [], // 坐席续保率榜单
});
let timerHandler = 0;
const getTotalArchievement = computed(():string =>
{
const cnyFormat = new Intl.NumberFormat( "zh-cn", {
style: "currency",
currency: "CNY",
minimumFractionDigits: 0,
});
const archievement = cnyFormat.format( ui.totalArchievement );
return archievement;
});
/**
* 将请求函数获取的部门业绩数据,渲染到页面上。
* @param data DepartmentArchievementl类型的部门业绩数据对象
*/
const applyDepartmentArchievementData = ( data: DepartmentArchievement ): void =>
{
// console.log( "部门业绩数据", data );
// 检查请求是否成功
if ( data.success !== true )
{
// 失败就提示消息,然后退出
ElMessage({
message: data.message,
type: "error",
});
return;
}
// ui.chartData = data.mensual_archievement_list;
// ui.totalArchievement = data.total_archievement;
ui.attaching_rate = data.attaching_rate;
ui.insurance_renewal_rate = data.insurance_renewal_rate;
ui.leading_reward_gainers = data.leading_reward_gainers;
ui.advance_reward_gainers = data.advance_reward_gainers;
ui.dishonorPersons = data.backward_list;
// 更新UI
// 先不显示界面往队列中加入显示队列的回调让vue刷新组件。
ui.showUI = false;
setTimeout(() =>
{
ui.showUI = true;
}, 0 );
};
const applyCallerArchievementData = ( data: CallerArchievement ): void =>
{
// 检查请求是否成功
if ( data.success !== true )
{
// 失败就提示消息,然后退出
ElMessage({
message: data.message,
type: "error",
});
return;
}
ui.chartData = data.mensual_archievement_list.slice( 0, thisMonth );
ui.totalArchievement = data.total_archievement;
console.log( "业绩清单", ui.chartData );
console.log( "当月", data.mensual_archievement_list );
ui.showUI = false;
setTimeout(() =>
{
ui.showUI = true;
}, 0 );
};
const applyRankingListData = ( data: RankingListResponse ): void =>
{
ui.attachingRankingList = data.attachingRateRankingList;
ui.renewalRankingList = data.renewalRateRankingList;
// 更新UI
// 先不显示界面往队列中加入显示队列的回调让vue刷新组件。
ui.showUI = false;
console.log( "获取排行榜后的ui:", data );
setTimeout(() =>
{
ui.showUI = true;
}, 0 );
};
// 退出桌面霸屏
const logoutDesktopArchievement = () =>
{
console.log( "111" );
logout();
// router.push("/login");
};
// 检查存储的登录信息,不存在则返回登录页面
if ( callerInfo.telSalerCode === "" )
{
ElMessage({
message: "登录信息失效,请重新登录!",
type: "success",
center: true,
});
router.push( "/login" );
}
/**
* 用于定时对页面进行刷新,其中会请求最新的业绩数据。
*/
const refresh = () =>
{
const deparmentInfo: Department = {
departmentCode: callerInfo.departmentCode,
departmentName: callerInfo.departmentName,
};
const rankinglistRequest: RankingListRequest = {
departmentCode: callerInfo.departmentCode,
year: thisYearString,
month: thisMonthString,
};
queryDepartmentArchievement( deparmentInfo, applyDepartmentArchievementData );
queryCallerArchievement( callerInfo, applyCallerArchievementData );
requestRankingList( rankinglistRequest, applyRankingListData );
};
/**
* 加载前
*/
onBeforeMount(() =>
{
// 设置每10分钟刷新一次
timerHandler = setInterval( refresh, 600 * 1000 );
refresh();
});
/**
* 页面卸载前
*/
onUnmounted((): void =>
{
// 退出页面前关掉定时器
clearInterval( timerHandler );
});
return {
ui,
callerInfo,
timerHandler,
getTotalArchievement,
renderData: applyDepartmentArchievementData,
refresh,
logoutDesktopArchievement,
};
},
};
</script>
<style scoped lang="scss">
.view-wrapper {
box-sizing: border-box;
min-height: 800px;
height: calc(100vh - 10mm);
min-width: 1280px;
width: 100vw;
padding: 5mm;
display: flex;
justify-content: flex-end;
align-items: stretch;
}
.left-wrapper {
width: 10%;
}
.center-wrapper {
//中间部分
width: 50%;
min-width: 780px;
display: flex;
flex-direction: column;
align-items: stretch;
justify-content: start;
.slogan {
//标语
margin: 0px;
padding: 15px 0px;
display: block;
text-align: center;
flex-grow: 0;
font: {
family: "FZ-ZHUOHEI";
weight: 100;
size: 90px;
}
color: $color-bg-04;
text-shadow: #feebb1 0px 0px,
#feebb1 5px 0px,
#feebb1 -5px -0px,
#feebb1 -0px -5px,
#feebb1 -4px -4px,
#feebb1 4px 4px,
#feebb1 4px -4px,
#feebb1 -4px 4px;
}
.total-archievement-wrapper {
height: 80px;
span {
display: block;
width: 100%;
color: #25e6e6;
text-align: center;
font: {
size: 35px;
family: "FZ-ZHUOHEI";
}
flex-grow: 0;
}
}
.archievement-wrapper {
//业绩部分
height: 280px;
display: flex;
justify-content: center;
align-items: stretch;
>*+* {
margin-left: 15px;
}
.total-archievement-rate-wrapper {
//业绩比例
// width: 20%;
width: 140px;
min-width: 140px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.total-archievement-charts-wrapper {
//业绩图表
width: 70%;
display: flex;
justify-content: center;
align-items: center;
}
}
.reward-wrapper {
//奖励部分
// height: 280px;
padding: 15px;
display: flex;
justify-content: center;
align-items: center;
>*+* {
margin-left: 15px;
}
}
}
.right-wrapper {
min-width: 300px;
width: 25%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
// >*+* {
// margin-top: 15px;
// }
>h1 {
font: {
family: "FZ-ZHUOHEI";
weight: 100;
size: 30px;
}
color: $color-bg-04;
text-align: center;
width: 300px;
}
>div {
display: block;
height: 260px;
width: 300px;
}
}
</style>
<style lang="scss">
body {
background-image: radial-gradient(farthest-corner at 100% 0%,
$color-bg-01,
$color-bg-02,
$color-bg-03,
$color-bg-04,
$color-bg-05,
$color-bg-05 );
}
div {
// border: 1px solid red;
box-sizing: border-box;
}
</style>