导出合并

rollback^2
lion 9 months ago
parent c245b17a3a
commit d7275fd344

@ -2,7 +2,7 @@
<div id="app"> <div id="app">
<router-view /> <router-view />
<ThemePicker style="display: none;"></ThemePicker> <!-- <ThemePicker style="display: none;"></ThemePicker> -->
<OnlineFile></OnlineFile> <OnlineFile></OnlineFile>
</div> </div>
</template> </template>

@ -6,7 +6,7 @@
<el-date-picker v-model="select.month" <el-date-picker v-model="select.month"
type="month" size="small" value-format="yyyy-MM" type="month" size="small" value-format="yyyy-MM"
placeholder="月份" format="yyyy-MM"/> placeholder="月份" format="yyyy-MM"/>
<el-select style="width:250px;margin-left:6px" size="small" v-model="select.department_id" placeholder="请选择"> <el-select style="width:250px;margin-left:6px" size="small" @change="changeDepartment" v-model="select.department_id" placeholder="请选择">
<el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id"> <el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id">
</el-option> </el-option>
</el-select> </el-select>
@ -15,11 +15,16 @@
</template> </template>
</vxe-toolbar> </vxe-toolbar>
<vxe-table ref="table" stripe :border='true' style="margin-top: 10px;" :loading="loading" <vxe-table ref="table" stripe :border='true' style="margin-top: 10px;" :loading="loading"
:max-height="1400" :min-height="400" :export-config="{}" :print-config="{}" :column-config="{ resizable: true }" :max-height="1400" :min-height="400"
:export-config="{type: 'xlsx',filename:exportName,sheetName:exportName}"
:print-config="{}" :column-config="{ resizable: true }"
:expand-config="{ :expand-config="{
visibleMethod: () => false, visibleMethod: () => false,
trigger: 'manual' trigger: 'manual'
}" :data="tableData" :span-method="mergeCells"> }" :data="tableData"
:merge-cells="mergeCells"
>
<!-- :span-method="mergeCells" -->
<vxe-column width="240" header-align="center" align="center" field="department_name" title="科室"></vxe-column> <vxe-column width="240" header-align="center" align="center" field="department_name" title="科室"></vxe-column>
<vxe-column width="180" header-align="center" align="center" field="user.name" title="姓名"></vxe-column> <vxe-column width="180" header-align="center" align="center" field="user.name" title="姓名"></vxe-column>
@ -44,7 +49,7 @@
</div> </div>
</template> </template>
</vxe-column> </vxe-column>
<vxe-column header-align="center" align="center" field="expire" title="过期天数"> <vxe-column header-align="center" align="center" field="expire" title="过期时间">
<template #default="{ row }"> <template #default="{ row }">
<div> <div>
{{row.expire=='0.00'?'0':row.expire}} {{row.expire=='0.00'?'0':row.expire}}
@ -82,20 +87,29 @@
month: this.$moment().format('YYYY-MM'), month: this.$moment().format('YYYY-MM'),
department_id: '' department_id: ''
}, },
departments:[] departments:[],
mergeCells:[],
exportName:'调休统计表',
dName:'全部科室'
} }
}, },
methods: { methods: {
async getList() { async getList() {
this.loading = true; this.loading = true;
try { try {
const res = await leaveList(this.select, false); const res = await leaveList(this.select, false);
console.log(res);
let _arr = res?.timeOff || [] let _arr = res?.timeOff || []
_arr.forEach(item=>{ _arr.forEach(item=>{
item.department_name = item.user.department.name item.department_name = item.user.department.name
item.sortnumber = item.user.department.sortnumber
})
_arr.sort((a,b)=>{
return a.sortnumber - b.sortnumber
}) })
this.tableData = _arr; this.tableData = _arr;
this.mergeCells = this.generateMergeCells(this.tableData)
let date = this.$moment(this.select.month).format("YYYY年MM月")
this.exportName = `${date}${this.dName}调休统计表`
this.loading = false; this.loading = false;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
@ -105,7 +119,6 @@
async getDepartmentList() { async getDepartmentList() {
try { try {
const res = await departmentListNoAuth(); const res = await departmentListNoAuth();
console.log(res);
let arr = res let arr = res
this.departments = arr this.departments = arr
this.departments.unshift({ this.departments.unshift({
@ -116,43 +129,50 @@
console.error(err); console.error(err);
} }
}, },
mergeCells({ changeDepartment(e){
row, if(e){
$rowIndex, this.departments.map(item=>{
column, if(item.id==e){
data this.dName = item.name
}) {
console.log("row, $rowIndex, column, data", {
row,
$rowIndex,
column,
data
})
let fields = ["department_name"]
let cellValue = row[column.property]
if (cellValue && fields.includes(column.property)) {
let prevRow = data[$rowIndex - 1]
let nextRow = data[$rowIndex + 1]
if (prevRow && prevRow[column.property] === cellValue) {
return {
rowspan: 0,
colspan: 0
} }
} else { })
let countRowspan = 1 }else{
while (nextRow && nextRow[column.property] === cellValue) { this.dName = '全部科室'
nextRow = data[++countRowspan + $rowIndex] }
},
//
generateMergeCells(data) {
const columns = this.$refs.table.getColumns()
let mergeCells = [];
const columnsToMerge = ['department_name'];
columnsToMerge.forEach(key => {
const col = columns.findIndex(item => item['field'] === key);
if (col === -1) {
return;
}
for (let i = 0; i < data.length; i++) {
let rowspan = 1;
const currentValue = data[i][key];
for (let j = i + 1; j < data.length; j++) {
if (data[j][key] === currentValue) {
rowspan++;
} else {
break;
}
} }
if (countRowspan > 1) { if (rowspan > 1) {
return { mergeCells.push({
rowspan: countRowspan, row: i,
col,
rowspan,
colspan: 1 colspan: 1
} });
i += rowspan - 1;
} }
} }
} });
return mergeCells;
} },
}, },
computed: {}, computed: {},

@ -5,7 +5,8 @@
<template #buttons> <template #buttons>
<el-date-picker v-model="select.month" type="month" size="small" value-format="yyyy-MM" placeholder="月份" <el-date-picker v-model="select.month" type="month" size="small" value-format="yyyy-MM" placeholder="月份"
format="yyyy-MM" /> format="yyyy-MM" />
<el-select style="width:250px;margin-left:6px" size="small" v-model="select.department_id" placeholder="请选择"> <el-select style="width:250px;margin-left:6px" size="small" @change="changeDepartment"
v-model="select.department_id" placeholder="请选择">
<el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id"> <el-option v-for="item in departments" :key="item.id" :label="item.name" :value="item.id">
</el-option> </el-option>
</el-select> </el-select>
@ -14,12 +15,12 @@
</template> </template>
</vxe-toolbar> </vxe-toolbar>
<vxe-table ref="table" stripe :border='true' style="margin-top: 10px;" :loading="loading" :max-height="1400" <vxe-table ref="table" stripe :border='true' style="margin-top: 10px;" :loading="loading" :max-height="1400"
:min-height="400" :export-config="{type: 'xlsx'}" :print-config="{}" :column-config="{ resizable: true }" :min-height="400" :export-config="{type: 'xlsx',filename:exportName,sheetName:exportName}" :print-config="{}"
:expand-config="{ :column-config="{ resizable: true }" :expand-config="{
visibleMethod: () => false, visibleMethod: () => false,
trigger: 'manual' trigger: 'manual'
}" :data="tableData" :span-method="spanMethods"> }" :data="tableData" :merge-cells="mergeCells">
<!-- :span-method="spanMethods" :merge-cells="mergeCells"--> <!-- :span-method="spanMethods" -->
<vxe-column width="180" header-align="center" align="center" field="department_name" title="科室"></vxe-column> <vxe-column width="180" header-align="center" align="center" field="department_name" title="科室"></vxe-column>
<vxe-column width="180" header-align="center" align="center" field="name" title="姓名"></vxe-column> <vxe-column width="180" header-align="center" align="center" field="name" title="姓名"></vxe-column>
<vxe-column width="180" header-align="center" align="center" field="kaishiriqi" title="日期"> <vxe-column width="180" header-align="center" align="center" field="kaishiriqi" title="日期">
@ -68,44 +69,9 @@
department_id: '' department_id: ''
}, },
departments: [], departments: [],
mergeCells: [ mergeCells: [],
// { row: 0, col: 2, rowspan: 1, colspan: 2 }, exportName: '加班统计表',
// { row: 2, col: 2, rowspan: 2, colspan: 1 } dName: '全部科室'
],
columns: [{
field: 'department_name',
title: '科室'
},
{
field: 'name',
title: '姓名'
},
{
field: 'kaishiriqi',
title: '开始日期'
},
{
field: 'yuanyinshuoming',
title: '加班事由'
},
{
field: 'jiabanshijian',
title: '加班时间'
},
{
field: 'yuanyinshuoming',
title: '加班事由'
},
{
field: 'jiabanshichang',
title: '加班时长(h)'
},
{
field: 'allDay',
title: '本月累计(d)'
}
]
} }
}, },
methods: { methods: {
@ -115,9 +81,9 @@
const res = await overtimeList(this.select, false); const res = await overtimeList(this.select, false);
console.log(res); console.log(res);
let data = res?.users || []; let data = res?.users || [];
this.tableData = this.overtimeData(data) this.tableData = this.overtimeData(data)
console.log("this.tableData", this.tableData) let date = this.$moment(this.select.month).format("YYYY年MM月")
// this.setRowSpans() this.exportName = `${date}${this.dName}加班统计表`
this.loading = false; this.loading = false;
} catch (err) { } catch (err) {
console.error(err); console.error(err);
@ -151,15 +117,20 @@
overtime overtime
} = item; } = item;
const allDay = overtime.reduce((sum, overtimeItem) => sum + parseFloat(overtimeItem.day), 0); const allDay = overtime.reduce((sum, overtimeItem) => sum + parseFloat(overtimeItem.day), 0);
overtime.forEach(overtimeItem => { overtime.forEach(overtimeItem => {
overtimeItem.pid = id; overtimeItem.pid = id;
overtimeItem.name = name; overtimeItem.name = name;
overtimeItem.department_name = department.name overtimeItem.department_name = department.name
overtimeItem.sortnumber = department.sortnumber
overtimeItem.department_id = department.id
overtimeItem.allDay = parseFloat(allDay).toFixed(2); overtimeItem.allDay = parseFloat(allDay).toFixed(2);
result.push(overtimeItem); result.push(overtimeItem);
}); });
result.sort((a, b) => {
return a.sortnumber - b.sortnumber
})
}); });
this.mergeCells = this.generateMergeCells(result)
return result; return result;
}, },
exportjbMethod({ exportjbMethod({
@ -167,112 +138,50 @@
}) { }) {
return `${row.kaishiriqi?row.kaishiriqi.substring(11,row.kaishiriqi.length):''}-${row.kaishiriqi?row.jieshushijian.substring(11,row.jieshushijian.length):''}` return `${row.kaishiriqi?row.kaishiriqi.substring(11,row.kaishiriqi.length):''}-${row.kaishiriqi?row.jieshushijian.substring(11,row.jieshushijian.length):''}`
}, },
spanMethods({ changeDepartment(e) {
row, if (e) {
$rowIndex, this.departments.map(item => {
column, if (item.id == e) {
data this.dName = item.name
}) {
let fields = ["department_name", "name", "allDay"]
let cellValue = row[column.property]
if (cellValue && fields.includes(column.property)) {
let prevRow = data[$rowIndex - 1]
let nextRow = data[$rowIndex + 1]
if (prevRow && prevRow[column.property] === cellValue) {
return {
rowspan: 0,
colspan: 0
}
} else {
let countRowspan = 1
while (nextRow && nextRow[column.property] === cellValue) {
nextRow = data[++countRowspan + $rowIndex]
} }
if (countRowspan > 1) { })
return { } else {
rowspan: countRowspan, this.dName = '全部科室'
colspan: 1
}
}
}
} }
}, },
// //
setRowSpans() { generateMergeCells(data) {
const options = { const columns = this.$refs.table.getColumns()
list: this.tableData, // let mergeCells = [];
columns: this.columns, // const columnsToMerge = ['department_name', 'name', 'allDay'];
merges: [ "name", "department_name"], // columnsToMerge.forEach(key => {
condition: ['pid'], // const col = columns.findIndex(item => item['field'] === key);
field: 'field' // if (col === -1) {
}; return;
// pid使pid }
this.mergeCells = this.setMergeCells(options); for (let i = 0; i < data.length; i++) {
console.log('this.mergeCells: ', this.mergeCells); let rowspan = 1;
}, const currentValue = data[i][key];
setMergeCells({ for (let j = i + 1; j < data.length; j++) {
list = [], if (data[j][key] === currentValue) {
columns = [], rowspan++;
merges = [], } else {
condition = [], break;
field = 'field' }
}) { }
console.log("list",list) if (rowspan > 1) {
const validMap = new Map(); // mergeCells.push({
for (let i = 0; i < list.length; i++) { row: i,
// col,
console.log("list[i][field])",i,list[i]['pid']) rowspan,
const hashKey = condition.map(field => list[i][field]).join('&&'); colspan: 1
let flag = true; });
let count = 1; i += rowspan - 1;
// icountwhile
while (flag && i + count < list.length) {
//
const nextRow = condition.map(field => list[i + count][field]).join('&&');
if (hashKey === nextRow) {
// count
count++;
} else {
// while
flag = false;
} }
} }
// validMap });
count > 1 && validMap.set(hashKey + '_' + i, {
row: i,
rowspan: count
});
// i 1 i++
i += count - 1;
// while
flag = true;
}
//
const recordsList = [...validMap.values()];
console.log("recordsList",recordsList)
if (recordsList.length == 0) {
return [];
}
//
const cols = merges.reduce((acc, mergeField) => {
const idx = columns.findIndex(item => item[field] === mergeField);
idx !== -1 && acc.push(idx);
return acc;
}, []);
console.log("cols",cols)
//
const mergeCells = recordsList.flatMap(({
row,
rowspan
}) => cols.map(col => ({
row,
col,
rowspan,
colspan: 1
})));
return mergeCells; return mergeCells;
} },
}, },
computed: {}, computed: {},

Loading…
Cancel
Save