|
@@ -1,68 +1,219 @@
|
|
|
-<script lang="ts" setup>
|
|
|
-/**
|
|
|
- * @description 部门完成率
|
|
|
- */
|
|
|
-const tableData1 = [
|
|
|
- {
|
|
|
- id: 1,
|
|
|
- date: '89.47%',
|
|
|
- name: '职能板块',
|
|
|
- children: [
|
|
|
- {
|
|
|
- id: 31,
|
|
|
- date: '91.67%',
|
|
|
- name: '人力中心'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 32,
|
|
|
- date: '88.89%',
|
|
|
- name: '财务中心'
|
|
|
- }
|
|
|
- ]
|
|
|
- },
|
|
|
- {
|
|
|
- id: 2,
|
|
|
- date: '77.95%',
|
|
|
- name: '空间规划研究院',
|
|
|
- children: [
|
|
|
- {
|
|
|
- id: 31,
|
|
|
- date: '91.67%',
|
|
|
- name: '人力中心'
|
|
|
- },
|
|
|
- {
|
|
|
- id: 32,
|
|
|
- date: '88.89%',
|
|
|
- name: '财务中心'
|
|
|
- }
|
|
|
- ]
|
|
|
- }
|
|
|
-]
|
|
|
-</script>
|
|
|
<template>
|
|
|
<div class="oa-sys-list-view">
|
|
|
- <div class="title">部门完成率</div>
|
|
|
- <div>
|
|
|
+ <div class="title">
|
|
|
+ <div>各板块/部门周报完成率</div>
|
|
|
+ <div>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="selectDate"
|
|
|
+ type="month"
|
|
|
+ placeholder="选择月"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="table-box">
|
|
|
<el-table
|
|
|
- :data="tableData1"
|
|
|
+ class="el-table"
|
|
|
+ :data="dataSource"
|
|
|
style="width: 100%"
|
|
|
row-key="id"
|
|
|
border
|
|
|
- lazy
|
|
|
- :load="load"
|
|
|
+ stripe
|
|
|
+ :load="loading"
|
|
|
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
|
|
|
default-expand-all
|
|
|
+ header-row-class-name="table-header"
|
|
|
+ :span-method="objectSpanMethod"
|
|
|
>
|
|
|
- <el-table-column prop="name" label="部门" />
|
|
|
- <el-table-column prop="date" label="完成率" />
|
|
|
+ <el-table-column prop="deptFather" label="板块" align="center" class-name="dept-father" />
|
|
|
+ <el-table-column label="板块完成率" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-tag effect="plain" type="primary">{{ computedRate(scope.row.fatherRate) }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="deptName" label="部门" align="center" />
|
|
|
+ <el-table-column label="部门完成率" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-progress :percentage="computedRate(scope.row.fillRate, true)" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" fixed="right" align="center">
|
|
|
+ <template #default="scope">
|
|
|
+ <el-button type="primary" plain round @click="handleView(scope.row)">查看</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
</el-table>
|
|
|
</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
+<script lang="ts" setup>
|
|
|
+/**
|
|
|
+ * @description 部门完成率
|
|
|
+ */
|
|
|
+import request from '@/config/axios'
|
|
|
+import { handleTree } from '@/utils/tree'
|
|
|
+import moment from 'moment'
|
|
|
+
|
|
|
+const loading = ref(true)
|
|
|
+const dataSource = ref([])
|
|
|
+const selectDate = ref(moment().format('YYYY-MM'))
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getRateData()
|
|
|
+})
|
|
|
+
|
|
|
+watch(selectDate, () => {
|
|
|
+ getRateData()
|
|
|
+})
|
|
|
+
|
|
|
+// 获取完成率数据
|
|
|
+const getRateData = async () => {
|
|
|
+ loading.value = true
|
|
|
+ request
|
|
|
+ .get({
|
|
|
+ url: '/adm/reportStatistics/query-dept-report-statistics',
|
|
|
+ params: {
|
|
|
+ year: moment(selectDate.value).format('YYYY'),
|
|
|
+ month: moment(selectDate.value).format('M')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .then((res) => {
|
|
|
+ ElMessage.success(`${moment(selectDate.value).format('YYYY-MM')} 数据查询成功`)
|
|
|
+ const rateTree = handleTree(res, 'deptId')
|
|
|
+ dataSource.value = setRateData(rateTree)
|
|
|
+ loading.value = false
|
|
|
+ })
|
|
|
+ .catch(() => {
|
|
|
+ ElMessage.error('查询失败,请稍后重试!')
|
|
|
+ })
|
|
|
+ // console.log('rateData', rateData)
|
|
|
+}
|
|
|
+// 处理完成率数据
|
|
|
+const rowSpanList: any = ref([])
|
|
|
+const setRateData = (rateTree) => {
|
|
|
+ const dataSource = rateTree?.[0].children ?? []
|
|
|
+ const rataData: any = []
|
|
|
+ for (let index = 0; index < dataSource.length; index++) {
|
|
|
+ const data = dataSource[index]
|
|
|
+ if (data.children && data.children.length > 0) {
|
|
|
+ for (const item of data.children) {
|
|
|
+ rataData.push({
|
|
|
+ deptFather: data.deptName,
|
|
|
+ fatherRate: data.fillRate,
|
|
|
+ deptName: item.deptName,
|
|
|
+ fillRate: item.fillRate,
|
|
|
+ deptId: item.deptId
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ rataData.push({
|
|
|
+ deptFather: '职能部门',
|
|
|
+ fatherRate: rateTree[0].fillRate,
|
|
|
+ deptName: data.deptName,
|
|
|
+ fillRate: data.fillRate,
|
|
|
+ deptId: data.deptId
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ rowSpanList.value = getDeptFatherCountsAndIndices(rataData)
|
|
|
+ return rataData
|
|
|
+}
|
|
|
+// 获取相同内容的数组下标
|
|
|
+const getDeptFatherCountsAndIndices = (data) => {
|
|
|
+ const countsAndIndices: any = []
|
|
|
+ let currentDeptFather = null
|
|
|
+ let startIndex = 0
|
|
|
+ for (let i = 0; i < data.length; i++) {
|
|
|
+ const item = data[i]
|
|
|
+ if (item.deptFather === currentDeptFather) {
|
|
|
+ continue
|
|
|
+ } else {
|
|
|
+ if (currentDeptFather !== null) {
|
|
|
+ countsAndIndices.push({
|
|
|
+ deptFather: currentDeptFather,
|
|
|
+ count: i - startIndex,
|
|
|
+ startIndex
|
|
|
+ })
|
|
|
+ }
|
|
|
+ currentDeptFather = item.deptFather
|
|
|
+ startIndex = i
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (currentDeptFather !== null) {
|
|
|
+ countsAndIndices.push({
|
|
|
+ deptFather: currentDeptFather,
|
|
|
+ count: data.length - startIndex,
|
|
|
+ startIndex
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return countsAndIndices
|
|
|
+}
|
|
|
+// 设置表格单元格布局,按照相同数组下标进行分类
|
|
|
+const objectSpanMethod = ({ rowIndex, columnIndex }) => {
|
|
|
+ if (columnIndex === 0 || columnIndex === 1) {
|
|
|
+ const rowSpans = rowSpanList.value
|
|
|
+ const isSplit = rowSpans.find((item) => item.startIndex == rowIndex)
|
|
|
+ if (isSplit) {
|
|
|
+ const { count, startIndex, deptFather } = isSplit
|
|
|
+ return { rowspan: count, colspan: 1 }
|
|
|
+ } else {
|
|
|
+ return {
|
|
|
+ rowspan: 0,
|
|
|
+ colspan: 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+// 计算完成率
|
|
|
+const computedRate = (value, number?) => {
|
|
|
+ if (value === 0 || value === null) return 0
|
|
|
+ if (number) return (value * 100).toFixed(2)
|
|
|
+ return (value * 100).toFixed(2) + '%'
|
|
|
+}
|
|
|
+// 点击查看跳转详情
|
|
|
+const { push } = useRouter()
|
|
|
+const handleView = (row) => {
|
|
|
+ // console.log('点击查看跳转详情', row)
|
|
|
+ // 还需判断是跳转周报还是日报
|
|
|
+ push(`/oaSystem/DeptCenter/weeklyStatistic?deptId=${row.deptId}`)
|
|
|
+}
|
|
|
+</script>
|
|
|
<style scoped lang="scss">
|
|
|
.title {
|
|
|
+ height: 32px;
|
|
|
+ font-weight: bold;
|
|
|
+ font-size: 24px;
|
|
|
+ color: #121518;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+
|
|
|
+.table-box {
|
|
|
+ position: relative;
|
|
|
+ width: 100%;
|
|
|
+ margin-top: 20px;
|
|
|
+ flex: 1;
|
|
|
+ .el-table {
|
|
|
+ width: 100%;
|
|
|
+ height: calc(100vh - 280px);
|
|
|
+ display: block;
|
|
|
+ overflow: hidden;
|
|
|
+ // background-color: none;
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.table-header) {
|
|
|
+ th.el-table__cell {
|
|
|
+ font-weight: 400 !important;
|
|
|
+ color: #121518 !important;
|
|
|
+ background-color: #cfdae2 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+:deep(.dept-father) {
|
|
|
+ font-family:
|
|
|
+ Microsoft YaHei,
|
|
|
+ Microsoft YaHei;
|
|
|
+ font-weight: bold;
|
|
|
font-size: 16px;
|
|
|
- font-weight: 600;
|
|
|
- margin-bottom: 10px;
|
|
|
+ color: #121518;
|
|
|
}
|
|
|
</style>
|