WarehousingStaticsView.ets 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. import WorkOrderInfo from '../viewmodel/wms/WorkOrderInfo'
  2. import {DemandMaterial,MaterialBox,EmptyBox} from "../params/OrderMaterialsStorageParams"
  3. import WorkOrderMaterialInfo from "../viewmodel/wms/WorkOrderMaterialInfo"
  4. import WmsRequest from '../common/util/request/WmsRequest'
  5. import RequestParamModel from '../viewmodel/wms/RequestParamModel'
  6. import MaterialInfo from '../viewmodel/wms/MaterialInfo'
  7. import MaterialBoxInfo from '../viewmodel/wms/MaterialBoxInfo'
  8. @Component
  9. export struct StaticOrderList {
  10. private scrollerForList: Scroller = new Scroller()
  11. @Prop workOrders: WorkOrderInfo[] = []
  12. @State selectedIndex: number = -1
  13. @State scaleValue : number = 1
  14. build() {
  15. Column() { // 订单列表
  16. List({ space: 8,scroller:this.scrollerForList }) {
  17. ForEach(this.workOrders, (item: WorkOrderInfo, index) => {
  18. ListItem() {
  19. StaticOrderItem({
  20. item: item,
  21. index:index,
  22. workOrders:this.workOrders
  23. })
  24. }
  25. })
  26. }
  27. .width('100%')
  28. .flexGrow(1)
  29. }
  30. .width('100%')
  31. .height('100%')
  32. }
  33. }
  34. @Component
  35. struct StaticOrderItem{
  36. @Prop item: WorkOrderInfo
  37. @Prop index: number
  38. @Prop workOrders:WorkOrderInfo[]
  39. @State scaleValue : number = 1
  40. @State selectedOrder : WorkOrderInfo = {}
  41. private onSelect(index: number): void {
  42. this.selectedOrder = this.workOrders[index]
  43. }
  44. OrderMaterialController: CustomDialogController = new CustomDialogController({
  45. builder: OrderMaterialDialog({
  46. selectedOrder:this.selectedOrder
  47. }),
  48. autoCancel: true, // 点击遮罩关闭
  49. customStyle: true,
  50. maskColor: 'rgba(0,0,0,0.8)', // 黑色遮罩
  51. })
  52. build() {
  53. Column() {
  54. // 订单标题(带订单号)
  55. Text(`${this.item.orderName}${this.item.orderCode}`)
  56. .fontSize($r('app.float.fontSize_30'))
  57. .fontColor($r('app.color.FFFFFF'))
  58. .width('100%')
  59. .textAlign(TextAlign.Start)
  60. // 订单详情
  61. Column({ space: 3 }) {
  62. Text(`工单编号: ${this.item.workOrderCode}`)
  63. .fontColor($r('app.color.FFFFFF'))
  64. .fontSize($r('app.float.fontSize_16'))
  65. .fontWeight(FontWeight.Lighter)
  66. Text(`下发时间: ${this.item.planStartWhen}`)
  67. .fontColor($r('app.color.FFFFFF'))
  68. .fontSize($r('app.float.fontSize_16'))
  69. .fontWeight(FontWeight.Lighter)
  70. Row() {
  71. Text(`齐套比例:${(Number(this.item.inventoryNum) / Number(this.item.planNum) * 100).toFixed(0)}%`)
  72. .fontColor($r('app.color.FFFFFF'))
  73. .fontSize($r('app.float.fontSize_16'))
  74. .fontWeight(FontWeight.Lighter)
  75. }
  76. .width('100%')
  77. .justifyContent(FlexAlign.Start)
  78. }
  79. .margin({ top: 6 })
  80. .alignItems(HorizontalAlign.Start)
  81. }.backgroundColor(this.scaleValue===0.9 ? $r('app.color.2030D158') : $r('app.color.20FFFFFF'))
  82. .borderRadius($r('app.float.virtualSize_24'))
  83. .padding(13)
  84. //.border({width:2,color:$r('app.color.20FFFFFF')})
  85. .scale({ x: this.scaleValue, y: this.scaleValue })
  86. .animation({
  87. duration: 200,
  88. curve: Curve.Linear // 弹性曲线更生动
  89. })
  90. .onClick(() => {
  91. this.scaleValue = 0.9; // 点击时缩小
  92. setTimeout(() => {
  93. this.scaleValue = 1; // 0.2秒后恢复
  94. this.onSelect(this.index)
  95. this.OrderMaterialController.open()
  96. }, 200);
  97. })
  98. }
  99. }
  100. @CustomDialog
  101. struct OrderMaterialDialog {
  102. private scrollerForList: Scroller = new Scroller()
  103. @Prop workOrders:WorkOrderInfo[] = []
  104. @Prop inBoundRation:number = 10
  105. @Prop outBoundRation:number = 79
  106. @Link selectedOrder: WorkOrderInfo
  107. @State materialData: WorkOrderMaterialInfo[] = [];
  108. queryDemandMaterial=async(workOrderCode:string)=>{
  109. this.materialData = await WmsRequest.post('/api/v1/wms/workOrderMaterial/list', {
  110. workOrderCode: workOrderCode,
  111. } as RequestParamModel) as WorkOrderMaterialInfo[]
  112. }
  113. controller: CustomDialogController
  114. searchRequestMaterial: () => void = () => {}
  115. async aboutToAppear(){
  116. const workOrderCode = this.selectedOrder?.workOrderCode ?? '';
  117. this.queryDemandMaterial(workOrderCode);
  118. }
  119. build() {
  120. Column() {
  121. Column(){
  122. Text('订单物流状况详情')
  123. .fontColor($r('app.color.FFFFFF'))
  124. .fontSize($r('app.float.fontSize_38'))
  125. }.height('8%')
  126. .justifyContent(FlexAlign.Center)
  127. Column() {
  128. // 订单标题(带订单号)
  129. Text(`${this.selectedOrder.orderName}${this.selectedOrder.orderCode}`)
  130. .fontSize($r('app.float.fontSize_30'))
  131. .fontColor($r('app.color.FFFFFF'))
  132. .width('100%')
  133. .textAlign(TextAlign.Start)
  134. Row(){
  135. Column({ space: 3 }) {
  136. Text(`工单编号: ${this.selectedOrder.workOrderCode}`)
  137. .fontColor($r('app.color.FFFFFF'))
  138. .fontSize($r('app.float.fontSize_16'))
  139. Text(`下发时间: ${this.selectedOrder.planStartWhen}`)
  140. .fontColor($r('app.color.FFFFFF'))
  141. .fontSize($r('app.float.fontSize_16'))
  142. Text(`预计完成时间: ${this.selectedOrder.planStartEnd}`)
  143. .fontColor($r('app.color.FFFFFF'))
  144. .fontSize($r('app.float.fontSize_16'))
  145. Text(`生产数量: ${this.selectedOrder.inventoryNum}`)
  146. .fontColor($r('app.color.FFFFFF'))
  147. .fontSize($r('app.float.fontSize_16'))
  148. }
  149. .margin({ top: 6 })
  150. .alignItems(HorizontalAlign.Start)
  151. .width('80%')
  152. Column({ space: 3 }){
  153. Row(){
  154. Text('物料入库比例')
  155. .width('80%')
  156. .fontColor($r('app.color.60FFFFFF'))
  157. .fontSize($r('app.float.fontSize_16'))
  158. Text(`${this.inBoundRation}%`)
  159. .width('20%')
  160. .fontColor($r('app.color.FFFFFF'))
  161. .fontSize($r('app.float.fontSize_16'))
  162. .textAlign(TextAlign.End)
  163. }
  164. Row() {
  165. Row()
  166. .width(`${this.inBoundRation}%`)
  167. .height('100%')
  168. .borderRadius($r('app.float.virtualSize_24'))
  169. .linearGradient({
  170. angle: 90,
  171. colors: [[$r('app.color.1050FF'), 0.0], [$r('app.color.73C3FF'), 1]]
  172. })
  173. }.height('10%').width('100%').backgroundColor($r('app.color.10FFFFFF'))
  174. .borderRadius($r('app.float.virtualSize_24'))
  175. Row(){
  176. Text('物料出库比例')
  177. .width('80%')
  178. .fontColor($r('app.color.60FFFFFF'))
  179. .fontSize($r('app.float.fontSize_16'))
  180. Text(`${this.outBoundRation}%`)
  181. .width('20%')
  182. .fontColor($r('app.color.FFFFFF'))
  183. .fontSize($r('app.float.fontSize_16'))
  184. .textAlign(TextAlign.End)
  185. }.margin({ top: '2%' })
  186. Row() {
  187. Row()
  188. .width(`${this.outBoundRation}%`)
  189. .height('100%')
  190. .borderRadius($r('app.float.virtualSize_24'))
  191. .linearGradient({
  192. angle: 90,
  193. colors: [[$r('app.color.1050FF'), 0.0], [$r('app.color.73C3FF'), 1]]
  194. })
  195. }
  196. .height('10%')
  197. .width('100%')
  198. .backgroundColor($r('app.color.10FFFFFF'))
  199. .borderRadius($r('app.float.virtualSize_24'))
  200. }
  201. .width('20%')
  202. .alignItems(HorizontalAlign.Start)
  203. }.width('100%')
  204. }.backgroundColor( $r('app.color.20FFFFFF'))
  205. .borderRadius($r('app.float.virtualSize_24'))
  206. .padding({left:30,right:10,top:10,bottom:5})
  207. .height('14%')
  208. .width('95%')
  209. Column(){
  210. List({scroller:this.scrollerForList}) {
  211. ForEach(this.materialData, (item:WorkOrderMaterialInfo) => {
  212. ListItem() {
  213. Column() {
  214. Column(){
  215. Text(item.itemName)
  216. .fontSize($r('app.float.fontSize_16'))
  217. .fontColor($r('app.color.FFFFFF'))
  218. .width('100%')
  219. .textAlign(TextAlign.Start)
  220. Text(`型号: ${item.itemCode}`)
  221. .fontSize($r('app.float.fontSize_16'))
  222. .fontColor($r('app.color.60FFFFFF'))
  223. .width('100%')
  224. .fontWeight(FontWeight.Lighter)
  225. .textAlign(TextAlign.Start)
  226. }
  227. Row(){
  228. Text(`入库数量:${item.storageNum}`)
  229. .fontSize($r('app.float.fontSize_16'))
  230. .fontColor($r('app.color.FFFFFF'))
  231. .width('20%')
  232. .fontWeight(FontWeight.Lighter)
  233. .textAlign(TextAlign.Start)
  234. Text(`出库数量:${item.storageNum}`)
  235. .fontSize($r('app.float.fontSize_16'))
  236. .fontColor($r('app.color.FFFFFF'))
  237. .fontWeight(FontWeight.Lighter)
  238. .width('20%')
  239. .textAlign(TextAlign.Start)
  240. Text(`缺料数量:${item.num}`)
  241. .fontSize($r('app.float.fontSize_16'))
  242. .fontColor($r('app.color.FFFFFF'))
  243. .fontWeight(FontWeight.Lighter)
  244. .width('20%')
  245. .textAlign(TextAlign.Start)
  246. Text(`需求数量:${item.num}`)
  247. .fontSize($r('app.float.fontSize_16'))
  248. .fontColor($r('app.color.FFFFFF'))
  249. .width('20%')
  250. .fontWeight(FontWeight.Lighter)
  251. .textAlign(TextAlign.Start)
  252. }.justifyContent(FlexAlign.Start).width('100%').margin({top:'1%'})
  253. }.width('100%').justifyContent(FlexAlign.SpaceEvenly).padding(10)
  254. }
  255. })
  256. }
  257. .width('100%')
  258. .height('100%')
  259. .divider({
  260. strokeWidth: 1,
  261. color: $r('app.color.20FFFFFF')
  262. })
  263. }.height('57%').width('95%').margin({top:'2%',bottom:'2%'})
  264. Divider()
  265. .vertical(false)
  266. .strokeWidth(1)
  267. .color($r('app.color.15FFFFFF'))
  268. Column(){
  269. Text('关闭')
  270. .fontColor($r('app.color.60FFFFFF'))
  271. .fontSize($r('app.float.fontSize_30'))
  272. }
  273. .height('8%')
  274. .justifyContent(FlexAlign.Center)
  275. .width('100%')
  276. .onClick(
  277. () => this.controller.close()
  278. )
  279. }
  280. .height('90%')
  281. .width('80%')
  282. .backgroundColor($r('app.color.2A2A2A'))
  283. .justifyContent(FlexAlign.End)
  284. .borderColor($r('app.color.000000'))
  285. .borderWidth(1)
  286. .borderRadius($r('app.float.virtualSize_16'))
  287. }
  288. }
  289. @Component
  290. export struct StaticMaterialList {
  291. private scrollerForList: Scroller = new Scroller()
  292. @Prop currentStock: MaterialInfo[] = []
  293. @State scaleValue : number = 1
  294. build() {
  295. Column() { // 订单列表
  296. List({ space: 8,scroller:this.scrollerForList }) {
  297. ForEach(this.currentStock, (item: MaterialInfo, index) => {
  298. ListItem() {
  299. StaticMaterialItem({
  300. item: item,
  301. index:index,
  302. currentStock:this.currentStock
  303. })
  304. }
  305. })
  306. }
  307. .width('100%')
  308. .flexGrow(1)
  309. }
  310. .width('100%')
  311. .height('100%')
  312. }
  313. }
  314. @Component
  315. struct StaticMaterialItem{
  316. @Prop item: MaterialInfo
  317. @Prop index: number
  318. @Prop currentStock:MaterialInfo[]
  319. @State scaleValue : number = 1
  320. @State selectedMaterial :MaterialInfo={}
  321. private onSelect(index: number): void {
  322. this.selectedMaterial = this.currentStock[index]
  323. }
  324. MaterialBoxController: CustomDialogController = new CustomDialogController({
  325. builder: MaterialBoxDialog({
  326. selectedMaterial:this.selectedMaterial
  327. }),
  328. autoCancel: true, // 点击遮罩关闭
  329. customStyle: true,
  330. maskColor: 'rgba(0,0,0,0.8)', // 黑色遮罩
  331. })
  332. build() {
  333. Column() {
  334. // 订单标题(带订单号)
  335. Text(`${this.item.materialName}`)
  336. .fontSize($r('app.float.fontSize_30'))
  337. .fontColor($r('app.color.FFFFFF'))
  338. .width('100%')
  339. .textAlign(TextAlign.Start)
  340. .maxLines(1) // 限制单行显示
  341. // .textOverflow({ overflow: TextOverflow.Ellipsis }) // 超出显示...
  342. // 订单详情
  343. Column({ space: 3 }) {
  344. Text(`型号: ${this.item.materialNo}`)
  345. .fontColor($r('app.color.FFFFFF'))
  346. .textAlign(TextAlign.Start)
  347. .width('100%')
  348. .fontWeight(FontWeight.Lighter)
  349. .fontSize($r('app.float.fontSize_16'))
  350. Text(`总数量: ${this.item.num}`)
  351. .fontColor($r('app.color.FFFFFF'))
  352. .width('100%')
  353. .fontWeight(FontWeight.Lighter)
  354. .fontSize($r('app.float.fontSize_16'))
  355. .textAlign(TextAlign.Start)
  356. }
  357. .margin({ top: 6 })
  358. .alignItems(HorizontalAlign.Start)
  359. }.backgroundColor(this.scaleValue===0.9 ? $r('app.color.2030D158') : $r('app.color.20FFFFFF'))
  360. .borderRadius($r('app.float.virtualSize_24'))
  361. .padding(13)
  362. //.border({width:2,color:$r('app.color.20FFFFFF')})
  363. .scale({ x: this.scaleValue, y: this.scaleValue })
  364. .animation({
  365. duration: 200,
  366. curve: Curve.Linear // 弹性曲线更生动
  367. })
  368. .onClick(() => {
  369. this.scaleValue = 0.9; // 点击时缩小
  370. setTimeout(() => {
  371. this.scaleValue = 1; // 0.2秒后恢复
  372. this.onSelect(this.index)
  373. this.MaterialBoxController.open()
  374. }, 200);
  375. })
  376. }
  377. }
  378. @CustomDialog
  379. struct MaterialBoxDialog {
  380. @Link selectedMaterial: MaterialInfo
  381. private scrollerMaterial: Scroller = new Scroller()
  382. @State selectedMaterialIndex: number = -1 // 物料箱选中索引
  383. private onSelectMaterial(index: number) {
  384. this.selectedMaterialIndex = index
  385. }
  386. @State materialBoxes: MaterialBoxInfo[] = [];
  387. @Prop emptyBoxes: EmptyBox[] = [];
  388. controller: CustomDialogController
  389. searchRequestMaterial: () => void = () => {}
  390. loadMaterialBoxes= async()=>{
  391. this.materialBoxes = await WmsRequest.post("/api/v1/stock/groupList", {
  392. materialNo: this.selectedMaterial.materialNo,
  393. } as RequestParamModel);
  394. }
  395. async aboutToAppear() {
  396. this.loadMaterialBoxes();
  397. }
  398. build() {
  399. Column() {
  400. Column(){
  401. Text('物料库存')
  402. .fontColor($r('app.color.FFFFFF'))
  403. .fontSize($r('app.float.fontSize_38'))
  404. }.height('8%')
  405. .justifyContent(FlexAlign.Center)
  406. Column() {
  407. Grid(this.scrollerMaterial) {
  408. ForEach(this.materialBoxes, (box: MaterialBoxInfo, index) => {
  409. GridItem() {
  410. Column() {
  411. // 订单标题(带订单号)
  412. Text(`${box.materials?box.materials[0].materialName:''}`)
  413. .fontSize($r('app.float.fontSize_30'))
  414. .fontColor($r('app.color.FFFFFF'))
  415. .width('100%')
  416. .textAlign(TextAlign.Start)
  417. .margin({ bottom: '2%',left:'2%' })
  418. Column({ space: 3 }) {
  419. Text(`料箱编号: ${box.vehicleCode}`)
  420. .fontColor($r('app.color.FFFFFF'))
  421. .fontSize($r('app.float.fontSize_16'))
  422. .fontWeight(FontWeight.Lighter)
  423. .textAlign(TextAlign.Start)
  424. Text(`所属订单: `)
  425. .fontColor($r('app.color.FFFFFF'))
  426. .fontSize($r('app.float.fontSize_16'))
  427. .fontWeight(FontWeight.Lighter)
  428. .textAlign(TextAlign.Start)
  429. Text(`数量: ${box.materials?box.materials[0].num:''}${box.materials?box.materials[0].unit:''}`)
  430. .fontColor($r('app.color.FFFFFF'))
  431. .fontSize($r('app.float.fontSize_16'))
  432. .fontWeight(FontWeight.Lighter)
  433. .textAlign(TextAlign.Start)
  434. Text(`层数: ${box.position}`)
  435. .fontColor($r('app.color.FFFFFF'))
  436. .fontSize($r('app.float.fontSize_16'))
  437. .fontWeight(FontWeight.Lighter)
  438. .textAlign(TextAlign.Start)
  439. Text(`位置: ${box.coordinate}`)
  440. .fontColor($r('app.color.FFFFFF'))
  441. .fontSize($r('app.float.fontSize_16'))
  442. .fontWeight(FontWeight.Lighter)
  443. .textAlign(TextAlign.Start)
  444. }
  445. .width('100%')
  446. .margin({left:'2%'})
  447. .justifyContent(FlexAlign.Start)
  448. .alignItems(HorizontalAlign.Start)
  449. }
  450. //.margin({ top: 6 })
  451. .alignItems(HorizontalAlign.Start)
  452. }
  453. .backgroundColor(index === this.selectedMaterialIndex ? $r('app.color.2030D158') : $r('app.color.20FFFFFF')) // 选中状态加深
  454. .borderRadius($r('app.float.virtualSize_24'))
  455. .padding(8)
  456. .border({
  457. width: 2,
  458. color: index === this.selectedMaterialIndex ? $r('app.color.2030D158') : $r('app.color.20FFFFFF')
  459. })
  460. .onClick(() => {
  461. this.onSelectMaterial(index)
  462. })
  463. })
  464. }
  465. .columnsTemplate('1fr 1fr 1fr')
  466. // .rowsTemplate('1fr 1fr')
  467. .columnsGap(10) // 移除网格内部列间距
  468. .rowsGap(10) // 移除网格内部行间距
  469. .width('100%') // 确保填满父容器
  470. .height('97%')
  471. .padding(10)
  472. }.height('82%')
  473. Divider()
  474. .vertical(false)
  475. .strokeWidth(1)
  476. .color($r('app.color.15FFFFFF'))
  477. Column(){
  478. Text('关闭')
  479. .fontColor($r('app.color.60FFFFFF'))
  480. .fontSize($r('app.float.fontSize_30'))
  481. }
  482. .height('8%')
  483. .justifyContent(FlexAlign.Center)
  484. .width('100%')
  485. .onClick(
  486. () => this.controller.close()
  487. )
  488. }
  489. .height('90%')
  490. .width('80%')
  491. .backgroundColor($r('app.color.2A2A2A'))
  492. .justifyContent(FlexAlign.End)
  493. .borderColor($r('app.color.000000'))
  494. .borderWidth(1)
  495. .borderRadius($r('app.float.virtualSize_16'))
  496. }
  497. }
  498. @Component
  499. export struct LineChart {
  500. private settings: RenderingContextSettings = new RenderingContextSettings(true)
  501. private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
  502. // 图表数据
  503. @Link frequencyData: number[]
  504. private readonly months: string[] = ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月']
  505. // 图表尺寸和边距
  506. private readonly chartWidth: number = 400
  507. private readonly chartHeight: number = 250
  508. private readonly chartPadding: number = 30
  509. build() {
  510. Column() {
  511. Canvas(this.context)
  512. .width(this.chartWidth)
  513. .height(this.chartHeight)
  514. .backgroundColor('#2c2c2c')
  515. .onReady(() => this.drawChart())
  516. }
  517. .width('100%')
  518. .height('100%')
  519. }
  520. private drawChart() {
  521. // 清空画布
  522. this.context.clearRect(0, 0, this.chartWidth, this.chartHeight)
  523. // 绘制坐标轴
  524. this.drawAxis()
  525. // 绘制折线
  526. this.drawLine()
  527. // 绘制数据点
  528. this.drawPoints()
  529. }
  530. private drawAxis() {
  531. this.context.beginPath()
  532. this.context.strokeStyle = '#666666'
  533. this.context.lineWidth = 1
  534. // Y轴
  535. this.context.moveTo(this.chartPadding, this.chartPadding)
  536. this.context.lineTo(this.chartPadding, this.chartHeight - this.chartPadding)
  537. // X轴
  538. this.context.moveTo(this.chartPadding, this.chartHeight - this.chartPadding)
  539. this.context.lineTo(this.chartWidth - this.chartPadding, this.chartHeight - this.chartPadding)
  540. // 绘制刻度和标签
  541. this.drawLabels()
  542. this.context.stroke()
  543. }
  544. private drawLabels() {
  545. this.context.fillStyle = '#ffffff'
  546. this.context.font = '14px sans-serif'
  547. // Y轴刻度
  548. for (let i = 0; i <= 5; i++) {
  549. const y = this.chartHeight - this.chartPadding - (i * (this.chartHeight - 2 * this.chartPadding) / 5)
  550. const value = i * 100
  551. this.context.fillText(value.toString(), 5, y + 4)
  552. }
  553. // X轴标签
  554. this.months.forEach((month, i) => {
  555. const x = this.chartPadding + (i * (this.chartWidth - 2 * this.chartPadding) / (this.months.length - 1))
  556. this.context.fillText(month, x - 15, this.chartHeight - 10)
  557. })
  558. }
  559. private drawLine() {
  560. this.context.beginPath()
  561. this.context.strokeStyle = '#2196F3'
  562. this.context.lineWidth = 2
  563. this.frequencyData.forEach((value, i) => {
  564. const x = this.chartPadding + (i * (this.chartWidth - 2 * this.chartPadding) / (this.frequencyData.length - 1))
  565. const y = this.chartHeight - this.chartPadding - ((value / 500) * (this.chartHeight - 2 * this.chartPadding))
  566. if (i === 0) {
  567. this.context.moveTo(x, y)
  568. } else {
  569. this.context.lineTo(x, y)
  570. }
  571. })
  572. this.context.stroke()
  573. }
  574. private drawPoints() {
  575. this.frequencyData.forEach((value, i) => {
  576. const x = this.chartPadding + (i * (this.chartWidth - 2 * this.chartPadding) / (this.frequencyData.length - 1))
  577. const y = this.chartHeight - this.chartPadding - ((value / 500) * (this.chartHeight - 2 * this.chartPadding))
  578. this.context.beginPath()
  579. this.context.fillStyle = '#2196F3'
  580. this.context.arc(x, y, 4, 0, Math.PI * 2)
  581. this.context.fill()
  582. })
  583. }
  584. }