detection-business/pages/statistics/staffStatistics/index.vue
2025-08-25 13:46:36 +08:00

466 lines
10 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.

<template>
<view class="">
<view class="top_">
<view class="icon_" @click="goBack()">
<u-icon name="arrow-left" color="#fff" size="24"></u-icon>
</view>
<view class="top_img">
<image src="./assets/name.png" mode=""></image>
<view class="top_i_text">员工排名与项目统计</view>
</view>
</view>
<view class="cont_box">
<view class="cont_top">
<view class="ds_">
<view class="tap_text" :class="{'acv':tapIndex == index}" v-for="(item,index) in tapList"
:key="index" @click="tapIcon(index)">
<view class="">{{item.label || "无"}}</view>
<view class="tap_img" v-show="tapIndex == index">
<image src="./assets/icon_tap.png" mode=""></image>
</view>
</view>
</view>
<uni-datetime-picker v-model="queryParams.datetimeRange" type="daterange" rangeSeparator="至"
@change="getStaffCount" class="">
<view class="cont_time">
<view class="cont_size">{{queryParams.datetimeRange[0]}}</view>
<view class="bule_size">~</view>
<view class="cont_size">{{queryParams.datetimeRange[1]}}</view>
<view class=""> <u-icon name="arrow-down-fill" color="#0357FF" size="12"></u-icon></view>
</view>
</uni-datetime-picker>
</view>
<view class="user_box">
<view class="user_left">
<view class="user_name">总计</view>
</view>
<view class="user_right">
<view class="user_kar" v-for="(item,index) in allCounts" :key="index">
<view class="">{{ item.projectName }}</view>
<view class="num_">{{ item.total }}</view>
</view>
</view>
</view>
<!-- 循环 -->
<view class="user_box" v-for="(items,index) in List" :key="index">
<view class="user_left" @click="goDetail(items)">
<view class="user_img">
<view class="user_p_img" v-show="index == 0">
<image src="./assets/top1.png" mode=""></image>
</view>
<view class="user_p_img" v-show="index == 1">
<image src="./assets/top2.png" mode=""></image>
</view>
<view class="user_p_img" v-show="index == 2">
<image src="./assets/top3.png" mode=""></image>
</view>
<image src="/static/imgs/yh.png" mode=""></image>
</view>
<view class="user_name">{{ items.nickname }}</view>
<view class="user_ramk">服务{{ items.totalCount }}次</view>
</view>
<view class="user_right">
<view class="user_kar" v-for="(item,index) in items.children" :key="index">
<view class="">{{ item.projectName }}</view>
<view class="num_">{{ item.count }}</view>
</view>
</view>
</view>
</view>
<u-calendar :show="show" minDate="2023-05-05" maxDate="2026-01-01" :mode="mode" @confirm="confirm"></u-calendar>
</view>
</template>
<script>
import request from "@/utils/request";
import config from "config";
import {
getDateRange
} from "@/utils/utils";
export default {
data() {
return {
tapList: [{
label: "本日",
value: "day",
},
{
label: "本月",
value: "month",
},
],
tapIndex: 0,
show: false,
mode: 'range',
titles: "员工统计",
List: [],
allCounts: [],
selectList: [],
useSelectList: [],
status: "loading",
baseImageUrl: config.baseImageUrl,
isShowScreen: false,
columns: [],
queryParams: {
datetimeRange: []
},
queryStr: null,
selected: "day",
dateRangeList: [{
label: "本日",
value: "day",
},
{
label: "本月",
value: "month",
},
],
}
},
onLoad() {
const now = new Date();
this.setCurrentMonthRange();
this.getStaffCount();
this.getInspectionProject();
},
methods: {
confirm(e) {
console.log(e);
},
tapIcon(index) {
this.tapIndex = index
this.slectRange(index)
},
goBack() {
uni.navigateBack()
}, // 获取员工统计
getStaffCount() {
request({
url: "/partnerOwn/partner/getStaffCount",
method: "post",
data: this.queryParams,
}).then((res) => {
this.$nextTick(() => {
this.List = res.data;
this.allCounts = this.summarizeByProjectName(res.data);
});
});
}, // 补零1 → 01
pad(n) {
return n.toString().padStart(2, "0");
},
// Date → "YYYY-MM-DD"
formatDate(d) {
// 添加类型检查,确保 d 是 Date 对象
if (!(d instanceof Date)) {
console.error("formatDate() 期望接收 Date 对象,但收到:", d);
d = new Date(d); // 尝试转换为 Date 对象
if (isNaN(d.getTime())) {
// 检查是否有效日期
d = new Date(); // 如果转换失败,使用当前日期
}
}
return `${d.getFullYear()}-${this.pad(d.getMonth() + 1)}-${this.pad(
d.getDate()
)}`;
},
// 设置本月起止日期:月初到今天
setCurrentMonthRange() {
// 直接使用 Date 对象
const now = new Date();
// 创建月初的 Date 对象
const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
this.queryParams.datetimeRange = [
this.formatDate(now), // 月初
this.formatDate(now), // 今天
];
},
// 辅助函数:补零
pad(num) {
return num.toString().padStart(2, "0");
},
summarizeByProjectName(data) {
const result = {};
data.forEach(user => {
user.children.forEach(item => {
const name = item.projectName || '未知项目';
const count = item.count || 0;
result[name] = (result[name] || 0) + count;
});
});
// 转成数组并按总数降序排序
return Object.entries(result)
.map(([projectName, total]) => ({
projectName,
total
}))
.sort((a, b) => b.total - a.total);
},
// 获取工作内容列表
getInspectionProject() {
request({
url: "/inspection/dl-inspection-project/page",
method: "get",
params: {
pageNo: 1,
pageSize: 10000,
},
}).then((res) => {
this.columns = res.data.records;
});
},
slectRange(index) {
this.selected = index;
console.log(index, this.selected);
const {
value
} = this.tapList[index];
console.log(value);
// this.queryParams.datetimeRange = [
// this.formatDate(firstDay),
// this.formatDate(now)
// ];
this.queryParams.datetimeRange = getDateRange(value);
this.getStaffCount();
},
goDetail(data) {
uni.navigateTo({
// url: `/pages/index/staffProjectList/staffProjectList?userId=${data.userId}&range=${encodeURIComponent(JSON.stringify(this.queryParams.datetimeRange))}`,
url: `/pages/statistics/staffStatisticsDetail/index?userId=${data.userId}&range=${encodeURIComponent(JSON.stringify(this.queryParams.datetimeRange))}`,
});
},
// 显示下拉框
showDropdown() {
this.isShowScreen = true;
},
// 处理选择器确认事件
submitScreen(e) {
this.isShowScreen = false;
this.queryParams.id = e.value[0].id;
this.queryStr = e.value[0].projectName;
this.getStaffCount();
},
// 处理选择器取消事件
handleCancel() {
this.isShowScreen = false;
},
// 清除选择
clearSelection() {
this.queryParams.id = null;
this.queryStr = null;
this.getStaffCount();
},
}
}
</script>
<style lang='scss'>
.top_ {
width: 100%;
height: 340rpx;
position: relative;
background: #dea5ff;
background: url(./assets/banner.png);
background-repeat: no-repeat;
background-size: 100% 100%;
}
.icon_ {
position: absolute;
left: 30rpx;
top: 100rpx;
}
.top_img {
position: absolute;
top: 100rpx;
left: 52rpx;
width: 474rpx;
height: 148rpx;
z-index: 999;
image {
width: 474rpx;
height: 148rpx;
}
}
.top_i_text {
font-weight: 400;
font-size: 28rpx;
color: #0357FF;
}
.cont_box {
background: #F8F9FA;
box-shadow: 0rpx 6rpx 16rpx 0rpx rgba(12, 74, 157, 0.25);
border-radius: 20rpx 20rpx 0rpx 0rpx;
box-sizing: border-box;
padding: 15px;
}
.cont_top {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 30rpx;
}
.ds_ {
display: flex;
align-items: center
}
.tap_text {
font-weight: 400;
font-size: 28rpx;
color: #707677;
margin-right: 15px;
}
.cont_time {
width: 422rpx;
height: 60rpx;
background: #F1F4F7;
border-radius: 36rpx;
border: 2rpx solid #0357FF;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0px 30rpx;
}
.cont_size {
font-weight: 400;
font-size: 24rpx;
color: #686C7A;
}
.bule_size {
color: #0357FF;
font-size: 16px;
font-weight: bold;
margin: 0px 10rpx;
}
.tap_img {
height: 3px;
text-align: center;
margin: 0 auto;
image {
width: 34rpx;
height: 12rpx;
}
}
.acv {
font-weight: bold;
color: #292D2E !important;
}
.user_box {
width: 100%;
display: flex;
justify-content: space-between;
background: #FFFFFF;
border-radius: 8rpx;
box-sizing: border-box;
padding: 15rpx;
margin-bottom: 20rpx;
}
.user_right {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
width: 70%;
}
.user_left {
width: 30%;
}
.user_img {
width: 72rpx;
height: 72rpx;
border-radius: 50%;
border: 4rpx solid #FFDD89;
position: relative;
margin: 0px auto;
text-align: center;
image {
width: 100%;
height: 100%;
overflow: hidden;
border-radius: 50%;
}
}
.user_p_img {
width: 48rpx;
height: 48rpx;
position: absolute;
top: -38rpx;
left: 12rpx;
image {
width: 100%;
height: 100%;
}
}
.user_name {
font-weight: 600;
font-size: 28rpx;
color: #2F353B;
margin: 5px auto;
text-align: center;
}
.user_ramk {
width: 150rpx;
height: 34rpx;
background: #E3EAF8;
border-radius: 50px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 400;
font-size: 24rpx;
color: #0357FF;
margin: 0px auto;
}
.user_kar {
width: 230rpx;
height: 80rpx;
background: #F9F9FC;
border-radius: 8rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
padding: 30rpx;
font-weight: 400;
font-size: 26rpx;
color: #6D7377;
margin-bottom: 10rpx;
}
.num_ {
font-weight: 600;
font-size: 28rpx;
color: #2F353B;
}
</style>