Archer_cdm 2 years ago
parent
commit
9dddfd5aaa
  1. 43
      api/app/lib/controllers/employeeCommunicate/index.js
  2. 3
      api/app/lib/routes/employeeCommunicate/index.js
  3. 5
      api/app/lib/utils/xlsxDownload.js
  4. 18
      web/client/src/sections/humanAffairs/containers/communication/employeeCommunication.jsx

43
api/app/lib/controllers/employeeCommunicate/index.js

@ -31,6 +31,47 @@ const moment = require('moment');
} }
} }
/**
* 导出员工沟通统计数据
*/
async function exportData(ctx) {
try {
const { models } = ctx.fs.dc;
const { simpleExcelDown } = ctx.app.fs.utils;
let exportData = await models.EmployeeCommunicate.findAll({
attributes: ['id', 'personalName', 'job', 'departmentName', 'communicateDate', 'communicateContent',
'communicateResult', 'valuation', 'communicateCondition', 'nextPlan'],
order: [['id', 'ASC']]
});
const columnKeys = {
personalName: '被沟通人',
job: '岗位',
departmentName: '部门',
communicateDate: '沟通时间',
communicateContent: '沟通内容',
communicateResult: '沟通成果',
valuation: '对被沟通人近期表现的评价',
communicateCondition: '沟通情况反馈',
nextPlan: '下一步工作计划或提升方向'
}
let header = [];
Object.keys(columnKeys).map(key => {
header.push({ title: columnKeys[key], key: key });
})
const fileName = `员工沟通统计_${moment().format('YYYYMMDDHHmmss')}` + '.xlsx'
const filePath = await simpleExcelDown({ data: exportData, header, fileName: fileName, format: 'YYYY-MM-DD', formatKey: 'communicateDate' })
const fileData = fs.readFileSync(filePath);
ctx.status = 200;
ctx.set('Content-Type', 'application/x-xls');
ctx.set('Content-disposition', 'attachment; filename=' + encodeURI(fileName));
ctx.body = fileData;
} catch (error) {
ctx.fs.logger.error(`path:${ctx.path},error:${error}`)
ctx.status = 400;
ctx.body = { name: 'ExportAllError', message: `导出员工沟通统计数据失败` }
}
}
module.exports = { module.exports = {
get get,
exportData
} }

3
api/app/lib/routes/employeeCommunicate/index.js

@ -6,4 +6,7 @@ module.exports = function (app, router, opts) {
app.fs.api.logAttr['GET/employee/communicate/list'] = { content: '查询员工沟通统计数据', visible: true }; app.fs.api.logAttr['GET/employee/communicate/list'] = { content: '查询员工沟通统计数据', visible: true };
router.get('/employee/communicate/list', employeeCommunicate.get); router.get('/employee/communicate/list', employeeCommunicate.get);
app.fs.api.logAttr['GET/export/employee/communicate'] = { content: '导出员工沟通统计数据', visible: false };
router.get('/export/employee/communicate', employeeCommunicate.exportData);
}; };

5
api/app/lib/utils/xlsxDownload.js

@ -19,7 +19,7 @@ module.exports = function (app, opts) {
} }
} }
async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss') } = {}) { async function simpleExcelDown ({ data = [], header = [], fileName = moment().format('YYYY-MM-DD HH:mm:ss'), format = '', formatKey = ''} = {}) {
const fileDirPath = path.join(__dirname, `../../downloadFiles`) const fileDirPath = path.join(__dirname, `../../downloadFiles`)
makeDir(fileDirPath) makeDir(fileDirPath)
const file = new xlsx.File(); const file = new xlsx.File();
@ -59,6 +59,9 @@ module.exports = function (app, opts) {
indexCell.style = headerStyle indexCell.style = headerStyle
for (let h of header) { for (let h of header) {
const cell = row.addCell(); const cell = row.addCell();
if (format && formatKey && formatKey === h.key && data[i][h.key]) {
cell.value = moment(data[i][h.key]).format(format)
} else
cell.value = data[i][h.key] || h.defaultValue || '-'; cell.value = data[i][h.key] || h.defaultValue || '-';
cell.style = style cell.style = style
} }

18
web/client/src/sections/humanAffairs/containers/communication/employeeCommunication.jsx

@ -1,14 +1,14 @@
import React, { useEffect, useRef, useState, useMemo } from 'react'; import React, { useEffect, useRef, useState, useMemo } from 'react';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import moment from 'moment' import moment from 'moment'
import { Select, Input, Button, Tooltip, Table, Pagination, Skeleton, DatePicker } from '@douyinfe/semi-ui'; import { Select, Input, Button, Tooltip, Table, Pagination, Skeleton, DatePicker, Toast } from '@douyinfe/semi-ui';
import { IconSearch } from '@douyinfe/semi-icons'; import { IconSearch } from '@douyinfe/semi-icons';
import DetailModal from './detailModal'; import DetailModal from './detailModal';
import { SkeletonScreen } from "$components"; import { SkeletonScreen } from "$components";
import '../../style.less' import '../../style.less'
const EmployeeCommunication = (props) => { const EmployeeCommunication = (props) => {
const { dispatch, actions } = props const { dispatch, actions, user } = props
const { humanAffairs } = actions; const { humanAffairs } = actions;
const [keywordTarget, setKeywordTarget] = useState('personalName'); const [keywordTarget, setKeywordTarget] = useState('personalName');
const [keyword, setKeyword] = useState('');// const [keyword, setKeyword] = useState('');//
@ -18,6 +18,7 @@ const EmployeeCommunication = (props) => {
const [modalV, setModalV] = useState(false); const [modalV, setModalV] = useState(false);
const [dataToDetail, setDataToDetail] = useState(null); const [dataToDetail, setDataToDetail] = useState(null);
const [tableData, setTableData] = useState([]); const [tableData, setTableData] = useState([]);
const [exportUrl, setExportUrl] = useState('');
const page = useRef(query.page); const page = useRef(query.page);
function seachValueChange(value) { function seachValueChange(value) {
setKeyword(value) setKeyword(value)
@ -189,6 +190,11 @@ const EmployeeCommunication = (props) => {
setTimeRange(''); setTimeRange('');
} }
} }
const exportAllData = () => {
let url = `export/employee/communicate?token=${user.token}&timestamp=${moment().valueOf()}`
setExportUrl(url);
}
const scroll = useMemo(() => ({}), []); const scroll = useMemo(() => ({}), []);
return (<div style={{ padding: '0px 12px' }}> return (<div style={{ padding: '0px 12px' }}>
<div style={{ display: 'flex' }}> <div style={{ display: 'flex' }}>
@ -237,7 +243,10 @@ const EmployeeCommunication = (props) => {
}}>查询</Button> }}>查询</Button>
</div> </div>
<div style={{ display: 'flex', marginRight: 20 }}> <div style={{ display: 'flex', marginRight: 20 }}>
<div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, marginLeft: 18, cursor: "pointer" }}> <div style={{ padding: '6px 20px', background: '#0F7EFB', color: '#FFFFFF', fontSize: 14, marginLeft: 18, cursor: "pointer" }}
onClick={() => {
exportAllData()
}}>
导出 导出
</div> </div>
</div> </div>
@ -291,6 +300,9 @@ const EmployeeCommunication = (props) => {
close={() => closeAndFetch()} close={() => closeAndFetch()}
onCancel={() => setModalV(false)} /> : '' onCancel={() => setModalV(false)} /> : ''
} }
{
exportUrl ? <iframe src={`/_api/${exportUrl}`} style={{ display: 'none' }} /> : ''
}
</div >) </div >)
} }

Loading…
Cancel
Save