sale-client 4.2.113 → 4.2.115

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.
package/.project CHANGED
@@ -5,6 +5,11 @@
5
5
  <projects>
6
6
  </projects>
7
7
  <buildSpec>
8
+ <buildCommand>
9
+ <name>org.eclipse.jdt.core.javabuilder</name>
10
+ <arguments>
11
+ </arguments>
12
+ </buildCommand>
8
13
  <buildCommand>
9
14
  <name>org.eclipse.buildship.core.gradleprojectbuilder</name>
10
15
  <arguments>
@@ -12,6 +17,7 @@
12
17
  </buildCommand>
13
18
  </buildSpec>
14
19
  <natures>
20
+ <nature>org.eclipse.jdt.core.javanature</nature>
15
21
  <nature>org.eclipse.buildship.core.gradleprojectnature</nature>
16
22
  </natures>
17
23
  <filteredResources>
@@ -1,7 +1,7 @@
1
1
  var path = require('path')
2
2
  var checkVersion = require('./versionCheck.js')
3
3
  checkVersion()
4
- const [ serverRul, localUrl ] = ['http://121.36.106.17:31467/', 'http://121.36.106.17:31467/']
4
+ const [ serverRul, localUrl ] = ['http://192.168.50.67:31567/', 'http://192.168.50.67:31567/']
5
5
  var merge = require('webpack-merge')
6
6
  var baseConfig = require('./webpack.dev.conf')
7
7
  var devConfig = {
@@ -50,12 +50,12 @@ var devConfig = {
50
50
  '/rs/pay': {
51
51
  target: 'http://localhost:8080'
52
52
  },
53
- // '/api/af-revenue': {
54
- // pathRewrite: {
55
- // '/api/af-revenue': '/af-revenue'
56
- // },
57
- // target: "http://localhost:8080"
58
- // },
53
+ '/api/af-revenue': {
54
+ pathRewrite: {
55
+ '/api/af-revenue': '/af-revenue'
56
+ },
57
+ target: "http://localhost:8080"
58
+ },
59
59
  '/api': {
60
60
  target: serverRul
61
61
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sale-client",
3
- "version": "4.2.113",
3
+ "version": "4.2.115",
4
4
  "description": "收费模块前台组件",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,498 @@
1
+ <template>
2
+ <div class="evaluation-panel">
3
+ <div class="status-bar">
4
+ <div class="error" v-if="error">
5
+ <h4>错误信息:</h4>
6
+ <pre>{{ error }}</pre>
7
+ </div>
8
+ <div class="status-item">
9
+ <span>员工: {{ signInParams.name }} (工号: {{ signInParams.num }})</span>
10
+ </div>
11
+ <div class="status-item">
12
+ <span>评价状态: {{ evaluationStatus }}</span>
13
+ </div>
14
+ </div>
15
+
16
+ <div class="section">
17
+ <button class="btn-gn" @click="openSubScreen" :disabled="loading || subScreenState.isOpen">评价</button>
18
+ <button class="btn-gn" @click="closeSubScreen" :disabled="!subScreenState.isOpen">关闭副屏</button>
19
+ <button class="button_clear btn-gn" @click="clean">取消</button>
20
+ </div>
21
+ </div>
22
+ </template>
23
+
24
+ <script>
25
+ import QXClient from '../../../plugins/QXClient'
26
+
27
+ export default {
28
+ title: 'ServiceEvaluation',
29
+ data() {
30
+ return {
31
+ signInParams: {
32
+ num: this.$login.f.id,
33
+ name: this.$login.f.name,
34
+ pos: this.$login.f.f_show_rolestr,
35
+ org: this.$login.f.f_show_department_name,
36
+ equ: this.$login.f.f_show_department_name,
37
+ },
38
+ loading: false,
39
+ error: null,
40
+ response: null,
41
+ evaluationStatus: '未发起',
42
+ isComponentDestroyed: false,
43
+
44
+ // 副屏相关状态
45
+ broadcastChannel: null,
46
+ myWindow: null,
47
+ isWindows: navigator.platform.indexOf('Win') !== -1,
48
+
49
+ subScreenState: {
50
+ isOpen: false
51
+ }
52
+ }
53
+ },
54
+
55
+ props: {
56
+ row: {
57
+ type: Object,
58
+ default: undefined
59
+ }
60
+ },
61
+
62
+ ready() {
63
+ console.log('ServiceEvaluation 组件已加载')
64
+
65
+ // 监听页面卸载
66
+ window.addEventListener('beforeunload', this.cleanup)
67
+ },
68
+
69
+ beforeDestroy() {
70
+ this.cleanup()
71
+ },
72
+
73
+ destroyed() {
74
+ this.cleanup()
75
+ },
76
+
77
+ methods: {
78
+ cleanup() {
79
+ console.log('开始清理组件资源')
80
+ this.isComponentDestroyed = true
81
+
82
+ // 重置状态
83
+ this.loading = false
84
+
85
+ // 关闭广播通道
86
+ if (this.broadcastChannel) {
87
+ try {
88
+ this.broadcastChannel.close()
89
+ } catch (e) {
90
+ console.warn('关闭广播通道时出错:', e)
91
+ }
92
+ this.broadcastChannel = null
93
+ }
94
+
95
+ // 关闭窗口
96
+ if (this.myWindow && !this.myWindow.closed) {
97
+ try {
98
+ this.myWindow.close()
99
+ } catch (e) {
100
+ console.warn('关闭窗口时出错:', e)
101
+ }
102
+ this.myWindow = null
103
+ }
104
+
105
+ // 移除事件监听
106
+ window.removeEventListener('beforeunload', this.cleanup)
107
+
108
+ this.subScreenState.isOpen = false
109
+ },
110
+
111
+ safeExecute() {
112
+ if (this.isComponentDestroyed) {
113
+ console.log('组件已销毁,停止执行')
114
+ return false
115
+ }
116
+ return true
117
+ },
118
+
119
+ clean() {
120
+ this.$info('取消操作')
121
+ this.$dispatch('refresh', this.row)
122
+ },
123
+
124
+ // 打开副屏进行评价
125
+ openSubScreen() {
126
+ const url = './evaluation/evaluation.html'
127
+
128
+ console.log('正在打开副屏...')
129
+
130
+ // 清理旧的广播通道
131
+ if (this.broadcastChannel) {
132
+ try {
133
+ this.broadcastChannel.close()
134
+ } catch (e) {
135
+ console.warn('关闭旧通道时出错:', e)
136
+ }
137
+ this.broadcastChannel = null
138
+ }
139
+
140
+ // 创建新的广播通道
141
+ try {
142
+ this.broadcastChannel = new BroadcastChannel('QX-demo')
143
+
144
+ this.broadcastChannel.onmessage = (event) => {
145
+ console.log('收到副屏消息:', event.data)
146
+ this.handleSubScreenMessage(event.data)
147
+ }
148
+
149
+ this.broadcastChannel.onmessageerror = (event) => {
150
+ console.error('广播通道消息错误:', event)
151
+ }
152
+
153
+ } catch (error) {
154
+ console.error('创建广播通道失败:', error)
155
+ this.error = '创建通信通道失败: ' + error.message
156
+ return
157
+ }
158
+
159
+ // 更新状态
160
+ this.subScreenState.isOpen = true
161
+ this.loading = true
162
+ this.evaluationStatus = '等待用户评价'
163
+ this.error = null
164
+
165
+ // Windows系统手动打开窗口
166
+ if (this.isWindows) {
167
+ if (this.myWindow && !this.myWindow.closed) {
168
+ try {
169
+ this.myWindow.close()
170
+ } catch (e) {
171
+ console.warn('关闭旧窗口时出错:', e)
172
+ }
173
+ }
174
+
175
+ this.myWindow = window.open(
176
+ url,
177
+ '_blank',
178
+ 'height=800px, width=1280px, top=0, left=0, toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no'
179
+ )
180
+
181
+ if (this.myWindow) {
182
+ this.myWindow.focus()
183
+ } else {
184
+ this.error = '无法打开新窗口,请检查浏览器弹窗设置'
185
+ this.loading = false
186
+ this.subScreenState.isOpen = false
187
+ return
188
+ }
189
+ }
190
+
191
+ // 调用客户端API打开副屏
192
+ QXClient.openwebontablet({
193
+ data: { url: url },
194
+ successCallback: (data) => {
195
+ console.log('打开副屏成功:', data)
196
+
197
+ // 发送准备消息给副屏
198
+ setTimeout(() => {
199
+ if (this.broadcastChannel) {
200
+ this.broadcastChannel.postMessage({
201
+ type: 'mainscreen_ready',
202
+ timestamp: new Date().toISOString(),
203
+ message: '主屏已准备就绪'
204
+ })
205
+ }
206
+ }, 500)
207
+ },
208
+ errorCallback: (error) => {
209
+ console.error('打开副屏失败:', error)
210
+ this.error = '打开副屏失败: ' + JSON.stringify(error)
211
+ this.showCeAlert(this.error, 'error')
212
+
213
+ // 清理资源
214
+ if (this.broadcastChannel) {
215
+ this.broadcastChannel.close()
216
+ this.broadcastChannel = null
217
+ }
218
+
219
+ this.loading = false
220
+ this.subScreenState.isOpen = false
221
+ this.evaluationStatus = '未发起'
222
+ }
223
+ })
224
+ },
225
+
226
+ // 处理副屏消息
227
+ handleSubScreenMessage(data) {
228
+ try {
229
+ let parsedData = data
230
+ if (typeof data === 'string') {
231
+ try {
232
+ parsedData = JSON.parse(data)
233
+ } catch (e) {
234
+ // 如果不是JSON,保持原样
235
+ }
236
+ }
237
+
238
+ // 处理不同类型的消息
239
+ if (typeof parsedData === 'object' && parsedData.type) {
240
+ switch (parsedData.type) {
241
+ case 'evaluation_result':
242
+ this.processEvaluationResult(parsedData.result || parsedData)
243
+ break
244
+
245
+ case 'evaluation_canceled':
246
+ this.showCeAlert('用户取消了评价', 'warning')
247
+ this.evaluationStatus = '用户取消了评价'
248
+
249
+ // 延迟关闭副屏
250
+ setTimeout(() => {
251
+ this.closeSubScreen()
252
+ }, 1000)
253
+ break
254
+
255
+ case 'subscreen_ready':
256
+ break
257
+ }
258
+ } else if (parsedData && parsedData.eva_value !== undefined) {
259
+ // 兼容旧格式的评价结果
260
+ this.processEvaluationResult(parsedData)
261
+ }
262
+ } catch (error) {
263
+ console.error('处理副屏消息时出错:', error)
264
+ }
265
+ },
266
+
267
+ // 处理评价结果
268
+ async processEvaluationResult(result) {
269
+ console.log('处理评价结果:', result)
270
+ // 保存评价结果
271
+ this.evaluationStatus = '用户已评价'
272
+ // 提交评价到服务器
273
+ await this.submitEvaluation(result.eva_value)
274
+
275
+ // 延迟关闭副屏
276
+ setTimeout(() => {
277
+ this.closeSubScreen()
278
+ }, 2000)
279
+ },
280
+
281
+ // 提交评价到服务器
282
+ async submitEvaluation(value) {
283
+ if (!this.safeExecute()) return
284
+
285
+ this.evaluationStatus = '正在提交评价...'
286
+ console.log('用户评价值:', value)
287
+
288
+ try {
289
+ await this.$resetpost('api/af-revenue/logic/saveEvaluationBussiness', {
290
+ f_orgid: this.$login.f.orgid,
291
+ f_userinfo_id: this.row.f_userinfo_id,
292
+ f_operatorid: this.$login.f.id,
293
+ f_satisfaction: 5 - value,
294
+ f_user_type: this.row.f_user_type
295
+ }, {resolveMsg: '提交评价成功', rejectMsg: '提交评价失败!'})
296
+
297
+ this.showCeAlert('评价提交成功', 'success')
298
+ this.evaluationStatus = '评价已提交'
299
+ this.$dispatch('success', '评价')
300
+ } catch (error) {
301
+ console.error('提交评价失败:', error)
302
+ this.showCeAlert('提交评价失败: ' + (error.message || '未知错误'), 'error')
303
+ this.evaluationStatus = '提交失败'
304
+ }
305
+
306
+ this.loading = false
307
+ },
308
+
309
+ // 关闭副屏
310
+ closeSubScreen() {
311
+
312
+ // 发送关闭消息给副屏
313
+ if (this.broadcastChannel) {
314
+ try {
315
+ this.broadcastChannel.postMessage({
316
+ type: 'close_subscreen',
317
+ message: '主屏要求关闭副屏',
318
+ timestamp: new Date().toISOString()
319
+ })
320
+ } catch (e) {
321
+ console.warn('发送关闭消息时出错:', e)
322
+ }
323
+
324
+ // 延迟关闭通道
325
+ setTimeout(() => {
326
+ try {
327
+ this.broadcastChannel.close()
328
+ } catch (e) {
329
+ console.warn('关闭广播通道时出错:', e)
330
+ }
331
+ this.broadcastChannel = null
332
+ }, 300)
333
+ }
334
+
335
+ // 调用客户端API关闭副屏
336
+ QXClient.closewebontablet({
337
+ successCallback: (data) => {
338
+ console.log('关闭副屏成功:', data)
339
+ this.subScreenState.isOpen = false
340
+ },
341
+ errorCallback: (error) => {
342
+ console.error('关闭副屏失败:', error)
343
+ this.subScreenState.isOpen = false
344
+ }
345
+ })
346
+
347
+ // 关闭Windows窗口
348
+ if (this.myWindow && !this.myWindow.closed) {
349
+ try {
350
+ this.myWindow.close()
351
+ } catch (e) {
352
+ console.warn('关闭Windows窗口时出错:', e)
353
+ }
354
+ this.myWindow = null
355
+ }
356
+
357
+ this.subScreenState.isOpen = false
358
+ },
359
+
360
+ showCeAlert(message, type) {
361
+ if (!this.safeExecute()) return
362
+ if (type === 'error') {
363
+ console.error(message)
364
+ this.$showAlert(message, 'danger', 2000)
365
+ } else if (type === 'warning') {
366
+ this.$showAlert(message, 'warning', 2000)
367
+ } else {
368
+ console.log(message)
369
+ this.$showAlert(message, 'success', 2000)
370
+ }
371
+ }
372
+ }
373
+ }
374
+ </script>
375
+
376
+ <style scoped>
377
+ .evaluation-panel {
378
+ padding: 20px;
379
+ }
380
+
381
+ .status-bar {
382
+ background-color: #f8f9fa;
383
+ border: 1px solid #dee2e6;
384
+ border-radius: 5px;
385
+ padding: 15px;
386
+ margin-bottom: 20px;
387
+ }
388
+
389
+ .status-item {
390
+ display: flex;
391
+ align-items: center;
392
+ margin: 8px 0;
393
+ }
394
+
395
+ .section {
396
+ margin-bottom: 20px;
397
+ padding: 15px;
398
+ border: 1px solid #e0e0e0;
399
+ border-radius: 5px;
400
+ }
401
+
402
+ .section h3 {
403
+ margin-top: 0;
404
+ color: #333;
405
+ border-bottom: 1px solid #ddd;
406
+ padding-bottom: 8px;
407
+ }
408
+
409
+ .button_search, .button_clear, .btn-gn {
410
+ padding: 10px 20px;
411
+ margin-right: 10px;
412
+ border: none;
413
+ border-radius: 4px;
414
+ cursor: pointer;
415
+ font-size: 14px;
416
+ }
417
+
418
+ .button_search {
419
+ background-color: #007bff;
420
+ color: white;
421
+ }
422
+
423
+ .button_clear {
424
+ background-color: #6c757d;
425
+ color: white;
426
+ }
427
+
428
+ .btn-gn {
429
+ background-color: #28a745;
430
+ color: white;
431
+ }
432
+
433
+ button:disabled {
434
+ background-color: #cccccc;
435
+ cursor: not-allowed;
436
+ }
437
+
438
+ .log-container {
439
+ max-height: 150px;
440
+ overflow-y: auto;
441
+ padding: 10px;
442
+ background-color: #f8f9fa;
443
+ border-radius: 4px;
444
+ font-size: 12px;
445
+ }
446
+
447
+ .log-entry {
448
+ padding: 5px;
449
+ margin-bottom: 3px;
450
+ border-left: 3px solid #ccc;
451
+ }
452
+
453
+ .log-entry.info {
454
+ border-left-color: #6c757d;
455
+ }
456
+
457
+ .log-entry.received {
458
+ border-left-color: #28a745;
459
+ }
460
+
461
+ .log-entry.sent {
462
+ border-left-color: #007bff;
463
+ }
464
+
465
+ .log-entry.error {
466
+ border-left-color: #dc3545;
467
+ }
468
+
469
+ .log-time {
470
+ color: #6c757d;
471
+ margin-right: 10px;
472
+ }
473
+
474
+ .log-message {
475
+ word-break: break-word;
476
+ }
477
+
478
+ .error {
479
+ background-color: #fef0f0;
480
+ border-left: 4px solid #f56c6c;
481
+ padding: 15px;
482
+ margin-top: 20px;
483
+ border-radius: 4px;
484
+ }
485
+
486
+ .error h4 {
487
+ margin-top: 0;
488
+ color: #f56c6c;
489
+ }
490
+
491
+ pre {
492
+ white-space: pre-wrap;
493
+ word-wrap: break-word;
494
+ margin: 0;
495
+ font-family: 'Courier New', monospace;
496
+ font-size: 13px;
497
+ }
498
+ </style>
@@ -79,6 +79,7 @@
79
79
  data () {
80
80
  return {
81
81
  model: {},
82
+ repairList: [], // 所有维修记录列表
82
83
  pared: 0,
83
84
  repairImages: [] // 维修照片列表
84
85
  }
@@ -95,25 +96,27 @@
95
96
  }
96
97
  let http = new HttpResetClass()
97
98
  let res = await http.load('POST', 'api/af-revenue/sql/getServiceRepair', {data: data}, {resolveMsg: null, rejectMsg: null})
98
- this.model = res.data[0]
99
- console.log('看看维修情况', res, this.model)
100
- if (this.model) {
99
+ console.log('看看维修情况', res, res.data)
100
+ if (res.data && res.data.length > 0) {
101
+ this.repairList = res.data
102
+ this.model = res.data[0]
101
103
  this.pared = 1
102
- await this.getRepairImages(this.model.id)
104
+ await this.getAllRepairImages(res.data)
103
105
  } else {
104
106
  this.pared = 0
107
+ this.repairList = []
105
108
  this.repairImages = []
106
109
  }
107
110
  } else {
108
111
  this.pared = 0
112
+ this.repairList = []
109
113
  this.repairImages = []
110
114
  }
111
115
  },
112
- // 获取维修照片
116
+ // 获取单个维修记录的照片
113
117
  async getRepairImages (workorderId) {
114
118
  if (!workorderId) {
115
- this.repairImages = []
116
- return
119
+ return []
117
120
  }
118
121
  try {
119
122
  let http = new HttpResetClass()
@@ -132,16 +135,33 @@
132
135
  }
133
136
  }, {resolveMsg: null, rejectMsg: null})
134
137
  if (repairImgRes.data && repairImgRes.data.length > 0) {
135
- this.repairImages = repairImgRes.data
136
- console.log('this.repairImages', this.repairImages)
137
- } else {
138
- this.repairImages = []
138
+ return repairImgRes.data
139
139
  }
140
- } else {
141
- this.repairImages = []
142
140
  }
141
+ return []
143
142
  } catch (error) {
144
143
  console.error('获取维修照片失败:', error)
144
+ return []
145
+ }
146
+ },
147
+ // 获取所有维修记录的照片
148
+ async getAllRepairImages (repairList) {
149
+ if (!repairList || repairList.length === 0) {
150
+ this.repairImages = []
151
+ return
152
+ }
153
+ try {
154
+ let allImages = []
155
+ for (let repair of repairList) {
156
+ if (repair.id) {
157
+ let images = await this.getRepairImages(repair.id)
158
+ allImages = allImages.concat(images)
159
+ }
160
+ }
161
+ this.repairImages = allImages
162
+ console.log('所有维修照片', this.repairImages)
163
+ } catch (error) {
164
+ console.error('获取所有维修照片失败:', error)
145
165
  this.repairImages = []
146
166
  }
147
167
  }
@@ -63,6 +63,7 @@
63
63
  <th>收费时间</th>
64
64
  <th>记录状态</th>
65
65
  <th>生成记录人员</th>
66
+ <th>备注</th>
66
67
  <th>所属分公司</th>
67
68
  <th>操作</th>
68
69
  </tr>
@@ -79,6 +80,7 @@
79
80
  <td>{{ row.f_operate_date }}</td>
80
81
  <td>{{ row.f_state }}</td>
81
82
  <td>{{ row.f_operator }}</td>
83
+ <td>{{ row.f_comment }}</td>
82
84
  <td>{{ row.f_orgname }}</td>
83
85
  <td style="text-align: center"> <button v-if="row.f_state === '待生成'" type="button" class="btn btn-danger" @click.stop="$parent.$parent.$parent.cancel(row)">作废</button>&nbsp;&nbsp;&nbsp;
84
86
  </td>