123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- <template>
- <div class="oa-sys-list-view">
- <div class="title">
- <div>各板块/部门周日报完成率</div>
- <div>
- <el-button
- class="remind-btn"
- type="primary"
- plain
- round
- :disabled="isDisabled"
- @click="handleClick"
- >
- {{ isDisabled ? `请稍候 (${countdown}s)` : '一键催报' }}
- </el-button>
- <el-date-picker
- v-model="selectDate"
- type="month"
- placeholder="选择月"
- style="width: 200px"
- />
- </div>
- </div>
- <div class="table-box">
- <el-table
- class="el-table"
- :data="dataSource"
- style="width: 100%"
- row-key="id"
- v-loading="loading"
- :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
- stripe
- default-expand-all
- border
- header-row-class-name="table-header"
- :span-method="objectSpanMethod"
- >
- <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'
- defineOptions({ name: 'CompletionRate' })
- const loading = ref(false)
- const dataSource = ref([])
- const selectDate = ref(moment().format('YYYY-MM'))
- onMounted(() => {
- getRateData()
- })
- watch(selectDate, () => {
- getRateData()
- })
- // 获取完成率数据
- const getRateData = async () => {
- loading.value = true
- const searchDate = selectDate.value ?? moment().format('YYYY-MM')
- request
- .get({
- url: '/adm/reportStatistics/query-dept-report-statistics',
- params: {
- year: moment(searchDate).format('YYYY'),
- month: moment(searchDate).format('M')
- }
- })
- .then((res) => {
- ElMessage.success(`${moment(searchDate).format('YYYY年M月')} 数据查询成功`)
- const rateTree = handleTree(res, 'deptId')
- dataSource.value = setRateData(rateTree)
- loading.value = false
- })
- .catch(() => {
- ElMessage.error('查询失败,请稍后重试!')
- loading.value = false
- })
- // console.log('rateData', rateData)
- }
- // 处理完成率数据
- const rowSpanList: any = ref([])
- const setRateData = (rateTree) => {
- const dataSource = rateTree?.[0].children ?? []
- // 处理职能部门数据
- if (rateTree?.[1]) {
- dataSource.unshift(rateTree[1])
- }
- // 处理要渲染的数据
- 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({
- ...item,
- deptFather: data.deptName,
- fatherRate: data.fillRate,
- deptName: item.deptName,
- fillRate: item.fillRate,
- deptId: item.deptId
- })
- }
- } else if (data.deptName === '北京分公司') {
- // 因为北京分公司暂无下属部门,以防后期添加,先这样处理
- rataData.push({
- ...data,
- deptFather: data.deptName,
- fatherRate: data.fillRate,
- deptName: data.deptName,
- fillRate: data.fillRate,
- deptId: data.deptId
- })
- }
- // else {
- // // 总经理室不展示
- // rataData.push({
- // deptFather: '总经理室',
- // fatherRate: data.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?) => {
- let rate = value ? (value * 100).toFixed(2) : 0
- if (number) {
- return rate
- } else {
- return rate + ' %'
- }
- }
- // 点击查看跳转详情
- const { push } = useRouter()
- const handleView = (row) => {
- // 还需判断是跳转周报还是日报
- if (row.reportType == 'weekly') {
- push(
- `/oaSystem/DeptCenter/weeklyStatistic?deptId=${row.deptId}&date=${moment(
- selectDate.value
- ).format('YYYY-MM')}`
- )
- } else {
- push(
- `/oaSystem/DeptCenter/dailyStatistic?deptId=${row.deptId}&date=${moment(
- selectDate.value
- ).format('YYYY-MM')}`
- )
- }
- }
- /** 一键催报 ↓ */
- const isDisabled = ref(false)
- const countdown = ref(0)
- const sendRemind = () => {
- const searchDate = selectDate.value ?? moment().format('YYYY-MM')
- request
- .get({
- url: '/adm/reportStatistics/sendFillRemind',
- params: {
- year: moment(searchDate).format('YYYY'),
- month: moment(searchDate).format('M')
- }
- })
- .then(() => {
- ElMessage.success('已成功向未填报周日报员工发送催报消息!')
- })
- .catch(() => {
- ElMessage.error('催报消息发送失败,请稍后重试!')
- })
- }
- const handleClick = () => {
- if (!isDisabled.value) {
- isDisabled.value = true
- countdown.value = 15
- sendRemind()
- const timer = setInterval(() => {
- countdown.value -= 1
- if (countdown.value <= 0) {
- clearInterval(timer)
- isDisabled.value = false
- }
- }, 1000)
- }
- }
- </script>
- <style scoped lang="scss">
- .title {
- height: 32px;
- font-weight: bold;
- font-size: 24px;
- color: #121518;
- display: flex;
- justify-content: space-between;
- .remind-btn {
- margin-right: 50px;
- }
- }
- .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;
- color: #121518;
- }
- </style>
|