analysis.component.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
  1. import { Component, ChangeDetectionStrategy, OnInit, ChangeDetectorRef, ElementRef } from '@angular/core';
  2. import { NzMessageService } from 'ng-zorro-antd';
  3. import { STColumn, XlsxService } from '@delon/abc';
  4. import { getTimeDistance } from '@delon/util';
  5. import { _HttpClient } from '@delon/theme';
  6. import { I18NService } from '@core';
  7. import { yuan } from '@shared';
  8. import { ProjectFileService } from 'app/services/projectFile/project-file.service';
  9. import { FbsWorkshopDispatchListService } from 'app/services/fbs/fbs-workshop-dispatch-list.service';
  10. import { FbsAbnormalWorkingHoursService } from 'app/services/fbs/fbs-abnormal-working-hours.service';
  11. import { FbsWorkshopDispatchList } from 'app/entity/fbs/fbs-workshop-dispatch-list';
  12. import { convertingNumbers } from '@shared/utils/shared';
  13. import { FbsAbnormalWorkingHours } from 'app/entity/fbs/fbs-abnormal-working-hours';
  14. @Component({
  15. selector: 'app-dashboard-analysis',
  16. templateUrl: './analysis.component.html',
  17. styleUrls: ['./analysis.component.less'],
  18. styles:[
  19. `
  20. table{
  21. border-collapse:collapse;border:none;
  22. }
  23. th{
  24. border:solid#000 1px;
  25. }
  26. td{
  27. border:solid#000 1px;
  28. }
  29. .bolder{
  30. font-weight:bolder;
  31. }
  32. `
  33. ]
  34. // changeDetection: ChangeDetectionStrategy.OnPush,
  35. })
  36. export class DashboardAnalysisComponent implements OnInit {
  37. data: any = {};
  38. loading = true;
  39. date_range: Date[] = [];
  40. rankingListData: any[] = Array(7)
  41. .fill({})
  42. .map((item, i) => {
  43. return {
  44. title: this.i18n.fanyi('app.analysis.test', { no: i }),
  45. total: 323234,
  46. };
  47. });
  48. titleMap = {
  49. y1: this.i18n.fanyi('app.analysis.traffic'),
  50. y2: this.i18n.fanyi('app.analysis.payments'),
  51. };
  52. searchColumn: STColumn[] = [
  53. { title: '排名', i18n: 'app.analysis.table.rank', index: 'index' },
  54. {
  55. title: '搜索关键词',
  56. i18n: 'app.analysis.table.search-keyword',
  57. index: 'keyword',
  58. click: (item: any) => this.msg.success(item.keyword),
  59. },
  60. {
  61. type: 'number',
  62. title: '用户数',
  63. i18n: 'app.analysis.table.users',
  64. index: 'count',
  65. sorter: (a, b) => a.count - b.count,
  66. },
  67. {
  68. type: 'number',
  69. title: '周涨幅',
  70. i18n: 'app.analysis.table.weekly-range',
  71. index: 'range',
  72. render: 'range',
  73. sorter: (a, b) => a.range - b.range,
  74. },
  75. ];
  76. constructor(
  77. private http: _HttpClient,
  78. public msg: NzMessageService,
  79. private i18n: I18NService,
  80. private cdr: ChangeDetectorRef,
  81. private projectFileService: ProjectFileService,
  82. private fbsWorkshopDispatchListService:FbsWorkshopDispatchListService,
  83. private fbsAbnormalWorkingHoursService:FbsAbnormalWorkingHoursService,
  84. private xlsx: XlsxService
  85. ) { }
  86. ngOnInit() {
  87. // const offlineData: any[] = [];
  88. // for (let i = 0; i < 10; i += 1) {
  89. // offlineData.push({
  90. // name: `门店${i}`,
  91. // cvr: Math.ceil(Math.random() * 9) / 10,
  92. // });
  93. // };
  94. // offlineData.forEach((item: any, idx: number) => {
  95. // item.show = idx === 0;
  96. // item.chart = Object.assign([], offlineData);
  97. // });
  98. // this.http.get('/chart').subscribe((res: any) => {
  99. // res.offlineData.forEach((item: any, idx: number) => {
  100. // item.show = idx === 0;
  101. // item.chart = Object.assign([], res.offlineChartData);
  102. // });
  103. // this.data = res;
  104. // this.loading = false;
  105. // });
  106. this.getCircleChartData();
  107. this.feeTotal = `&yen ${this.feeData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
  108. this.alertTotal = `&yen ${this.feeData.reduce((pre, now) => now.y + pre, 0).toFixed(2)}`;
  109. this.getNow();
  110. this.getSumDispatchReport();
  111. this.getAbnormalWorkingHoursReport();
  112. this.getPlanningReport();
  113. this.getAbnormalWorkingHoursTotal();
  114. }
  115. /**
  116. * @description: 获取数据
  117. * @param {type}
  118. * @author: 段亚鑫
  119. */
  120. isVisible = false;
  121. getCircleChartData() {
  122. this.projectFileService.queryStatusNum().then((response) => {
  123. this.projectFeeData = response.result.statusList;
  124. this.projectFeeTotal = response.result.sum;
  125. this.isVisible = true;
  126. this.loading = false;
  127. // this.chart.render();
  128. })
  129. }
  130. /**
  131. * @description: 渲染图表
  132. * @param {type}
  133. * @author: 段亚鑫
  134. */
  135. chart: any;
  136. render(el: ElementRef) {
  137. const data = [{
  138. item: '事例一',
  139. count: 40,
  140. percent: 0.4
  141. }, {
  142. item: '事例二',
  143. count: 21,
  144. percent: 0.21
  145. }, {
  146. item: '事例三',
  147. count: 17,
  148. percent: 0.17
  149. }, {
  150. item: '事例四',
  151. count: 13,
  152. percent: 0.13
  153. }, {
  154. item: '事例五',
  155. count: 9,
  156. percent: 0.09
  157. }];
  158. this.chart = new G2.Chart({
  159. container: el.nativeElement,
  160. forceFit: true,
  161. height: 450,
  162. animate: false
  163. });
  164. this.chart.source(data, {
  165. percent: {
  166. formatter: function formatter(val) {
  167. val = val * 100 + '%';
  168. return val;
  169. }
  170. }
  171. });
  172. this.chart.coord('theta', {
  173. radius: 0.75,
  174. innerRadius: 0.6
  175. });
  176. this.chart.tooltip({
  177. showTitle: false,
  178. itemTpl: '<li><span style="background-color:{color};" class="g2-tooltip-marker"></span>{name}: {value}</li>'
  179. });
  180. // 文本
  181. this.chart.guide().html({
  182. position: ['50%', '50%'],
  183. html: '<div style="color:#8c8c8c;font-size: 14px;text-align: center;width: 10em;">主机<br><span style="color:#8c8c8c;font-size:20px">200</span>台</div>',
  184. alignX: 'middle',
  185. alignY: 'middle'
  186. });
  187. const interval = this.chart.intervalStack().position('percent').color('item').label('percent', {
  188. formatter: function formatter(val, item) {
  189. return item.point.item + ': ' + val;
  190. }
  191. }).tooltip('item*percent', function (item, percent) {
  192. percent = percent * 100 + '%';
  193. return {
  194. name: item,
  195. value: percent
  196. };
  197. }).style({
  198. lineWidth: 1,
  199. stroke: '#fff'
  200. });
  201. // this.chart.render();
  202. interval.setSelected(data[0]);
  203. }
  204. setDate(type: any) {
  205. this.date_range = getTimeDistance(type);
  206. setTimeout(() => this.cdr.detectChanges());
  207. }
  208. salesType = 'all';
  209. salesPieData: any;
  210. salesTotal = 0;
  211. changeSaleType() {
  212. this.salesPieData =
  213. this.salesType === 'all'
  214. ? this.data.salesTypeData
  215. : this.salesType === 'online'
  216. ? this.data.salesTypeDataOnline
  217. : this.data.salesTypeDataOffline;
  218. if (this.salesPieData) {
  219. this.salesTotal = this.salesPieData.reduce((pre, now) => now.y + pre, 0);
  220. }
  221. this.cdr.detectChanges();
  222. }
  223. handlePieValueFormat(value: any) {
  224. return yuan(value);
  225. }
  226. saleTabs: any[] = [{ key: 'sales', show: true }, { key: 'visits' }];
  227. salesChange(idx: number) {
  228. if (this.saleTabs[idx].show !== true) {
  229. this.saleTabs[idx].show = true;
  230. this.cdr.detectChanges();
  231. }
  232. }
  233. offlineIdx = 0;
  234. offlineChange(idx: number) {
  235. if (this.data.offlineData[idx].show !== true) {
  236. this.data.offlineData[idx].show = true;
  237. this.cdr.detectChanges();
  238. }
  239. }
  240. projectFeeTotal: any = null;
  241. projectFeeData = [
  242. // {x:'试剂/PD01',y:5.0,},
  243. // {x:'试剂/PDA',y:2.5,},
  244. // {x:'试剂/PR02',y:1.5,},
  245. // {x:'检测/PD01',y:5.5,},
  246. // {x:'检测/PDA',y:2.2,},
  247. // {x:'检测/PR02',y:1.6,},
  248. // {x:'会议/PD01',y:0.8,},
  249. // {x:'会议/PDA',y:3.2,},
  250. // {x:'会议/PR02',y:1.5,},
  251. // {x:'培训/PD01',y:2.5,},
  252. // {x:'培训/PDA',y:7.6,},
  253. // {x:'培训/PR02',y:1.8,},
  254. // {x:'会议/PD01',y:0.8,},
  255. // {x:'会议/PDA',y:3.2,},
  256. // {x:'人工/PR02',y:4.2,},
  257. ];
  258. projectFeeFormat(val: number) {
  259. // console.error(val)
  260. return val+"/个";
  261. }
  262. feeTotal: string;
  263. feeData = [
  264. { x: '一季度', y: 10000, },
  265. { x: '二季度', y: 40000, },
  266. { x: '三季度', y: 80000, },
  267. { x: '四季度', y: 30000, },
  268. ];
  269. feeFormat(val: number) {
  270. return `&yen ${val.toFixed(2)}`;
  271. }
  272. alertTotal: string;
  273. alertData = [
  274. { x: '办公费', y: 8000, },
  275. { x: '检测费', y: 12000, },
  276. { x: '设备采购费', y: 66000, },
  277. { x: '培训费', y: 45000, },
  278. ];
  279. alertFormat(val: number) {
  280. return `&yen ${val.toFixed(2)}`;
  281. }
  282. saveLoading=false;
  283. /**
  284. * 获取报表数据
  285. */
  286. listOfDataSelect=null;
  287. getSumDispatchReport(){
  288. this.saveLoading=true;
  289. this.fbsWorkshopDispatchListService.getSumDispatchReport(this.fbsWorkshopDispatchList).then((response)=>{
  290. this.listOfData=response.result;
  291. this.defaultSwitch();
  292. this.isSwitchChange();
  293. if(this.listOfDataSelect===null){
  294. this.listOfDataSelect=JSON.parse(JSON.stringify(response.result));
  295. }
  296. //获取时间集合数据
  297. this.getDateList();
  298. //总效率
  299. this.getEfficiencyTotal()
  300. this.saveLoading=false;
  301. })
  302. }
  303. achievementRateTotal="";//总达成率
  304. productivityTotal="";//生产率
  305. getEfficiencyTotal(){
  306. this.listOfData.forEach(element => {
  307. if(element.numberOfTasksTotal){
  308. element.numberOfTasksTotal=Number(element.numberOfTasksTotal).toFixed(0)
  309. }
  310. let numberOfTasksTotal=element.numberOfTasksTotal;//计划数量
  311. let standardWorkingHoursActualTotal=element.standardWorkingHoursActualTotal;//实际标准工时
  312. let quantityCompletedTotal=element.quantityCompletedTotal;//完成数量
  313. let manHoursCompletedTotal=element.manHoursCompletedTotal;//完成工时
  314. if(element.projectName==="统计"){
  315. this.achievementRateTotal=((Number(quantityCompletedTotal)/Number(numberOfTasksTotal))*100).toFixed(1);
  316. console.log("标准工时",standardWorkingHoursActualTotal)
  317. this.productivityTotal=((Number(standardWorkingHoursActualTotal)/Number(manHoursCompletedTotal))*100).toFixed(1)
  318. }
  319. });
  320. }
  321. /**
  322. * 工时报表的总工时
  323. */
  324. abnormalWorkingHours:FbsAbnormalWorkingHours={}
  325. getAbnormalWorkingHoursTotal(){
  326. this.fbsAbnormalWorkingHoursService.getTotal(this.fbsWorkshopDispatchList.year+"-"+this.fbsWorkshopDispatchList.month).then((response)=>{
  327. this.abnormalWorkingHours=response.result;
  328. })
  329. }
  330. /**
  331. * 获取时间列集合数据
  332. */
  333. widthLength=0;
  334. dateList=[];
  335. getDateList(){
  336. if(this.listOfData&&this.listOfData.length>0){
  337. this.dateList=this.listOfData[0].fbsWorkshopDispatchListList
  338. // this.widthLength=(this.listOfData[0].fbsWorkshopDispatchListList.length*700)+890;
  339. this.widthLength=(this.listOfData[0].fbsWorkshopDispatchListList.length*600)+1020;
  340. }
  341. }
  342. /**
  343. * 异常工时统计
  344. */
  345. abnormalWorkingHoursList:any=[];
  346. AbnormalWorkingHoursTotal:any={}
  347. getAbnormalWorkingHoursReport(){
  348. this.fbsAbnormalWorkingHoursService.getAbnormalWorkingHoursReport().then((response)=>{
  349. this.abnormalWorkingHoursList=response.result.fbsAbnormalWorkingHoursList;
  350. let attendanceHours=0;//出勤总工时
  351. let overtimeHours=0;//加班总工时
  352. let train=0;//其他总工时
  353. let abnormalWorkingHours=0;//异常总工时统计
  354. let warehouse=0;//仓库总工时统计
  355. this.abnormalWorkingHoursList.forEach(element => {
  356. if(element.attendanceHours){
  357. attendanceHours=attendanceHours+Number(element.attendanceHours);
  358. }
  359. if(element.overtimeHours){
  360. overtimeHours=overtimeHours+Number(element.overtimeHours);
  361. }
  362. train=train+Number(element.train)+Number(element.meeting)+Number(element.fiveS)+Number(element.researchAndDevelopment);
  363. abnormalWorkingHours=abnormalWorkingHours+Number(element.quality)+Number(element.design)+Number(element.rework)+Number(element.materiel)+Number(element.energy)+Number(element.other)+Number(element.equipment)+Number(element.plan);
  364. warehouse=warehouse+Number(element.mixedIngredients)+Number(element.warehousing)+Number(element.pack)+Number(element.warehouseOthers)
  365. });
  366. this.AbnormalWorkingHoursTotal.attendanceHours=attendanceHours;
  367. this.AbnormalWorkingHoursTotal.overtimeHours=overtimeHours;
  368. this.AbnormalWorkingHoursTotal.train=train;
  369. this.AbnormalWorkingHoursTotal.abnormalWorkingHours=abnormalWorkingHours;
  370. this.AbnormalWorkingHoursTotal.warehouse=warehouse;
  371. })
  372. }
  373. fbsWorkshopDispatchList:FbsWorkshopDispatchList={};
  374. listOfData=[]
  375. isSwitch=false;//是否显示已完成订单
  376. isSwitchChange(){
  377. this.listOfData.forEach(element => {
  378. if(element.status===4){
  379. if(this.isSwitch===false){
  380. element.isSwitch=false;
  381. }else{
  382. element.isSwitch=true;
  383. }
  384. }
  385. });
  386. }
  387. defaultSwitch(){
  388. this.listOfData.forEach(element => {
  389. if(element.status===4){
  390. element.isSwitch=false;
  391. }else{
  392. element.isSwitch=true;
  393. }
  394. });
  395. }
  396. /**
  397. * 导出
  398. */
  399. year="0";
  400. month="0";
  401. //初始化年月 默认当前年月
  402. getNow(){
  403. let date = new Date();
  404. this.fbsWorkshopDispatchList.year=date.getFullYear()+"";
  405. if(date.getMonth()<10){
  406. this.fbsWorkshopDispatchList.month="0"+(date.getMonth()+1)
  407. }else{
  408. this.fbsWorkshopDispatchList.month=(date.getMonth()+1)+"";
  409. }
  410. }
  411. exportLoading=false;
  412. export(){
  413. // let month=this.year.substring(2,4)+this.month;
  414. // this.fbsWorkshopDispatchListService.export(month).then((response)=>{
  415. // let list=[];
  416. // list=response.result
  417. // this.exportLoading=true;
  418. let data = [];
  419. let title = [
  420. ['项目编码'], // 项目编码
  421. ['项目名称'], // 项目名称
  422. ['工作中心'], // 工作中心
  423. ['订单编号'], // 订单编号
  424. ['物料编码'], // 物料编码
  425. ['物料名称'], // 物料名称
  426. ['状态'], // 状态
  427. ['数量'], // 数量
  428. ['完成数量'], // 累计完成数量
  429. ['剩余数量'], // 剩余
  430. ['标准工时'], // 标准工时
  431. ['实际工时'], // 累计完成工时
  432. ['订单达成率'], // 订单达成率
  433. ['计划生产效率'], // 计划生产效率
  434. ['计划开完工时间']
  435. ];
  436. data.push(title);
  437. this.listOfData.forEach(element => {
  438. let row=[];
  439. if(element.projectName=="统计"){
  440. row.push("标准总工时")
  441. row.push(element.standardWorkingHoursTotal)
  442. element.product="统计";
  443. row.push("")
  444. row.push("")
  445. }else{
  446. row.push(element.costItemCode)
  447. row.push(element.projectName)
  448. row.push(element.workCenter)
  449. row.push(element.productionOrderNumberName)
  450. }
  451. row.push(element.productId)
  452. row.push(element.product)
  453. row.push(element.lackOfMaterialState)
  454. row.push(convertingNumbers(element.numberOfTasksTotal))//
  455. row.push(element.quantityCompletedTotal)//quantityCompletedTotal//latestCompletedQuantity
  456. row.push(convertingNumbers(element.surplusNumberOfTasksTotal))//numberOfTasksTotal
  457. row.push(convertingNumbers(element.standardWorkingHoursTotal))//standardWorkingHoursTotal
  458. row.push(convertingNumbers(element.manHoursCompletedTotal))
  459. if(element.projectName!="统计"){
  460. row.push(element.achievementRate+"%")
  461. if(element.productionEfficiency){
  462. row.push(element.productionEfficiency+"%")
  463. }else{
  464. row.push("0.0%")
  465. }
  466. }
  467. row.push(element.startDate+"至"+element.dueDate)
  468. data.push(row);
  469. });
  470. let efficiencyTotal=[
  471. ['总达成率'],
  472. [this.achievementRateTotal+'%'],
  473. ['总生产效率'],
  474. [this.productivityTotal+'%'],
  475. ['出勤总工时'],
  476. [this.abnormalWorkingHours.attendanceHours],
  477. ['加班总工时'],
  478. [this.abnormalWorkingHours.overtimeHours],
  479. ['其他总工时'],
  480. [this.abnormalWorkingHours.other],
  481. ['异常总工时统计'],
  482. [this.abnormalWorkingHours.quality],
  483. ['仓库总工时统计'],
  484. [this.abnormalWorkingHours.plan]
  485. ];
  486. data.push(efficiencyTotal);
  487. // 导出
  488. this.xlsx.export({
  489. sheets: [
  490. {
  491. data: data,
  492. name: '生产订单汇总导出',
  493. },
  494. ],
  495. filename: '生产订单汇总导出.xlsx',
  496. });
  497. // this.exportLoading=false;
  498. // })
  499. }
  500. planningReportList=[]
  501. planningReportLoading=false;
  502. fbsWorkshopDispatchListPlanningReport:FbsWorkshopDispatchList={}
  503. columnTable2Width=0;
  504. getPlanningReport(){
  505. this.planningReportLoading=true;
  506. this.fbsWorkshopDispatchListService.getPlanningReport().then((response)=>{
  507. this.fbsWorkshopDispatchListPlanningReport=response.result;
  508. this.planningReportList=response.result.fbsWorkshopDispatchListList;
  509. this.columnTable2Width=response.result.dayList.length*25+420
  510. this.planningReportLoading=false;
  511. })
  512. }
  513. //控制查询条件展开与收起
  514. isShow=false;
  515. getShow(){
  516. if(this.isShow){
  517. this.isShow=false;
  518. }else{
  519. this.isShow=true;
  520. }
  521. }
  522. }