cost.vue 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. <template>
  2. <section>
  3. <el-row style="padding-bottom: 0px;text-align:center;margin-top:20px;z-index: 999;">
  4. <el-col :span="6" >
  5. <div ><span style="color:#999;">图表Y轴: </span>
  6. <el-radio-group v-model="yAxisValue" @change="onYAxisChange">
  7. <el-radio-button label="0">显示成本</el-radio-button>
  8. <el-radio-button label="1">显示工时</el-radio-button>
  9. </el-radio-group></div>
  10. </el-col>
  11. <el-col :span="14" style="display: flex;flex-wrap: wrap;">
  12. <el-date-picker v-show="user.timeType.fixMonthcost==0"
  13. v-model="dateRange" :editable="false"
  14. format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  15. @change="getEchart"
  16. :clearable="true"
  17. range-separator="至"
  18. type="daterange"
  19. start-placeholder="开始日期"
  20. end-placeholder="结束日期"
  21. ></el-date-picker>
  22. <el-date-picker v-show="user.timeType.fixMonthcost==1"
  23. v-model="dateRange" :editable="false"
  24. format="yyyy-MM" value-format="yyyy-MM"
  25. @change="getEchart"
  26. :clearable="false"
  27. type="month"
  28. ></el-date-picker>
  29. <el-radio-group v-model="radio" @change="getEchart" style="margin-left:10px;">
  30. <el-radio-button label="项目"></el-radio-button>
  31. <el-radio-button label="部门"></el-radio-button>
  32. <el-radio-button label="人员"></el-radio-button>
  33. <el-radio-button :label="namess" v-if="jichu.customDegreeActive == 1"></el-radio-button>
  34. </el-radio-group>
  35. <el-select v-model="personnelValue" filterable clearable placeholder="请选择人员" style="margin-top: 10px;width: 350px" v-if="radio == '人员'" @change="personnel()">
  36. <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.name"></el-option>
  37. </el-select>
  38. </el-col>
  39. <el-col :span="4">
  40. <el-button @click="showExportDialog">报表导出</el-button>
  41. </el-col>
  42. </el-row>
  43. <!-- <div id="clearfix" :style="'width:'+widthHtval+'px;position: relative; height:'+containerHeight+'px;'">
  44. <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
  45. </div> -->
  46. <div id="clearfix" :class="radio == '人员' ? 'ryuans' : ''" :style="'overflow-x: auto;width:100%;padding-bottom: 100px; position: relative; height:'+containerHeight+'px;'">
  47. <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
  48. </div>
  49. <!-- <div>
  50. <div id="container" :style="'height:'+containerHeight+'px;width:100%'"></div>
  51. </div> -->
  52. <div style="position:fixed;top:170px;left:600px;" v-show="radio=='部门' && parentDeptId != null">
  53. <el-button @click="backToParentDept">返回上级</el-button>
  54. </div>
  55. <!--导出报表条件选择 -->
  56. <el-dialog title="工时报表导出" v-if="exportDialog" :visible.sync="exportDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
  57. <el-form ref="form3" :model="exportParam" >
  58. <el-form-item prop="projectId" label="选择项目" v-if="radio != '人员'">
  59. <el-select v-model="exportParam.projectId" placeholder="全部项目" clearable style="width:350px;" filterable="true">
  60. <el-option v-for="item in projectList" :key="item.id" :label="item.projectName + item.projectCode" :value="item.id">
  61. <span style="float: left;color: #8492a6;">{{ item.projectCode }}</span>
  62. <span style="float: right;font-size: 13px;margin-left: 20px">{{ item.projectName }}</span>
  63. </el-option>
  64. </el-select>
  65. </el-form-item>
  66. <el-form-item prop="userIds" label="选择人员" v-if="radio == '人员'">
  67. <el-select v-model="exportParam.userIds" placeholder="全部人员" multiple="true" clearable style="width:350px;" filterable="true">
  68. <el-option v-for="item in hasReportUserList" :key="item.id" :label="item.name" :value="item.id"></el-option>
  69. </el-select>
  70. </el-form-item>
  71. <el-form-item prop="projectId" :label="user.timeType.fixMonthcost==0?'日期范围':'选择月份'">
  72. <el-date-picker v-show="user.timeType.fixMonthcost==0"
  73. v-model="exportParam.dateRange" :editable="false"
  74. format="yyyy-MM-dd" value-format="yyyy-MM-dd"
  75. :clearable="false"
  76. range-separator="至"
  77. type="daterange"
  78. start-placeholder="开始日期"
  79. end-placeholder="结束日期"
  80. ></el-date-picker>
  81. <el-date-picker v-show="user.timeType.fixMonthcost==1"
  82. v-model="dateRange" :editable="false"
  83. format="yyyy-MM" value-format="yyyy-MM"
  84. @change="getEchart"
  85. :clearable="true"
  86. type="month"
  87. ></el-date-picker>
  88. </el-form-item>
  89. <el-form-item label="选择人员" v-if="radio == '项目' || radio == '部门'">
  90. <el-select v-model="exportParam.userId" placeholder="请选择人员" style="width: 350px" filterable="true" clearable="true">
  91. <span v-for="(item, index) in users" :key="index">
  92. <el-option :label="item.name" :value="item.id"></el-option>
  93. </span>
  94. </el-select>
  95. </el-form-item>
  96. <el-form-item prop="type" label="选择样式" v-if="radio == '项目' || radio == '部门'">
  97. <el-select v-model="exportParam.type" placeholder="选择样式" style="width:350px;" >
  98. <el-option label="项目在行上" value="0"></el-option>
  99. <el-option label="项目在列上" value="1"></el-option>
  100. </el-select>
  101. <div class="prompt">
  102. <el-popover placement="top" width="1200" trigger="hover">
  103. <img src="../../assets/image/hanglie.png" alt="" width="100%">
  104. <i class="el-icon-question" slot="reference" />
  105. </el-popover>
  106. </div>
  107. </el-form-item>
  108. <el-form-item v-if="radio == '项目' || radio == '部门'">
  109. <el-checkbox v-model="exportParam.projectSum" >含单个项目数据汇总</el-checkbox>
  110. </el-form-item>
  111. </el-form>
  112. <div slot="footer" class="dialog-footer">
  113. <el-button type="primary" @click="exportProjectData" style="width:100%;" >导出</el-button>
  114. </div>
  115. </el-dialog>
  116. </section>
  117. </template>
  118. <script>
  119. import util from "../../common/js/util";
  120. export default {
  121. data() {
  122. return {
  123. personnelValue: '',
  124. personnelAll: [],
  125. yAxisValue: localStorage.yAxisValue?localStorage.yAxisValue:0,
  126. parentDeptStack:[],
  127. parentDeptId:null,
  128. hasReportUserList:[],
  129. projectList:[],
  130. exportParam:{projectId:null,dateRange:[],userId: null,type: '0'},
  131. exportDialog:false,
  132. dateRange:[],
  133. user: JSON.parse(sessionStorage.getItem("user")),
  134. radio: sessionStorage.radio!=null?sessionStorage.radio:'项目',
  135. containerHeight: 0,
  136. myChart: null,
  137. params: null,
  138. widthHtval: document.body.clientWidth - 230,
  139. users: [],
  140. jichu: [],
  141. namess: '',
  142. timers: null, // 点击的时间
  143. zhishin: 0
  144. };
  145. },
  146. methods: {
  147. //Y轴点击改变显示的数据
  148. onYAxisChange() {
  149. localStorage.yAxisValue = this.yAxisValue;
  150. this.jieliu();
  151. },
  152. jutishez() {
  153. this.http.post('/time-type/getCompanyTimeSetting', {
  154. companyId: this.user.companyId,
  155. },
  156. res => {
  157. if (res.code == "ok") {
  158. this.jichu = res.data
  159. if(res.data.customDegreeActive == 1) {
  160. this.namess = res.data.customDegreeName
  161. }
  162. } else {
  163. this.$message({
  164. message: res.msg,
  165. type: "error"
  166. });
  167. }
  168. },
  169. error => {
  170. this.$message({
  171. message: error,
  172. type: "error"
  173. });
  174. });
  175. },
  176. getUsers() {
  177. console.log(this.port.manage.list)
  178. this.http.post(this.port.manage.list, {
  179. departmentId: -1,
  180. pageIndex: 1,
  181. pageSize: 99999
  182. },
  183. res => {
  184. if (res.code == "ok") {
  185. this.users = res.data.records;
  186. } else {
  187. this.$message({
  188. message: res.msg,
  189. type: "error"
  190. });
  191. }
  192. },
  193. error => {
  194. this.$message({
  195. message: error,
  196. type: "error"
  197. });
  198. });
  199. },
  200. showExportDialog() {
  201. console.log(12345)
  202. this.exportDialog = true;
  203. this.exportParam.dateRange = this.dateRange;
  204. console.log(this.hasReportUserList)
  205. if (this.radio == '人员') {
  206. // this.exportParam.userIds = [];
  207. }
  208. },
  209. //获取我的项目列表
  210. getMyProjectList() {
  211. this.http.post('/project/getProjectList', {
  212. },
  213. res => {
  214. if (res.code == "ok") {
  215. this.projectList = res.data;
  216. } else {
  217. this.$message({
  218. message: res.msg,
  219. type: "error"
  220. });
  221. }
  222. },
  223. error => {
  224. this.$message({
  225. message: error,
  226. type: "error"
  227. });
  228. });
  229. },
  230. exportProjectData() {
  231. var param = {};
  232. if (this.exportParam.dateRange != null) {
  233. param = {startDate:this.exportParam.dateRange[0], endDate: this.exportParam.dateRange[1]};
  234. }
  235. var url = "/project/exportTimeCost";
  236. var fileName = '项目工时成本统计.xls';
  237. if (this.radio == '人员' ) {
  238. console.log(this.exportParam.userIds);
  239. fileName = '人员工时成本统计.xls';
  240. url = '/department/exportUserStatistic';
  241. if (this.exportParam.userIds != null && this.exportParam.userIds.length > 0) {
  242. var ids = '';
  243. this.exportParam.userIds.forEach(u=>{
  244. ids += u+',';
  245. })
  246. param.userIds = ids;
  247. }
  248. }
  249. if (this.exportParam.projectId) {
  250. param.projectId = this.exportParam.projectId;
  251. }
  252. if (this.exportParam.userId) {
  253. if(this.radio == '项目' || this.radio == '部门' || this.radio == '人员'){
  254. param.userId = this.exportParam.userId;
  255. }
  256. }
  257. if (this.exportParam.projectSum != null) {
  258. if(this.radio == '项目' || this.radio == '部门'){
  259. param.projectSum = this.exportParam.projectSum;
  260. }
  261. }
  262. param.type = this.exportParam.type
  263. this.http.post(url, param,
  264. res => {
  265. this.listLoading = false;
  266. if (res.code == "ok") {
  267. this.exportDialog = false;
  268. var aTag = document.createElement('a');
  269. aTag.download = fileName;
  270. aTag.href = res.data;
  271. aTag.click();
  272. } else {
  273. this.$message({
  274. message: res.msg,
  275. type: "error"
  276. });
  277. }
  278. },
  279. error => {
  280. this.listLoading = false;
  281. this.$message({
  282. message: error,
  283. type: "error"
  284. });
  285. });
  286. },
  287. // 人员筛选
  288. personnel() {
  289. if(this.personnelValue) {
  290. var arrlist = JSON.parse(JSON.stringify(this.personnelAll))
  291. var arr = []
  292. for(var i in arrlist.list) {
  293. if(arrlist.list[i].name == this.personnelValue) {
  294. arr.push(arrlist.list[i])
  295. }
  296. }
  297. arrlist.list = arr
  298. this.gtff(arrlist)
  299. } else {
  300. this.gtff(this.personnelAll)
  301. }
  302. },
  303. //获取人员成本统计列表
  304. getUserCostList() {
  305. this.listLoading = true;
  306. console.log(this.port.project.userCost, '获取人员成本统计列表')
  307. this.http.post(this.port.project.userCost, {
  308. startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange,
  309. endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange
  310. },
  311. res => {
  312. this.listLoading = false;
  313. var _this = this;
  314. this.hasReportUserList = [];
  315. if (res.code == "ok") {
  316. //
  317. // var sss = []
  318. // var ddd = []
  319. // for(var i = 0; i < 120; i++) {
  320. // sss.push(res.data.list[0])
  321. // ddd.push(res.data.userList[0])
  322. // }
  323. // res.data.list = sss
  324. // res.data.userList = ddd
  325. for(var i in res.data.list) {
  326. if(i>20) {
  327. // this.widthHtval = +this.widthHtval + 2
  328. this.widthHtval = +this.widthHtval + 40
  329. } else {
  330. this.widthHtval = document.body.clientWidth - 230
  331. }
  332. }
  333. //
  334. this.personnelAll = res.data
  335. this.gtff(res.data)
  336. //工时总成本
  337. // this.hasReportUserList = res.data.userList;
  338. // var xList = [] yList = [] , list = res.data.list, array = [] , series = [];
  339. // var totalMoneyCost = res.data.totalCostMoney;
  340. // var totalHours = 0.0;
  341. // if (list.length > 0) {
  342. // var num = list.length==0?0:list[0].project.length;
  343. // for(var i in list) {
  344. // xList.push(list[i].name);
  345. // var pro = list[i].project;
  346. // for(var j in pro) {
  347. // if(array.indexOf(pro[j].project) == -1) {
  348. // array.push(pro[j].project)
  349. // }
  350. // }
  351. // }
  352. // for(var i in array) {
  353. // yList.push(array[i]);
  354. // var dataList = [];
  355. // for(var j in list) {
  356. // var project = list[j].project , num = 0;
  357. // if(project.length != 0) {
  358. // for(var k in project) {
  359. // if(project[k].project == array[i]) {
  360. // dataList.push({
  361. // "value": this.yAxisValue==0?project[k].money:project[k].time,
  362. // "cost": project[k].time,
  363. // "money":project[k].money
  364. // })
  365. // totalHours += parseFloat(project[k].time);
  366. // } else {
  367. // num++;
  368. // }
  369. // if(k == project.length-1 && num != project.length-1) {
  370. // dataList.push({
  371. // "value": 0,
  372. // "cost": 0,
  373. // "money":0,
  374. // })
  375. // }
  376. // }
  377. // } else {
  378. // dataList.push({
  379. // "value": 0,
  380. // "cost": 0,
  381. // "money":0,
  382. // })
  383. // }
  384. // }
  385. // series.push({
  386. // name: array[i],
  387. // type: 'bar',
  388. // stack:'1',
  389. // barMaxWidth: 30,
  390. // data: dataList,
  391. // })
  392. // }
  393. // }
  394. // var myChart = echarts.init(document.getElementById("container"));
  395. // totalHours = totalHours.toFixed(1);
  396. // // 设置宽度
  397. // myChart.resize({
  398. // width: this.widthHtval
  399. // })
  400. // // 设置宽度
  401. // _this.myChart = myChart;
  402. // var option = {
  403. // //总成本
  404. // title: {
  405. // text: '工时成本总计' + totalMoneyCost.toFixed(2) + '元, 时长'+totalHours+'小时',
  406. // left:'left',
  407. // },
  408. // // 工具箱
  409. // legend: {
  410. // x: 80,
  411. // y: 10,
  412. // data: yList,
  413. // show: true,
  414. //        top:"5%",//与上方的距离 可百分比% 可像素px
  415. // },
  416. // grid : {
  417. // top : 80, //距离容器上边界40像素
  418. // // bottom: 100, //距离容器下边界30像素
  419. // bottom: 35, //距离容器下边界30像素
  420. // left: 150,
  421. // right: 150
  422. // },
  423. // toolbox: {
  424. // show: true,
  425. // feature:{
  426. // saveAsImage:{
  427. // show:true
  428. // },
  429. // restore:{
  430. // show:true
  431. // },
  432. // // dataView:{
  433. // // show:true
  434. // // },
  435. // // dataZoom:{
  436. // // show:true
  437. // // },
  438. // magicType:{
  439. // type:['line','bar']
  440. // }
  441. // }
  442. // },
  443. // tooltip:{
  444. // trigger:'axis',
  445. // formatter: function (params,ticket,callback) {
  446. // var totalTime = 0;
  447. // var totalCost = 0;
  448. // var res = "";
  449. // for(var i in params) {
  450. // if (params[i].data.value > 0) {
  451. // res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName
  452. // + "</font><br/>工作成本 : " + params[i].data.money
  453. // + "元 <br/>工作时长"+" : " + params[i].data.cost + "小时</br></div>";
  454. // totalTime += Number(params[i].data.cost);
  455. // totalCost += Number(params[i].data.money);
  456. // }
  457. // }
  458. // res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1)+'小时 '+totalCost.toFixed(2) + "元<br/>";
  459. // return res;
  460. // }
  461. // },
  462. // xAxis: {
  463. // data: xList,
  464. // axisLabel: {
  465. // interval:0,rotate:20
  466. // }
  467. // },
  468. // yAxis: [{
  469. // type : 'value',
  470. // axisLabel: {
  471. // formatter:this.yAxisValue==0?'{value} (元)':'{value} (小时)'
  472. // }
  473. // }],
  474. // series: series,
  475. // };
  476. // myChart.setOption(option,{notMerge:true});
  477. } else {
  478. this.$message({
  479. message: res.msg,
  480. type: "error"
  481. });
  482. }
  483. },
  484. error => {
  485. this.listLoading = false;
  486. this.$message({
  487. message: error,
  488. type: "error"
  489. });
  490. });
  491. },
  492. // 共同方法
  493. gtff(data) {
  494. var _this = this;
  495. this.hasReportUserList = data.userList;
  496. var xList = [] , yList = [] , list = data.list, array = [] , series = [];
  497. var totalMoneyCost = data.totalCostMoney;
  498. var totalHours = 0.0;
  499. if (list.length > 0) {
  500. var num = list.length==0?0:list[0].project.length;
  501. for(var i in list) {
  502. xList.push(list[i].name);
  503. var pro = list[i].project;
  504. for(var j in pro) {
  505. if(array.indexOf(pro[j].project) == -1) {
  506. array.push(pro[j].project)
  507. }
  508. }
  509. }
  510. for(var i in array) {
  511. yList.push(array[i]);
  512. var dataList = [];
  513. for(var j in list) {
  514. var project = list[j].project , num = 0;
  515. if(project.length != 0) {
  516. for(var k in project) {
  517. if(project[k].project == array[i]) {
  518. dataList.push({
  519. "value": this.yAxisValue==0?project[k].money:project[k].time,
  520. "cost": project[k].time,
  521. "money":project[k].money
  522. })
  523. totalHours += parseFloat(project[k].time);
  524. } else {
  525. num++;
  526. }
  527. if(k == project.length-1 && num != project.length-1) {
  528. dataList.push({
  529. "value": 0,
  530. "cost": 0,
  531. "money":0,
  532. })
  533. }
  534. }
  535. } else {
  536. dataList.push({
  537. "value": 0,
  538. "cost": 0,
  539. "money":0,
  540. })
  541. }
  542. }
  543. series.push({
  544. name: array[i],
  545. type: 'bar',
  546. stack:'1',
  547. barMaxWidth: 30,
  548. data: dataList,
  549. })
  550. }
  551. }
  552. var myChart = echarts.init(document.getElementById("container"));
  553. totalHours = totalHours.toFixed(1);
  554. // 设置宽度
  555. myChart.resize({
  556. width: this.widthHtval
  557. })
  558. // 设置宽度
  559. _this.myChart = myChart;
  560. var option = {
  561. //总成本
  562. title: {
  563. text: '工时成本总计' + totalMoneyCost.toFixed(2) + '元, 时长'+totalHours+'小时',
  564. left:'left',
  565. },
  566. // 工具箱
  567. legend: {
  568. x: 80,
  569. y: 10,
  570. data: yList,
  571. show: true,
  572.       top:"5%",//与上方的距离 可百分比% 可像素px
  573. },
  574. grid : {
  575. top : 80, //距离容器上边界40像素
  576. // bottom: 100, //距离容器下边界30像素
  577. bottom: 35, //距离容器下边界30像素
  578. left: 150,
  579. right: 150
  580. },
  581. toolbox: {
  582. show: true,
  583. feature:{
  584. saveAsImage:{
  585. show:true
  586. },
  587. restore:{
  588. show:true
  589. },
  590. // dataView:{
  591. // show:true
  592. // },
  593. // dataZoom:{
  594. // show:true
  595. // },
  596. magicType:{
  597. type:['line','bar']
  598. }
  599. }
  600. },
  601. tooltip:{
  602. trigger:'axis',
  603. formatter: function (params,ticket,callback) {
  604. var totalTime = 0;
  605. var totalCost = 0;
  606. var res = "";
  607. for(var i in params) {
  608. if (params[i].data.value > 0) {
  609. res += "<div style='margin-top:3px;font-size:12px;'><font color='#ddd'>项目名称:" + params[i].seriesName
  610. + "</font><br/>工作成本 : " + params[i].data.money
  611. + "元 <br/>工作时长"+" : " + params[i].data.cost + "小时</br></div>";
  612. totalTime += Number(params[i].data.cost);
  613. totalCost += Number(params[i].data.money);
  614. }
  615. }
  616. res = res +'<br/>'+ params[0].name+ '<br/>总计: ' + totalTime.toFixed(1)+'小时 '+totalCost.toFixed(2) + "元<br/>";
  617. return res;
  618. }
  619. },
  620. xAxis: {
  621. data: xList,
  622. axisLabel: {
  623. interval:0,rotate:20
  624. }
  625. },
  626. yAxis: [{
  627. type : 'value',
  628. axisLabel: {
  629. formatter:this.yAxisValue==0?'{value} (元)':'{value} (小时)'
  630. }
  631. }],
  632. series: series,
  633. };
  634. myChart.setOption(option,{notMerge:true});
  635. },
  636. yanjiu() {
  637. console.log('触发')
  638. },
  639. getEchart(){
  640. var that = this
  641. // that.timers = setTimeout(()=>{
  642. // clearTimeout(that.timers)
  643. // console.log(that.timers)
  644. that.jieliu()
  645. // },100);
  646. // this.jieliu()
  647. },
  648. backToParentDept() {
  649. if (this.radio == '部门') {
  650. if (this.parentDeptStack.length > 0) {
  651. this.parentDeptStack.pop();
  652. if (this.parentDeptStack.length > 0) {
  653. this.parentDeptId = this.parentDeptStack[this.parentDeptStack.length -1];
  654. } else {
  655. this.parentDeptId = null;
  656. }
  657. this.jieliu();
  658. }
  659. }
  660. },
  661. // 脱离出来的方法
  662. jieliu() {
  663. sessionStorage.radio = this.radio;
  664. var _this = this;
  665. var param = {};
  666. if (this.dateRange != null) {
  667. param = {startDate:this.user.timeType.fixMonthcost==0?this.dateRange[0]:this.dateRange,
  668. endDate: this.user.timeType.fixMonthcost==0?this.dateRange[1]:this.dateRange};
  669. console.log(param);
  670. }
  671. var url = '';
  672. if (this.radio=='项目') {
  673. url = this.port.project.listCost;
  674. } else if (this.radio=='部门') {
  675. url = this.port.project.depCost;
  676. param.parentDeptId = this.parentDeptId;
  677. } else if (this.radio=='人员') {
  678. this.getUserCostList();
  679. return;
  680. } else if (this.radio == this.namess) {
  681. url = '/project/getDegreeCost'
  682. }
  683. this.http.post(url, param,
  684. res => {
  685. if (res.code == "ok") {
  686. for(var i in res.data.costList) {
  687. if(i>20) {
  688. // this.widthHtval = +this.widthHtval + 2
  689. this.widthHtval = +this.widthHtval + 40
  690. } else {
  691. this.widthHtval = document.body.clientWidth - 230
  692. }
  693. }
  694. // 测试写的
  695. var xList = []
  696. var yList = []
  697. var list
  698. var totalMoneyCost;
  699. var totalHours = 0.0;
  700. if(this.radio == '项目' || this.radio=='部门') {
  701. list = res.data.costList
  702. totalMoneyCost = ((this.radio=='项目')?res.data.totalMoneyCost:res.data.totalCostMoney);
  703. for(var i in list) {
  704. if(this.radio=='项目') {
  705. xList.push(this.radio=='项目'?list[i].project:list[i].name);
  706. yList.push({
  707. "value": this.yAxisValue==0?list[i].costMoney.toFixed(2) || list[i].costMoney:list[i].cost.toFixed(1),
  708. "id": list[i].id || i,
  709. "cost": list[i].cost,
  710. "money":list[i].costMoney.toFixed(2)
  711. });
  712. totalHours += parseFloat(list[i].cost);
  713. } else {
  714. xList.push(list[i].departmentName);
  715. yList.push({
  716. "value": this.yAxisValue==0? list[i].costMoney.toFixed(2) || list[i].costMoney: list[i].costTime.toFixed(1),
  717. "id": list[i].departmentId,
  718. "cost": list[i].costTime,
  719. "hasSubDept": list[i].hasSubDept,
  720. "money":list[i].costMoney.toFixed(2)
  721. });
  722. totalHours += parseFloat(list[i].costTime);
  723. }
  724. }
  725. } else {
  726. list = res.data
  727. var totalMoneyCost = 0;
  728. for(var i in list) {
  729. console.log(list[i].name, list[i].costMoney, list[i].cost)
  730. xList.push(list[i].name);
  731. yList.push({
  732. "value": this.yAxisValue==0?list[i].costMoney:list[i].cost,
  733. "id": list[i].id || i,
  734. "cost": list[i].cost,
  735. "money":list[i].costMoney.toFixed(2)
  736. });
  737. totalHours += parseFloat(list[i].cost);
  738. totalMoneyCost += parseFloat(list[i].costMoney);
  739. }
  740. }
  741. totalHours = totalHours.toFixed(1);
  742. var myChart = echarts.init(document.getElementById("container"));
  743. myChart.resize({
  744. width: this.widthHtval
  745. })
  746. _this.myChart = myChart;
  747. // console.log(totalMoneyCost.toFixed(2), '看看', totalMoneyCost)
  748. // var chengbentongji = totalMoneyCost.toFixed(2) || totalMoneyCost
  749. if(totalMoneyCost) {
  750. this.zhishin = totalMoneyCost.toFixed(2)
  751. }
  752. if(this.radio == '项目' || this.radio == '人员' || this.radio=='部门') {
  753. var option = {
  754. title: {
  755. text: '工时成本总计' + this.zhishin + '元, 时长'+totalHours+'小时',
  756. left:'left',
  757. },
  758. // 工具箱
  759. toolbox: {
  760. show: true,
  761. feature:{
  762. saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
  763. }
  764. },
  765. tooltip:{
  766. trigger:'axis',
  767. formatter: function (params,ticket,callback) {
  768. var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money
  769. + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
  770. _this.params = params;
  771. return res;
  772. }
  773. },
  774. xAxis: {
  775. data: xList,
  776. axisLabel: {
  777. interval:0,rotate:20
  778. }
  779. },
  780. yAxis: [{
  781. type : 'value',
  782. axisLabel: {
  783. formatter:this.yAxisValue==0?'{value} (元)':'{value}小时'
  784. }
  785. }],
  786. series: [{
  787. name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
  788. type: 'bar',
  789. barMaxWidth: 30,
  790. data: yList,
  791. }]
  792. };
  793. } else {
  794. var option = {
  795. title: {
  796. text: '工时成本总计' + this.zhishin + '元, 时长'+totalHours+'小时',
  797. left:'left',
  798. },
  799. // 工具箱
  800. toolbox: {
  801. show: true,
  802. feature:{
  803. saveAsImage:{show:true},restore:{show:true}, magicType:{ type:['line','bar']},
  804. }
  805. },
  806. tooltip:{
  807. trigger:'axis',
  808. formatter: function (params,ticket,callback) {
  809. var res = params[0].name + "<br/>工作成本"+" : " + params[0].data.money
  810. + "元 <br/>工作时长"+" : " + params[0].data.cost + "小时";
  811. _this.params = params;
  812. return res;
  813. }
  814. },
  815. xAxis: {
  816. data: xList,
  817. axisLabel: {
  818. interval:0,rotate:20
  819. }
  820. },
  821. yAxis: [{
  822. type : 'value',
  823. axisLabel: {
  824. formatter:this.yAxisValue==0?'{value} (元)':'{value}小时'
  825. }
  826. }],
  827. series: [{
  828. name: this.yAxisValue==0?'工作成本(元)':'工作时长(小时)',
  829. type: 'bar',
  830. barMaxWidth: 30,
  831. data: yList,
  832. }]
  833. };
  834. }
  835. myChart.setOption(option,{notMerge: true});
  836. myChart.getZr().on('click', params => {
  837. const pointInPixel = [params.offsetX, params.offsetY];
  838. if (myChart.containPixel('grid', pointInPixel)) {
  839. console.log(_this.params)
  840. if(_this.radio=='项目') {
  841. if (_this.dateRange != null) {
  842. if (this.user.timeType.fixMonthcost == 0) {
  843. _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
  844. +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
  845. } else {
  846. _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name
  847. +"?startDate="+_this.dateRange+"&endDate="+_this.dateRange);
  848. }
  849. } else {
  850. _this.$router.push("/cost/" + _this.params[0].data.id + "/" + _this.params[0].name);
  851. }
  852. } else if (_this.radio=='部门') {
  853. if (_this.params[0].data.hasSubDept) {
  854. if (_this.parentDeptId != _this.params[0].data.id) {
  855. _this.parentDeptId = _this.params[0].data.id;
  856. _this.parentDeptStack.push(_this.parentDeptId);
  857. _this.jieliu();
  858. }
  859. // _this.jieliu();
  860. } else {
  861. if (_this.dateRange != null) {
  862. _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name
  863. +"?startDate="+_this.dateRange[0]+"&endDate="+_this.dateRange[1]);
  864. } else {
  865. _this.$router.push("/costDep/" + _this.params[0].data.id + "/" + _this.params[0].name);
  866. }
  867. }
  868. }
  869. }
  870. });
  871. } else {
  872. this.$message({
  873. message: res.msg,
  874. type: "error"
  875. });
  876. }
  877. },
  878. error => {
  879. this.$message({
  880. message: error,
  881. type: "error"
  882. });
  883. });
  884. },
  885. // 左右滚动
  886. scrollFunction () {
  887. this.domObj = document.getElementById('clearfix') // 通过id获取要设置的div
  888. if (this.domObj.attachEvent) { // IE
  889. this.domObj.attachEvent('onmousewheel', this.mouseScroll)
  890. } else if (this.domObj.addEventListener) {
  891. this.domObj.addEventListener('DOMMouseScroll', this.mouseScroll, false)
  892. }
  893. this.domObj.onmousewheel = this.domObj.onmousewheel = this.mouseScroll
  894. },
  895. mouseScroll(event) { // google 浏览器下
  896. let detail = event.wheelDelta || event.detail
  897. let moveForwardStep = -1
  898. let moveBackStep = 1
  899. let step = 0
  900. step = detail > 0 ? moveForwardStep * 100 : moveBackStep * 100
  901. event.preventDefault() // 阻止浏览器默认事件
  902. this.domObj.scrollLeft = this.domObj.scrollLeft + step
  903. },
  904. },
  905. created() {
  906. },
  907. mounted() {
  908. this.containerHeight = window.innerHeight - 200
  909. // this.containerHeight = window.innerHeight - 130
  910. const that = this;
  911. window.onresize = function temp() {
  912. this.containerHeight = window.innerHeight - 130
  913. // this.containerHeight = window.innerHeight - 200
  914. };
  915. if (this.user.timeType.fixMonthcost == 0) {
  916. if (this.$route.query.startDate != null) {
  917. this.dateRange = [this.$route.query.startDate, this.$route.query.endDate];
  918. } else {
  919. //默认查看本月
  920. var now = new Date();
  921. var t = util.formatDate.format(now, 'yyyy-MM-dd');
  922. var startStr = util.formatDate.format(new Date(), 'yyyy-MM') + "-01";
  923. this.dateRange = [startStr,t];
  924. }
  925. this.exportParam.dateRange = this.dateRange;
  926. } else if (this.user.timeType.fixMonthcost == 1) {
  927. if (this.$route.query.startDate != null) {
  928. this.dateRange = this.$route.query.startDate;
  929. } else {
  930. //默认查看本月
  931. var startStr = util.formatDate.format(new Date(), 'yyyy-MM');
  932. this.dateRange = startStr;
  933. }
  934. this.exportParam.dateRange = this.dateRange;
  935. }
  936. this.radio = '项目'
  937. this.getEchart();
  938. var _this = this;
  939. window.addEventListener("resize", function() {
  940. _this.myChart.resize();
  941. });
  942. // this.getDepartment();
  943. this.getMyProjectList();
  944. this.getUsers()
  945. this.jutishez()
  946. this.scrollFunction()
  947. },
  948. };
  949. </script>
  950. <style lang="scss" scoped>
  951. #container {
  952. // display: inline-block;
  953. display: block;
  954. position: absolute;
  955. // width: 100% !important;
  956. margin-top: 60px;
  957. }
  958. .ryuans {
  959. top: -50px;
  960. }
  961. .prompt {
  962. position: absolute;
  963. right: 10px;
  964. top: 0;
  965. }
  966. </style>
  967. <style lang="scss">
  968. </style>