costReportExport.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. <template>
  2. <el-dialog title="报表导出" :visible.sync="value" top="7.8vh" customClass="customWidth" width="500px"
  3. :before-close="handleClose">
  4. <el-form ref="exportFormRef" :model="exportParam">
  5. <!-- 头部 -->
  6. <div style="text-align: center;margin-bottom: 20px">
  7. <el-radio-group size="medium" v-model="exportParam.reportType">
  8. <el-radio-button :label="0">常规报表</el-radio-button>
  9. <el-radio-button :label="1">月度报表</el-radio-button>
  10. </el-radio-group>
  11. </div>
  12. <!-- 常规报表 -->
  13. <template v-if="exportParam.reportType == 0">
  14. <el-form-item prop="projectCategoryId" :label="$t('projectclassification')"
  15. v-if="singleChoiceType == $t('projectclassification') || singleChoiceType == $t('other.project')">
  16. <el-select v-model="exportParam.projectCategoryId" :placeholder="$t('classificationitems')" clearable
  17. style="width:350px;" filterable="true" @change="filterCategory">
  18. <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id">
  19. </el-option>
  20. </el-select>
  21. </el-form-item>
  22. <el-form-item prop="projectId" :label="'选择项目'" v-if="!['人员', '项目分类', '部门', '主项目'].includes(singleChoiceType)">
  23. <select-project v-model="exportParam.projectId" :size="'medium'" :placeholder="'全部项目'" width="350px"
  24. clearable></select-project>
  25. </el-form-item>
  26. <el-form-item prop="exportContent" :label="$t('daoChuNeiRon')"
  27. v-if="permissions.countCost && permissions.countHours && (['项目', '项目分类'].includes(singleChoiceType))">
  28. <el-select v-model="exportParam.exportContent" style="width:350px;" filterable="true"
  29. popper-class="projectSelectPopperClass">
  30. <el-option :label="$t('gongShiHeChengBen')" value="hoursAndCost"></el-option>
  31. <el-option :label="$t('jingGongShi')" value="hours"></el-option>
  32. <el-option :label="$t('jingChenBen')" value="cost"></el-option>
  33. </el-select>
  34. </el-form-item>
  35. <el-form-item :label="$t('departmentchoice')" v-if="singleChoiceType == $t('other.project')">
  36. <el-cascader v-if="user.userNameNeedTranslate != 1" v-model="exportParam.deptId" :options="departmentList"
  37. :placeholder="$t('defaultText.pleaseChoose')" :props="{ checkStrictly: true, expandTrigger: 'hover' }"
  38. clearable filterable style="width:350px;"></el-cascader>
  39. <vueCascader :size="'medium'" :widthStr="'350'" :clearable="true" :subject="departmentList" :radios="true"
  40. :distinction="'1'" @vueCasader="vueCasader" v-if="user.userNameNeedTranslate == 1"></vueCascader>
  41. </el-form-item>
  42. <el-form-item prop="userIds" :label="$t('screening.selectPeople')" v-if="singleChoiceType == $t('ren-yuan')">
  43. <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
  44. :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
  45. <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  46. </el-select>
  47. <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
  48. :subject="hasReportUserList" :clearable="true" :multiSelect="true" @selectCal="selectCal"
  49. :distinction="'1'"></selectCat>
  50. </el-form-item>
  51. <el-form-item prop="userIds" :label="$t('screening.selectPeople')"
  52. v-if="['项目', '项目分类'].includes(singleChoiceType)">
  53. <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userIds"
  54. :placeholder="$t('lable.allStaff')" multiple="true" clearable style="width:350px;" filterable="true">
  55. <el-option v-for="item in users" :key="item.id" :label="item.name" :value="item.id"></el-option>
  56. </el-select>
  57. <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :widthStr="'350'" :filterable="true"
  58. :subject="users" :clearable="true" :multiSelect="true" @selectCal="selectCal" :distinction="'1'">
  59. </selectCat>
  60. </el-form-item>
  61. <el-form-item prop="projectId"
  62. :label="user.timeType.fixMonthcost == 0 ? $t('time.dateRange') : $t('Selectmonth')">
  63. <el-date-picker v-show="user.timeType.fixMonthcost == 0" v-model="exportParam.dateRange" :editable="false"
  64. format="yyyy-MM-dd" value-format="yyyy-MM-dd" :clearable="false" :range-separator="$t('other.to')"
  65. type="daterange" :start-placeholder="$t('time.startDate')"
  66. :end-placeholder="$t('time.endDate')"></el-date-picker>
  67. <el-date-picker v-show="user.timeType.fixMonthcost == 1" v-model="dateRange" :editable="false"
  68. format="yyyy-MM" value-format="yyyy-MM" @change="getEchart" :clearable="true" type="month"></el-date-picker>
  69. </el-form-item>
  70. <el-form-item :label="$t('screening.selectPeople')" v-if="false">
  71. <el-select v-if="user.userNameNeedTranslate != '1'" v-model="exportParam.userId"
  72. :placeholder="$t('lable.allStaff')" style="width: 350px" filterable="true" clearable="true">
  73. <span v-for="(item, index) in users" :key="index">
  74. <el-option :label="item.name" :value="item.id"></el-option>
  75. </span>
  76. </el-select>
  77. <selectCat v-if="user.userNameNeedTranslate == '1'" :size="'medium'" :distinction="'4'" :widthStr="'350'"
  78. :subject="users" :clearable="true" @selectCal="selectCal"></selectCat>
  79. </el-form-item>
  80. <el-form-item prop="type" :label="$t('choosethestyle')" v-if="['项目', '项目分类'].includes(singleChoiceType)">
  81. <el-select v-model="exportParam.type" :placeholder="$t('choosethestyle')" style="width:350px;">
  82. <el-option
  83. :label="singleChoiceType == $t('projectclassification') ? $t('classifiedontheline') : $t('Itemontheline')"
  84. value="0"></el-option>
  85. <el-option
  86. :label="singleChoiceType == $t('projectclassification') ? $t('classifiedcolumns') : $t('itemisonthecolumn')"
  87. value="1"></el-option>
  88. </el-select>
  89. <div class="prompt">
  90. <el-popover placement="top" width="1200" trigger="hover">
  91. <img src="../../assets/image/hanglie.png" alt="" width="100%"
  92. v-if="this.singleChoiceType != $t('projectclassification')">
  93. <img src="../../assets/image/hanglie_corp.png" alt="" width="100%" v-else>
  94. <i class="el-icon-question" slot="reference" />
  95. </el-popover>
  96. </div>
  97. </el-form-item>
  98. <el-form-item
  99. v-if="exportParam.type == 1 && permissions.countHours && (singleChoiceType == $t('other.project'))">
  100. <el-checkbox v-model="exportParam.withPercent">{{ $t('gongHhiZhanbiXmu') }}</el-checkbox>
  101. </el-form-item>
  102. <el-form-item v-if="['项目', '项目分类', '主项目'].includes(singleChoiceType) && exportParam.type == '0'">
  103. <el-checkbox v-model="exportParam.projectSum">{{ $t('individualprojectdata') }}</el-checkbox>
  104. </el-form-item>
  105. <el-form-item v-if="singleChoiceType == $t('ren-yuan') && user.timeType.mainProjectState == 1">
  106. <el-checkbox v-model="exportParam.mainProjectColumn">{{ $t('hanZhuXiangMu') }}</el-checkbox>
  107. </el-form-item>
  108. </template>
  109. <!-- 月度报表 -->
  110. <template v-if="exportParam.reportType == 1">
  111. <el-form-item prop="date" :label="this.$t('Selectmonth')">
  112. <el-date-picker size="small" v-model="exportParam.date" :editable="false" format="yyyy-MM"
  113. value-format="yyyy-MM" :clearable="false" type="month" :placeholder="$t('Selectmonth')"
  114. style="margin-right: 20px"></el-date-picker>
  115. </el-form-item>
  116. </template>
  117. </el-form>
  118. <!-- 导出按钮 -->
  119. <div slot="footer" class="dialog-footer">
  120. <el-button type="primary" @click="exportParam.reportType == 0 ? exportProjectData() : exportMonthlyProjectData()"
  121. style="width:100%;" :loading="exporting">{{ $t('export.export') }}</el-button>
  122. </div>
  123. </el-dialog>
  124. </template>
  125. <script>
  126. import selectProject from "../../components/selectProject.vue";
  127. import selectCat from "@/components/select.vue"
  128. import vueCascader from "@/components/cascader.vue"
  129. export default {
  130. components: {
  131. selectProject,
  132. selectCat,
  133. vueCascader
  134. },
  135. props: {
  136. value: { // 双向数据绑定
  137. type: [String, Number, Array],
  138. required: true
  139. },
  140. singleChoiceType: {
  141. type: String,
  142. default: '项目'
  143. },
  144. hasReportUserList: {
  145. type: Array,
  146. default: []
  147. },
  148. chartDate: {
  149. type: Array,
  150. default: []
  151. },
  152. theCustomListId: {
  153. type: [String, Number],
  154. default: ''
  155. },
  156. theCustomListPlant: {
  157. type: [String, Number],
  158. default: ''
  159. },
  160. },
  161. data() {
  162. return {
  163. user: JSON.parse(sessionStorage.getItem("user")),
  164. permissions: JSON.parse(sessionStorage.getItem("permissions")),
  165. categoryList: [],
  166. departmentList: [],
  167. dateRange: [],
  168. projectList: [],
  169. newProjectList: [],
  170. exporting: false,
  171. exportParam: {
  172. reportType: 0,
  173. projectId: null,
  174. dateRange: [],
  175. userId: null,
  176. type: '0',
  177. withPercent: false,
  178. date: null,
  179. exportContent: 'hoursAndCost'
  180. }
  181. }
  182. },
  183. methods: {
  184. exportMonthlyProjectData() {
  185. var url = '/project/exportTimeByProjectAndEmployee';
  186. var fileName = this.exportParam.date + '月度工时统计表.xlsx';
  187. this.exporting = true;
  188. this.postData(url, this.exportParam).then((res) => {
  189. const aTag = document.createElement('a');
  190. aTag.download = fileName;
  191. aTag.href = res.data;
  192. aTag.click()
  193. }).finally(() => {
  194. this.exporting = false
  195. this.updateValue()
  196. })
  197. },
  198. exportProjectData() {
  199. let param = { stateKey: 1 }
  200. if (this.exportParam.dateRange != null) {
  201. param = {
  202. startDate: this.exportParam.dateRange[0],
  203. endDate: this.exportParam.dateRange[1],
  204. stateKey: 1
  205. };
  206. }
  207. var url = "/project/exportTimeCost";
  208. var fileName = this.$t('projectmanhourcoststatistics') + '.xlsx';
  209. if (this.singleChoiceType == this.$t('zhu-xiang-mu')) {
  210. param.withMainProject = 1;
  211. }
  212. if (this.singleChoiceType == this.$t('other.project')) {
  213. if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
  214. var ids = '';
  215. this.exportParam.userIds.forEach(u => {
  216. ids += u + ',';
  217. })
  218. param.userIds = ids.substring(0, ids.length - 1);
  219. }
  220. if (this.exportParam.projectCategoryId) {
  221. param.projectCategoryId = this.exportParam.projectCategoryId
  222. }
  223. //是否含工时占比显示
  224. if (this.exportParam.withPercent) {
  225. param.withPercent = 1;
  226. }
  227. }
  228. if (this.singleChoiceType == this.$t('ren-yuan')) {
  229. // console.log(this.exportParam.userIds);
  230. fileName = this.$t('labortimecoststatistics') + '.xlsx';
  231. url = '/department/exportUserStatistic';
  232. if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
  233. var ids = '';
  234. this.exportParam.userIds.forEach(u => {
  235. ids += u + ',';
  236. })
  237. param.userIds = ids.substring(0, ids.length - 1);
  238. }
  239. param.mainProjectColumn = this.exportParam.mainProjectColumn;
  240. }
  241. if (this.singleChoiceType == this.$t('projectclassification')) {
  242. fileName = this.$t('projectclassificationlaborosttatistics') + '.xlsx';
  243. url = '/project/exportTimeCostByCategory'
  244. if (this.exportParam.projectCategoryId) {
  245. param.projectCategoryId = this.exportParam.projectCategoryId
  246. }
  247. if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
  248. var ids = '';
  249. this.exportParam.userIds.forEach(u => {
  250. ids += u + ',';
  251. })
  252. param.userIds = ids.substring(0, ids.length - 1);
  253. }
  254. }
  255. if (this.singleChoiceType == this.$t('lable.department')) {
  256. fileName = this.$t('departmenthourscoststatistics') + '.xlsx'
  257. url = '/department/exportDeptStatistic'
  258. }
  259. if (this.exportParam.projectId && this.singleChoiceType != this.$t('ren-yuan') && this.singleChoiceType != this.$t('projectclassification')) {
  260. param.projectId = this.exportParam.projectId;
  261. }
  262. if (this.exportParam.userId) {
  263. if (this.singleChoiceType == this.$t('lable.department') || this.singleChoiceType == this.$t('ren-yuan')) {
  264. param.userId = this.exportParam.userId;
  265. }
  266. }
  267. if (this.exportParam.type == 1) {
  268. this.exportParam.projectSum = null
  269. }
  270. if (this.exportParam.projectSum != null) {
  271. if (this.singleChoiceType == this.$t('other.project') || this.singleChoiceType == this.$t('lable.department') || this.singleChoiceType == this.$t('projectclassification') || this.singleChoiceType == this.$t('zhu-xiang-mu')) {
  272. param.projectSum = this.exportParam.projectSum;
  273. }
  274. }
  275. if (!this.theCustomListFlg) {
  276. param.type = this.exportParam.type * 1
  277. }
  278. console.log(this.singleChoiceType)
  279. if (this.theCustomListFlg) {
  280. url = '/project/exportTimeCostByUserCustom'
  281. fileName = this.singleChoiceType + this.$t('statistical') + '.xlsx'
  282. param.customId = this.theCustomListId
  283. param.fieldName = this.theCustomListPlant
  284. }
  285. if (this.exportParam.deptId) {
  286. if (this.exportParam.deptId.length > 0) {
  287. param.deptId = this.exportParam.deptId[this.exportParam.deptId.length - 1]
  288. }
  289. }
  290. if (this.permissions.countCost && this.permissions.countHours && (this.singleChoiceType == this.$t('other.project') || this.singleChoiceType == this.$t('projectclassification'))) {
  291. param.exportContent = this.exportParam.exportContent
  292. }
  293. if (this.singleChoiceType == this.namess) {
  294. url = '/project/exportDegreeCost'
  295. param = {
  296. startDate: this.exportParam.dateRange[0],
  297. endDate: this.exportParam.dateRange[1],
  298. projectId: this.exportParam.projectId,
  299. }
  300. fileName = this.singleChoiceType + this.$t('chenBenTongJi') + '.xlsx'
  301. }
  302. this.exporting = true;
  303. this.postData(url, param).then((res) => {
  304. this.exporting = false;
  305. const aTag = document.createElement('a');
  306. aTag.download = fileName;
  307. aTag.href = res.data;
  308. aTag.click();
  309. }).finally(() => {
  310. this.exportDialog = false;
  311. this.updateValue()
  312. })
  313. },
  314. resetForm() {
  315. if (this.$refs['exportFormRef']) {
  316. this.$refs['exportFormRef'].resetFields();
  317. }
  318. this.exportParam = {
  319. reportType: 0,
  320. projectId: null,
  321. dateRange: this.chartDate,
  322. userId: null,
  323. type: '0',
  324. withPercent: false,
  325. date: this.dayjs().format('YYYY-MM'),
  326. exportContent: 'hoursAndCost'
  327. }
  328. },
  329. getUsers() {
  330. this.postData(`/user/getSimpleActiveUserList`, {}).then((res) => {
  331. this.users = res.data;
  332. })
  333. },
  334. getMyProjectList() {
  335. this.postData(`/project/getProjectList`, {
  336. category: this.exportParam.projectCategoryId || ''
  337. }).then((res) => {
  338. this.projectList = res.data;
  339. this.newProjectList = res.data
  340. })
  341. },
  342. getCategoryList() {
  343. this.postData(`/project-category/list`, {}).then((res) => {
  344. this.categoryList = res.data
  345. })
  346. },
  347. getDepartmentList() {
  348. this.postData(this.port.manage.depList, {}).then((res) => {
  349. let dptlist = JSON.parse(JSON.stringify(res.data));
  350. this.departmentList = this.changeArr(dptlist);
  351. })
  352. },
  353. changeArr(arr) {
  354. for (var i = 0; i < arr.length; i++) {
  355. if (arr[i].id != -1 && arr[i].id != 0) {
  356. if (arr[i].children != null && arr[i].children.length > 0) {
  357. arr[i].children = this.changeArr(arr[i].children);
  358. }
  359. arr[i].id && (arr[i].value = arr[i].id);
  360. delete arr[i].id;
  361. }
  362. }
  363. for (var i in arr) {
  364. if (arr[i].id == -1 || arr[i].id == 0) {
  365. arr.splice(i, 1)
  366. }
  367. }
  368. return arr;
  369. },
  370. filterCategory() {
  371. this.exportParam.projectId = ''
  372. const id = this.exportParam.projectCategoryId
  373. if (!id) {
  374. this.projectList = JSON.parse(JSON.stringify(this.newProjectList))
  375. return
  376. }
  377. const list = JSON.parse(JSON.stringify(this.newProjectList))
  378. this.projectList = list.filter(item => item.category == id)
  379. },
  380. // 自定义事件
  381. selectCal(obj) {
  382. if (obj.distinction == 1) {
  383. let arr = []
  384. for (var i in obj.arrUserList) {
  385. arr.push(obj.arrUserList[i].id)
  386. }
  387. this.exportParam.userIds = arr
  388. } else if (obj.distinction == 2) {
  389. this.personnelValue = obj.name
  390. this.personnel()
  391. } else if (obj.distinction == 4) {
  392. this.exportParam.userId = obj.id
  393. }
  394. },
  395. vueCasader(obj) {
  396. if (obj.distinction == 1) {
  397. let arr = []
  398. arr.push(obj.id)
  399. this.exportParam.deptId = arr
  400. }
  401. },
  402. handleClose(done) {
  403. this.updateValue(false)
  404. done()
  405. },
  406. updateValue(value) { // 更新数据
  407. this.resetForm()
  408. this.$emit('input', value);
  409. this.$emit('change', value);
  410. },
  411. // 单独封装请求
  412. async postData(urls, param) {
  413. return new Promise((resolve, reject) => {
  414. this.http.post(urls, { ...param },
  415. res => {
  416. if (res.code == 'ok') {
  417. resolve(res)
  418. } else {
  419. this.$message({
  420. message: res.msg,
  421. type: 'error'
  422. })
  423. reject(res)
  424. }
  425. resolve(res)
  426. },
  427. error => {
  428. this.$message({
  429. message: error,
  430. type: "error"
  431. });
  432. reject(error)
  433. }
  434. )
  435. });
  436. },
  437. },
  438. mounted() {
  439. this.exportParam.dateRange = this.chartDate
  440. this.exportParam.date = this.dayjs().format('YYYY-MM')
  441. this.exportParam.exportContent = 'hoursAndCost'
  442. this.getUsers()
  443. this.getCategoryList()
  444. this.getDepartmentList()
  445. this.getMyProjectList()
  446. },
  447. }
  448. </script>
  449. <style lang="scss" scoped>
  450. .prompt {
  451. position: absolute;
  452. right: 10px;
  453. top: 0;
  454. }
  455. </style>