manage-client 4.1.140 → 4.1.142

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,8 +6,8 @@ const proxyMiddleware = require('http-proxy-middleware')
6
6
  const app = express()
7
7
  const compiler = webpack(config)
8
8
 
9
- const server = 'http://192.168.50.67:31567/'
10
- const local = 'http://127.0.0.1:9026/'
9
+ const server = 'http://121.36.106.17:31467/'
10
+ const local = 'http://121.36.106.17:31467/'
11
11
  const proxyTable = {
12
12
  '/rs/logic/exportfile': {
13
13
  target: server
@@ -16,21 +16,21 @@ const proxyTable = {
16
16
  target: server
17
17
  },
18
18
  '/api/af-revenue/sql/': {
19
- pathRewrite: {
20
- '^/api/af-revenue': '/'
21
- },
19
+ // pathRewrite: {
20
+ // '^/api/af-revenue': '/'
21
+ // },
22
22
  target: local
23
23
  },
24
24
  '/api/af-revenue/report/': {
25
- pathRewrite: {
26
- '^/api/af-revenue': '/'
27
- },
25
+ // pathRewrite: {
26
+ // '^/api/af-revenue': '/'
27
+ // },
28
28
  target: local
29
29
  },
30
30
  '/api/af-revenue/logic': {
31
- pathRewrite: {
32
- '^/api/af-revenue': '/'
33
- },
31
+ // pathRewrite: {
32
+ // '^/api/af-revenue': '/'
33
+ // },
34
34
  target: local
35
35
  },
36
36
  '/api': {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "manage-client",
3
- "version": "4.1.140",
3
+ "version": "4.1.142",
4
4
  "description": "经营管控模块前台组件",
5
5
  "main": "src/index.js",
6
6
  "directories": {
@@ -132,10 +132,28 @@
132
132
  <button class="button_clear" @click="cancel()">取消</button>
133
133
  </footer>
134
134
  </modal>
135
+ <modal :show.sync="signatureModalShow" large backdrop="false" width="50%">
136
+ <header slot="modal-header" class="modal-header" style="text-align: center">
137
+ <h4 class="modal-title">业务员签名</h4>
138
+ </header>
139
+ <article slot="modal-body" class="modal-body">
140
+ <div style="text-align:center">
141
+ <canvas v-ref:signCanvas data-sign-canvas="true"
142
+ style="border:1px solid #ccc; background:#fff; width:600px; height:300px; touch-action:none;">
143
+ </canvas>
144
+ </div>
145
+ </article>
146
+ <footer slot="modal-footer" class="modal-footer">
147
+ <button type="button" class="button_clear" @click="clearSignatureCanvas()">清除</button>
148
+ <button type="button" class="button_search" @click="saveSignatureAndSubmit()" :disabled="signatureUploadInProgress">保存并提交</button>
149
+ <button type="button" class="button_clear" @click="signatureModalShow=false">取消</button>
150
+ </footer>
151
+ </modal>
135
152
  </div>
136
153
  </template>
137
154
 
138
155
  <script>
156
+ import Vue from 'vue'
139
157
  import {DataModel} from 'vue-client'
140
158
  import co from 'co'
141
159
 
@@ -174,6 +192,16 @@ export default {
174
192
  },
175
193
  pushAuditData: {},
176
194
  pushAuditShow: false,
195
+ signatureModalShow: false,
196
+ signatureData: '',
197
+ signatureDrawn: false,
198
+ signatureUploadInProgress: false,
199
+ signing: false,
200
+ signLastX: 0,
201
+ signLastY: 0,
202
+ signDPR: 1,
203
+ signCanvasContext: null,
204
+ signatureCanvas: null,
177
205
  config: {
178
206
  hasAudit: false
179
207
  }
@@ -189,10 +217,21 @@ export default {
189
217
  },
190
218
  methods: {
191
219
  auditConfirm () {
220
+ // If no signature yet, require the reviewer to sign first
221
+ if (!this.pushAuditData.f_audit_person) {
222
+ this.$showMessage('请选择审核人')
223
+ return
224
+ }
225
+ if (!this.pushAuditData.signature) {
226
+ this.signatureModalShow = true
227
+ return
228
+ }
229
+
192
230
  const param = {
193
231
  f_type: '收费结账报表',
194
232
  f_requestparam: this.model.data,
195
233
  f_audit_person: this.pushAuditData.f_audit_person,
234
+ f_signature: this.pushAuditData.signature,
196
235
  f_otherparam: this.pushAuditData,
197
236
  f_operator: this.$login.f.name,
198
237
  f_operatorid: this.$login.f.id,
@@ -210,8 +249,286 @@ export default {
210
249
  }).then((res) => {
211
250
  this.pushAuditShow = false
212
251
  this.pushAuditData.f_audit_person = ''
252
+ this.pushAuditData.signature = ''
253
+ })
254
+ },
255
+ initSignCanvas () {
256
+ this.$nextTick(() => {
257
+ let canvas = this.$refs.signCanvas
258
+ if (!canvas) {
259
+ canvas = this.$el.querySelector('canvas[data-sign-canvas]') || document.querySelector('canvas[data-sign-canvas]')
260
+
261
+ }
262
+ const desiredW = 600
263
+ const desiredH = 300
264
+ canvas.width = desiredW
265
+ canvas.height = desiredH
266
+ canvas.style.width = desiredW + 'px'
267
+ canvas.style.height = desiredH + 'px'
268
+ const ctx = canvas.getContext('2d')
269
+ ctx.setTransform(1, 0, 0, 1, 0, 0)
270
+ ctx.fillStyle = '#fff'
271
+ ctx.fillRect(0, 0, desiredW, desiredH)
272
+ ctx.strokeStyle = '#000'
273
+ ctx.lineWidth = 2
274
+ ctx.lineCap = 'round'
275
+ ctx.lineJoin = 'round'
276
+ this.signCanvasContext = ctx
277
+ this.signing = false
278
+ this.signatureDrawn = false
279
+ this.destroySignCanvasListeners()
280
+ const getPoint = (event) => {
281
+ const rect = canvas.getBoundingClientRect()
282
+ let clientX = event.clientX
283
+ let clientY = event.clientY
284
+ if (event.touches && event.touches.length) {
285
+ clientX = event.touches[0].clientX
286
+ clientY = event.touches[0].clientY
287
+ } else if (event.changedTouches && event.changedTouches.length) {
288
+ clientX = event.changedTouches[0].clientX
289
+ clientY = event.changedTouches[0].clientY
290
+ }
291
+ if (clientX == null || clientY == null) return null
292
+ const x = (clientX - rect.left) * (canvas.width / rect.width)
293
+ const y = (clientY - rect.top) * (canvas.height / rect.height)
294
+ return { x, y }
295
+ }
296
+
297
+ const onStart = (event) => {
298
+ event.preventDefault()
299
+ const point = getPoint(event)
300
+ if (!point) return
301
+ this.signing = true
302
+ this.signatureDrawn = true
303
+ this.signLastX = point.x
304
+ this.signLastY = point.y
305
+ }
306
+ const onMove = (event) => {
307
+ if (!this.signing) return
308
+ event.preventDefault()
309
+ const point = getPoint(event)
310
+ if (!point) return
311
+ const ctx2 = this.signCanvasContext
312
+ ctx2.beginPath()
313
+ ctx2.moveTo(this.signLastX, this.signLastY)
314
+ ctx2.lineTo(point.x, point.y)
315
+ ctx2.stroke()
316
+ this.signLastX = point.x
317
+ this.signLastY = point.y
318
+ }
319
+ const onEnd = (event) => {
320
+ if (this.signing) {
321
+ event.preventDefault()
322
+ }
323
+ this.signing = false
324
+ }
325
+ canvas.addEventListener('mousedown', onStart)
326
+ canvas.addEventListener('mousemove', onMove)
327
+ canvas.addEventListener('mouseup', onEnd)
328
+ canvas.addEventListener('mouseleave', onEnd)
329
+ canvas.addEventListener('touchstart', onStart, {passive:false})
330
+ canvas.addEventListener('touchmove', onMove, {passive:false})
331
+ canvas.addEventListener('touchend', onEnd)
332
+ canvas.addEventListener('touchcancel', onEnd)
333
+
334
+ this._signCanvasListeners = { canvas, onStart, onMove, onEnd }
335
+ this.signatureCanvas = canvas
336
+ })
337
+ },
338
+ destroySignCanvasListeners () {
339
+ if (!this._signCanvasListeners) return
340
+ const { canvas, onStart, onMove, onEnd } = this._signCanvasListeners
341
+ canvas.removeEventListener('mousedown', onStart)
342
+ canvas.removeEventListener('mousemove', onMove)
343
+ canvas.removeEventListener('mouseup', onEnd)
344
+ canvas.removeEventListener('mouseleave', onEnd)
345
+ canvas.removeEventListener('touchstart', onStart)
346
+ canvas.removeEventListener('touchmove', onMove)
347
+ canvas.removeEventListener('touchend', onEnd)
348
+ canvas.removeEventListener('touchcancel', onEnd)
349
+ this._signCanvasListeners = null
350
+ this.signatureCanvas = null
351
+ },
352
+ getSignCanvasElement () {
353
+ return this.$refs.signCanvas || this.signatureCanvas || this.$el.querySelector('canvas[data-sign-canvas]') || document.querySelector('canvas[data-sign-canvas]')
354
+ },
355
+ getSignPoint (event) {
356
+ const canvas = this.getSignCanvasElement()
357
+ if (!canvas) return null
358
+ const rect = canvas.getBoundingClientRect()
359
+ let clientX = event.clientX
360
+ let clientY = event.clientY
361
+
362
+ if (event.touches && event.touches.length) {
363
+ clientX = event.touches[0].clientX
364
+ clientY = event.touches[0].clientY
365
+ } else if (event.changedTouches && event.changedTouches.length) {
366
+ clientX = event.changedTouches[0].clientX
367
+ clientY = event.changedTouches[0].clientY
368
+ }
369
+
370
+ if (clientX == null || clientY == null) return null
371
+
372
+ // Use offset within canvas bounding box
373
+ const x = (clientX - rect.left) * (canvas.width / rect.width)
374
+ const y = (clientY - rect.top) * (canvas.height / rect.height)
375
+ return { x, y }
376
+ },
377
+ signStart (event) {
378
+ // legacy support: keep method but not used by native listeners
379
+ if (!this.signCanvasContext) return
380
+ const point = this.getSignPoint(event)
381
+ if (!point) return
382
+ this.signing = true
383
+ this.signatureDrawn = true
384
+ this.signLastX = point.x
385
+ this.signLastY = point.y
386
+ },
387
+ signMove (event) {
388
+ if (!this.signing || !this.signCanvasContext) return
389
+ const point = this.getSignPoint(event)
390
+ if (!point) return
391
+ const ctx = this.signCanvasContext
392
+ ctx.beginPath()
393
+ ctx.moveTo(this.signLastX, this.signLastY)
394
+ ctx.lineTo(point.x, point.y)
395
+ ctx.stroke()
396
+ this.signLastX = point.x
397
+ this.signLastY = point.y
398
+ },
399
+ signEnd () {
400
+ this.signing = false
401
+ },
402
+ clearSignatureCanvas () {
403
+ const canvas = this.getSignCanvasElement()
404
+ const ctx = this.signCanvasContext || (canvas ? canvas.getContext('2d') : null)
405
+ if (!canvas || !ctx) {
406
+ return
407
+ }
408
+
409
+ const desiredW = 600
410
+ const desiredH = 300
411
+ ctx.setTransform(1, 0, 0, 1, 0, 0)
412
+ ctx.clearRect(0, 0, desiredW, desiredH)
413
+ ctx.fillStyle = '#fff'
414
+ ctx.fillRect(0, 0, desiredW, desiredH)
415
+ this.signatureDrawn = false
416
+ this.pushAuditData.signature = ''
417
+ },
418
+ getUploadPathFromResponse (res) {
419
+ return res && (res.id)
420
+ },
421
+ canvasToBlob (canvas) {
422
+ return new Promise((resolve, reject) => {
423
+ if (canvas.toBlob) {
424
+ canvas.toBlob((blob) => {
425
+ if (blob) {
426
+ resolve(blob)
427
+ } else {
428
+ reject(new Error('canvas toBlob returned null'))
429
+ }
430
+ }, 'image/png')
431
+ } else {
432
+ try {
433
+ const dataURL = canvas.toDataURL('image/png')
434
+ const byteString = atob(dataURL.split(',')[1])
435
+ const mimeString = dataURL.split(',')[0].split(':')[1].split(';')[0]
436
+ const ab = new ArrayBuffer(byteString.length)
437
+ const ia = new Uint8Array(ab)
438
+ for (let i = 0; i < byteString.length; i++) {
439
+ ia[i] = byteString.charCodeAt(i)
440
+ }
441
+ resolve(new Blob([ab], { type: mimeString }))
442
+ } catch (err) {
443
+ reject(err)
444
+ }
445
+ }
446
+ })
447
+ },
448
+ uploadSignatureFile () {
449
+ return new Promise(async (resolve, reject) => {
450
+ const canvas = this.getSignCanvasElement()
451
+ if (!canvas) {
452
+ reject(new Error('签名画布未找到'))
453
+ return
454
+ }
455
+ let blob
456
+ try {
457
+ blob = await this.canvasToBlob(canvas)
458
+ } catch (err) {
459
+ reject(err)
460
+ return
461
+ }
462
+
463
+ const form = new FormData()
464
+ form.append('file', blob, 'signature.png')
465
+
466
+ const xhr = new XMLHttpRequest()
467
+ xhr.open('POST', 'api/af-revenue/file/uploadFile', true)
468
+ if (Vue.$login && Vue.$login.jwt) {
469
+ xhr.setRequestHeader('Authorization', 'Bearer ' + Vue.$login.jwtNew)
470
+ xhr.setRequestHeader('Token', Vue.$login.jwt)
471
+ }
472
+
473
+ xhr.onreadystatechange = function () {
474
+ if (xhr.readyState < 4) return
475
+ if (xhr.status < 400) {
476
+ try {
477
+ const res = JSON.parse(xhr.responseText)
478
+ const uploadPath = this.getUploadPathFromResponse(res)
479
+ if (!uploadPath) {
480
+ reject(new Error('上传成功但未返回有效路径'))
481
+ return
482
+ }
483
+ resolve(uploadPath)
484
+ } catch (err) {
485
+ reject(err)
486
+ }
487
+ } else {
488
+ let err
489
+ try {
490
+ err = JSON.parse(xhr.responseText)
491
+ } catch (parseErr) {
492
+ err = new Error(xhr.statusText || '签名上传失败')
493
+ }
494
+ reject(err)
495
+ }
496
+ }.bind(this)
497
+
498
+ xhr.onerror = function () {
499
+ reject(new Error('签名文件上传网络错误'))
500
+ }
501
+
502
+ xhr.send(form)
213
503
  })
214
504
  },
505
+ async saveSignatureAndSubmit () {
506
+ if (!this.signatureDrawn) {
507
+ if (this.$showMessage) this.$showMessage('请先签名')
508
+ return
509
+ }
510
+
511
+ const canvas = this.getSignCanvasElement()
512
+ if (!canvas) {
513
+ if (this.$showMessage) this.$showMessage('签名画布未找到,请重新打开签名弹窗')
514
+ return
515
+ }
516
+
517
+ if (this.signatureUploadInProgress) {
518
+ return
519
+ }
520
+ this.signatureUploadInProgress = true
521
+ try {
522
+ const uploadPath = await this.uploadSignatureFile()
523
+ this.pushAuditData.signature = uploadPath
524
+ this.signatureModalShow = false
525
+ this.auditConfirm()
526
+ } catch (err) {
527
+ if (this.$showMessage) this.$showMessage('签名上传失败,请重试')
528
+ } finally {
529
+ this.signatureUploadInProgress = false
530
+ }
531
+ },
215
532
  async getAuditor () {
216
533
  await this.$MagGetSaleParam.initinputtor()
217
534
  console.log('查询到的人员:', await this.$MagGetSaleParam.initinputtor())
@@ -221,6 +538,7 @@ export default {
221
538
  },
222
539
  cancel () {
223
540
  this.pushAuditShow = false
541
+ this.pushAuditData.signature = ''
224
542
  },
225
543
  pushAudit () {
226
544
  if (this.model.data === null || this.model.data === ' ') {
@@ -278,6 +596,15 @@ export default {
278
596
  }
279
597
  this.spans = len
280
598
  }
599
+ ,
600
+ signatureModalShow (val) {
601
+ console.log('[ManageBusSummary] signatureModalShow watcher', val)
602
+ if (val) {
603
+ this.initSignCanvas()
604
+ } else {
605
+ this.destroySignCanvasListeners()
606
+ }
607
+ }
281
608
  },
282
609
  computed: {
283
610
  charge_state () {