mg-ocr-invoice 0.2.3 → 0.2.4-beta

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.
@@ -1,104 +1,247 @@
1
1
  <template>
2
2
  <div class="Invoice">
3
- <div class="top" @click="openPreViewImg">
4
- <img :src="invoiceData.attachmentLink" alt="" />
3
+ <div class="top">
4
+ <img
5
+ :src="props.invoiceData.attachmentLink"
6
+ @click.stop="openPreViewImg"
7
+ alt="" />
5
8
  </div>
6
- <div class="company">
7
- <div class="title"><i></i> <span>公司</span></div>
8
- <div class="cardText">
9
- <p style="font-size: 13px; color: #888888">销售方</p>
10
- <div class="card">
11
- <div class="companyName">{{ invoiceData.sellerName }}</div>
12
- <div class="sellerInformation">
13
- <ul>
14
- <li>
15
- <i></i>
16
- <span class="label"> 纳税人识别号:</span>
17
- <span class="value">{{ invoiceData.sellerId }}</span>
18
- </li>
19
- <li>
20
- <i></i>
21
- <span class="label">地址、电话:</span>
22
- <span class="value">{{ invoiceData.sellerContact }}</span>
23
- </li>
24
- <li>
25
- <i></i>
26
- <span class="label">开户银行及账户:</span>
27
- <span class="value">{{ invoiceData.sellerAccount }}</span>
28
- </li>
29
- </ul>
30
- </div>
31
- </div>
32
- </div>
33
-
34
- <div class="purchaser">
35
- <ul>
36
- <li>
37
- <div class="label">购买方:</div>
38
- <div class="input">{{ invoiceData.payerName }}</div>
39
- </li>
40
- <li>
41
- <div class="label">发票类型:</div>
42
- <div class="input">{{ invoiceData.description }}</div>
43
- </li>
44
- <li>
45
- <div class="label">费用类型:</div>
46
- <div class="input">其他费</div>
47
- </li>
48
- <li>
49
- <div class="label">票面金额:</div>
50
- <div class="input">
51
- {{
52
- invoiceData.priceTaxTotalFigure || invoiceData.noTaxAmountTotal
53
- }}
9
+ <div>
10
+ <Form label-width="65px">
11
+ <CellGroup inset>
12
+ <template #title>
13
+ <div class="Field-title">
14
+ <span class="titleLeft">公司信息</span>
15
+ <span class="titleright">重新查验</span>
54
16
  </div>
55
- </li>
56
- <li>
57
- <div class="label">发票代码:</div>
58
- <div class="input">
59
- <ElInputNumber
60
- :min="0"
61
- :controls="false"
62
- @input="editFlag = true"
63
- v-model.trim="invoiceData.invoiceCode"></ElInputNumber>
17
+ </template>
18
+ <div class="marPX">
19
+ <Field
20
+ autocomplete="off"
21
+ label="销售方"
22
+ placeholder="请输入销售方"
23
+ v-model="formData.sellerReq.sellerName">
24
+ <template #right-icon>
25
+ <div @click="expandObj.showSeller = !expandObj.showSeller">
26
+ <Icon
27
+ name="arrow-down"
28
+ v-if="!expandObj.showSeller"
29
+ color="#969799" />
30
+ <Icon v-else name="arrow-up" color="#969799" />
31
+ </div>
32
+ </template>
33
+ </Field>
34
+ <div v-show="expandObj.showSeller">
35
+ <Field
36
+ autocomplete="off"
37
+ label="纳税人识别号"
38
+ placeholder="请输入纳税人识别号"
39
+ v-model="formData.sellerReq.sellerId" />
40
+ <Field
41
+ autocomplete="off"
42
+ label="地址/电话"
43
+ autosize
44
+ type="textarea"
45
+ placeholder="请输入地址+电话"
46
+ v-model="formData.sellerReq.sellerContact" />
47
+ <!-- <Field
48
+ autocomplete="off"
49
+ label="电话"
50
+ placeholder="请输入电话"
51
+ v-model="formData.sellerReq.sellerName" /> -->
52
+ <Field
53
+ autocomplete="off"
54
+ autosize
55
+ type="textarea"
56
+ label="开户银行/银行账号"
57
+ placeholder="请输入开户银行+银行账户"
58
+ v-model="formData.sellerReq.sellerAccount" />
59
+ <!-- <Field
60
+ autocomplete="off"
61
+ label="银行账号"
62
+ placeholder="请输入银行账号"
63
+ v-model="formData.sellerReq.sellerName" /> -->
64
64
  </div>
65
- </li>
66
- <li>
67
- <div class="label">
68
- <span class="van-field__label--required"></span>发票号码:
65
+ </div>
66
+ <div class="marPX">
67
+ <Field
68
+ autocomplete="off"
69
+ label="购买方"
70
+ placeholder="请输入购买方名称"
71
+ v-model="formData.payerReq.payerName">
72
+ <template #right-icon>
73
+ <div
74
+ @click="expandObj.showPurchaser = !expandObj.showPurchaser">
75
+ <Icon
76
+ name="arrow-down"
77
+ v-if="!expandObj.showPurchaser"
78
+ color="#969799" />
79
+ <Icon v-else name="arrow-up" color="#969799" />
80
+ </div>
81
+ </template>
82
+ </Field>
83
+ <div v-show="expandObj.showPurchaser">
84
+ <Field
85
+ autocomplete="off"
86
+ label="纳税人识别号"
87
+ placeholder="请输入纳税人识别号"
88
+ v-model="formData.payerReq.payerId" />
89
+ <Field
90
+ autocomplete="off"
91
+ label="地址/电话"
92
+ type="textarea"
93
+ placeholder="请输入地址+电话"
94
+ v-model="formData.payerReq.payerContact" />
95
+ <!-- <Field
96
+ autocomplete="off"
97
+ label="电话"
98
+ placeholder="请输入电话"
99
+ v-model="formData.payerReq.sellerName" /> -->
100
+ <Field
101
+ autocomplete="off"
102
+ autosize
103
+ type="textarea"
104
+ label="开户银行/银行账号"
105
+ placeholder="请输入开户银行+银行账户"
106
+ v-model="formData.payerReq.payerAccount" />
107
+ <!-- <Field
108
+ autocomplete="off"
109
+ label="银行账号"
110
+ placeholder="请输入银行账号"
111
+ v-model="formData.payerReq.sellerName" /> -->
69
112
  </div>
70
- <div class="input">
71
- <ElInputNumber
72
- :min="0"
73
- :controls="false"
74
- @input="editFlag = true"
75
- v-model.trim="invoiceData.invoiceNum"></ElInputNumber>
76
- <!-- <input type="text" v-model.trim="invoiceData.invoiceNum" /> -->
77
- <div v-if="showRequiredMsg" class="errColor">
78
- 发票号码不能为空!
79
- </div>
113
+ </div>
114
+ <div class="marPX">
115
+ <Field
116
+ autocomplete="off"
117
+ readonly
118
+ label="发票类型"
119
+ :model-value="props.invoiceData.description" />
120
+ </div>
121
+ <div class="marPX">
122
+ <Cell title="价税合计" :value="computed_amount">
123
+ <template #value>
124
+ <div style="color: #333;font-weight: 400; font-size: 16px;margin-right: 12px;">{{ computed_amount }}</div>
125
+ </template>
126
+ <template #right-icon>
127
+ <div @click="expandObj.showPrice = !expandObj.showPrice">
128
+ <Icon
129
+ name="arrow-down"
130
+ v-if="!expandObj.showPrice"
131
+ color="#969799" />
132
+ <Icon v-else name="arrow-up" color="#969799" />
133
+ </div>
134
+ </template>
135
+ </Cell>
136
+ <div v-show="!expandObj.showPrice">
137
+ <Field>
138
+ <template #input>
139
+ <table>
140
+ <thead>
141
+ <tr>
142
+ <th>商品金额(不含税)</th>
143
+ <th>税率</th>
144
+ <th>税额</th>
145
+ </tr>
146
+ </thead>
147
+ <tbody>
148
+ <tr
149
+ v-for="(item, index) in formData.itemAmountReqs"
150
+ @click="openEditpopUp(item, index)">
151
+ <td>{{ item.itemExTaxAmount }}</td>
152
+ <td>{{ item.itemTaxRate }}</td>
153
+ <td>
154
+ {{
155
+ computedTaxAmount(
156
+ item.itemExTaxAmount,
157
+ item.itemTaxRate
158
+ )
159
+ }}
160
+ </td>
161
+ </tr>
162
+ </tbody>
163
+ </table>
164
+ </template>
165
+ </Field>
80
166
  </div>
81
- </li>
82
- <li>
83
- <div class="label">校验码:</div>
84
- <div class="input">{{ invoiceData.checkCode }}</div>
85
- </li>
86
- <li>
87
- <div class="label">开票日期:</div>
88
- <div class="input">{{ invoiceData.invoiceDate }}</div>
89
- </li>
90
- </ul>
91
- </div>
92
- </div>
93
- <div class="submit">
94
- <span
95
- style="width: 30%; background-color: #07c160; color: #fff"
96
- @click="close"
97
- >返回</span
98
- >
99
- <span @click="submit">保存</span>
167
+ </div>
168
+ <div class="marPX">
169
+ <Field
170
+ autocomplete="off"
171
+ label="发票代码"
172
+ placeholder="请输入发票代码"
173
+ v-model="formData.codeReq.invoiceCode">
174
+ <template #right-icon>
175
+ <div @click="expandObj.invoiceCode = !expandObj.invoiceCode">
176
+ <Icon
177
+ name="arrow-down"
178
+ v-if="!expandObj.invoiceCode"
179
+ color="#969799" />
180
+ <Icon v-else name="arrow-up" color="#969799" />
181
+ </div>
182
+ </template>
183
+ </Field>
184
+ <div v-show="expandObj.invoiceCode">
185
+ <Field
186
+ autocomplete="off"
187
+ label="发票号码"
188
+ placeholder="请输入发票号码"
189
+ v-model="formData.codeReq.invoiceNum" />
190
+ <Field
191
+ autocomplete="off"
192
+ label="校验码"
193
+ placeholder="请输入校验码"
194
+ v-model="formData.codeReq.checkCode" />
195
+ </div>
196
+ </div>
197
+ <div class="marPX">
198
+ <Field
199
+ autocomplete="off"
200
+ label="开票日期"
201
+ readonly
202
+ v-model="props.invoiceData.invoiceDate" />
203
+ </div>
204
+ <div class="marPX">
205
+ <Field
206
+ autocomplete="off"
207
+ label="查验状态"
208
+ readonly
209
+ :model-value="const_realStatus[props.invoiceData.realStatus]" />
210
+ </div>
211
+ </CellGroup>
212
+ <div class="submit">
213
+ <span
214
+ style="width: 30%; background-color: #07c160; color: #fff"
215
+ @click="close">
216
+ 返回
217
+ </span>
218
+ <span @click="submit">保存</span>
219
+ </div>
220
+ </Form>
100
221
  </div>
101
222
  </div>
223
+ <ActionSheet v-model:show="showEdit" :title="editTitle(titleIndex)">
224
+ <div class="content">
225
+ <Form ref="REF_editForm">
226
+ <Field
227
+ autocomplete="off"
228
+ @blur="blurInput($event, 'itemExTaxAmount')"
229
+ label="不含税金额"
230
+ v-model="activeRow.itemExTaxAmount" />
231
+ <Field
232
+ autocomplete="off"
233
+ label="税率"
234
+ @blur="blurInput($event, 'itemTaxRate')"
235
+ v-model="activeRow.itemTaxRate">
236
+ <template #right-icon>%</template>
237
+ </Field>
238
+ <Cell title="税额" :value="rateAmount"> </Cell>
239
+ </Form>
240
+ <div class="btn">
241
+ <Button type="primary" @click="confirmEdit">确定</Button>
242
+ </div>
243
+ </div>
244
+ </ActionSheet>
102
245
  <Overlay
103
246
  style="
104
247
  display: flex;
@@ -113,27 +256,58 @@
113
256
  <script setup lang="ts">
114
257
  import { ref } from 'vue'
115
258
  import '@/utils/disableZoom'
116
- import { __updateInvoice } from '@/api/invoice'
259
+ import { __updateInvoiceData } from '@/api/invoice'
117
260
  import {
118
261
  showToast,
119
262
  Overlay,
120
263
  Loading,
121
264
  showFailToast,
122
265
  showImagePreview,
266
+ CellGroup,
267
+ Field,
268
+ Form,
269
+ Icon,
270
+ Button,
271
+ ActionSheet,
272
+ Cell,
123
273
  } from 'vant'
124
- import { ElInputNumber } from 'element-plus'
125
- const { ids, invoiceData } = defineProps({
126
- ids: {
127
- type: Object,
128
- required: true,
274
+ import { onMounted } from 'vue'
275
+ import { const_realStatus } from '../InvoiceList/const'
276
+ import { RowAttribute } from './const'
277
+ import { filterNumber } from '@/utils/number'
278
+ import { computed } from 'vue'
279
+ import Decimal from 'decimal.js'
280
+ const props = defineProps(['ids', 'invoiceData'])
281
+ const formData = ref({
282
+ codeReq: {
283
+ invoiceCode: '',
284
+ invoiceNum: '',
285
+ checkCode: '',
286
+ },
287
+ itemAmountReqs: [
288
+ {
289
+ detailCode: '',
290
+ itemExTaxAmount: 0,
291
+ itemTaxRate: 0,
292
+ },
293
+ ],
294
+ payerReq: {
295
+ payerAccount: '',
296
+ payerContact: '',
297
+ payerId: '',
298
+ payerName: '',
129
299
  },
130
- invoiceData: {
131
- type: Object,
132
- required: true,
300
+ sellerReq: {
301
+ sellerAccount: '',
302
+ sellerContact: '',
303
+ sellerId: '',
304
+ sellerName: '',
133
305
  },
306
+ taskId: '',
134
307
  })
135
308
  const emit = defineEmits(['saveSuccess'])
136
309
  document.title = '发票信息'
310
+ const expandObj: any = ref({})
137
311
  const showRequiredMsg = ref(false)
138
312
  // const modules = ref([Pagination])
139
313
  const showLoading = ref(false)
@@ -141,27 +315,13 @@ const close = () => {
141
315
  emit('saveSuccess')
142
316
  }
143
317
  const openPreViewImg = () => {
144
- showImagePreview([invoiceData.attachmentLink])
318
+ showImagePreview([props.invoiceData.attachmentLink])
145
319
  }
146
- const editFlag = ref(false)
320
+
147
321
  const submit = async () => {
148
- if (!editFlag.value) {
149
- emit('saveSuccess')
150
- return
151
- }
152
- if (!invoiceData.invoiceNum) {
153
- showRequiredMsg.value = true
154
- return
155
- } else {
156
- showRequiredMsg.value = false
157
- }
158
322
  showLoading.value = true
159
323
  try {
160
- const res: any = await __updateInvoice({
161
- ...ids,
162
- invoiceNum: invoiceData.invoiceNum,
163
- invoiceCode: invoiceData.invoiceCode,
164
- })
324
+ const res: any = await __updateInvoiceData(formData.value)
165
325
  if (res.code === 200) {
166
326
  showToast({
167
327
  type: 'success',
@@ -175,37 +335,122 @@ const submit = async () => {
175
335
  }
176
336
  showLoading.value = false
177
337
  }
338
+ const initData = () => {
339
+ console.log(props.invoiceData)
340
+ // 销售方数据回显
341
+ formData.value.sellerReq.sellerName = props.invoiceData.sellerName
342
+ formData.value.sellerReq.sellerAccount = props.invoiceData.sellerAccount
343
+ formData.value.sellerReq.sellerContact = props.invoiceData.sellerContact
344
+ formData.value.sellerReq.sellerId = props.invoiceData.sellerId
345
+ // 购买方数据回显
346
+ formData.value.payerReq.payerAccount = props.invoiceData.payerAccount
347
+ formData.value.payerReq.payerContact = props.invoiceData.payerContact
348
+ formData.value.payerReq.payerName = props.invoiceData.payerName
349
+ formData.value.payerReq.payerId = props.invoiceData.payerId
350
+ // 发票代码回显
351
+ formData.value.codeReq.invoiceCode = props.invoiceData.invoiceCode
352
+ formData.value.codeReq.invoiceNum = props.invoiceData.invoiceNum
353
+ formData.value.codeReq.checkCode = props.invoiceData.checkCode
354
+ formData.value.taskId = props.invoiceData.taskId
355
+ // 金额数据回显
356
+ formData.value.itemAmountReqs = JSON.parse(
357
+ JSON.stringify(props.invoiceData.deatis)
358
+ ).map((item: any) => {
359
+ return {
360
+ detailCode: item.code,
361
+ itemExTaxAmount: item.itemExTaxAmount,
362
+ itemTaxRate: item.itemTaxRate.replace(/%/g, ''),
363
+ }
364
+ })
365
+ }
366
+ const showEdit = ref(false)
367
+ const activeRow = ref<RowAttribute | any>({})
368
+ const titleIndex = ref<number>(0)
369
+ const editTitle = (index: number) => {
370
+ return `第${index + 1}行金额`
371
+ }
372
+ const openEditpopUp = (row: RowAttribute, index: number) => {
373
+ activeRow.value = JSON.parse(JSON.stringify(row))
374
+ activeRow.value.itemTaxRate = filterNumber(activeRow.value.itemTaxRate)
375
+ titleIndex.value = index
376
+ showEdit.value = true
377
+ }
378
+ const confirmEdit = () => {
379
+ formData.value.itemAmountReqs[titleIndex.value].detailCode =
380
+ activeRow.value.detailCode
381
+ formData.value.itemAmountReqs[titleIndex.value].itemExTaxAmount =
382
+ activeRow.value.itemExTaxAmount
383
+ formData.value.itemAmountReqs[titleIndex.value].itemTaxRate =
384
+ activeRow.value.itemTaxRate
385
+ showEdit.value = false
386
+ }
387
+ const blurInput = (e: any, key: any) => {
388
+ let value = activeRow.value[key]
389
+ activeRow.value[key] = filterNumber(value)
390
+ }
391
+
392
+ const computed_amount = computed(() => {
393
+ let count = new Decimal(0)
394
+ formData.value.itemAmountReqs.forEach((item) => {
395
+ count = count.plus(new Decimal(item.itemExTaxAmount))
396
+ })
397
+ return count.toFixed(2)
398
+ })
399
+ const rateAmount = computed(() => {
400
+ return new Decimal(filterNumber(Number(activeRow.value.itemExTaxAmount)))
401
+ .times(new Decimal(filterNumber(activeRow.value.itemTaxRate / 100)))
402
+ .toFixed(2)
403
+ })
404
+ const computedTaxAmount = (ExTaxAmount: any, TaxRate: any) => {
405
+ let rate: any = TaxRate + ''
406
+ return new Decimal(filterNumber(ExTaxAmount))
407
+ .times(new Decimal(filterNumber(rate / 100)))
408
+ .toFixed(2)
409
+ }
410
+ onMounted(() => {
411
+ initData()
412
+ })
178
413
  </script>
179
414
 
180
415
  <style lang="scss" scoped>
181
- ::v-deep {
182
- .el-input-number {
183
- width: 100%;
184
- }
185
- .el-input {
186
- .el-input__wrapper {
187
- width: 100%;
188
- padding: 0 !important;
189
- box-shadow: none;
416
+ .content {
417
+ background-color: #f7f8fa;
418
+ height: 200px;
419
+ :deep(.van-field__value) {
420
+ border: 1px solid #2196f3;
421
+ border-radius: 4px;
422
+ input {
423
+ padding-left: 12px;
190
424
  }
191
- .el-input__inner {
192
- width: 100%;
193
- text-align: left;
194
- box-shadow: none;
195
- padding: 0 !important;
425
+ }
426
+ .btn {
427
+ display: flex;
428
+ justify-content: space-between;
429
+ gap: 12px;
430
+ padding: 12px 16px 0;
431
+ button {
432
+ flex: 1;
433
+ border-radius: 25px;
196
434
  }
197
435
  }
198
436
  }
199
- * {
200
- padding: 0;
201
- margin: 0;
202
- box-sizing: border-box;
437
+ :deep(.van-cell-group) {
438
+ background-color: transparent;
439
+ .van-field__label {
440
+ color: #333333;
441
+ font-size: 16px;
442
+ font-weight: 400;
443
+ }
444
+ .van-field__control {
445
+ font-size: 16px;
446
+ }
203
447
  }
448
+
204
449
  .Invoice {
205
450
  padding-bottom: 100px;
206
451
  width: 100%;
207
452
  min-height: 100%;
208
- background-color: #f3f4f6;
453
+ background-color: #f2f4f7;
209
454
  .top {
210
455
  width: 100%;
211
456
  padding: 12px 4px;
@@ -216,102 +461,55 @@ const submit = async () => {
216
461
  }
217
462
  }
218
463
 
219
- .company {
220
- height: inherit;
221
- padding: 0 12px;
222
- background-color: #fff;
223
- .title {
224
- padding: 18px 0;
464
+ .Field-title {
465
+ display: flex;
466
+ justify-content: space-between;
467
+ align-items: center;
468
+ .titleLeft {
225
469
  font-size: 16px;
226
- font-weight: 500;
227
- display: flex;
228
- align-items: center;
229
- border-bottom: 1px dashed #e8e8e8;
230
- margin-bottom: 18px;
231
- i {
470
+ color: #333333;
471
+ font-family: PingFangSC-Medium, PingFang SC;
472
+ font-weight: 600;
473
+ &::before {
474
+ margin-right: 4px;
232
475
  display: inline-block;
476
+ content: '';
233
477
  width: 4px;
234
478
  height: 14px;
235
- background: #266fe8;
479
+ background-color: #266fe8;
236
480
  border-radius: 2px;
237
481
  }
238
-
239
- span {
240
- font-size: 16px;
241
- padding-left: 8px;
242
- }
243
482
  }
244
- .cardText {
245
- .card {
246
- margin-top: 8px;
247
- border-radius: 4px;
248
- background-color: #f6f6f6;
249
- font-size: 14px;
250
- .companyName {
251
- padding: 15px;
252
- }
253
- .sellerInformation {
254
- padding-left: 12px;
255
- padding-bottom: 20px;
256
- li {
257
- list-style: none;
258
- margin-bottom: 12px;
259
- display: flex;
260
- align-items: center;
261
- i {
262
- width: 4px;
263
- height: 4px;
264
- border-radius: 50%;
265
- background-color: #266fe8;
266
- }
267
- .label {
268
- width: 120px;
269
- margin-left: 12px;
270
- white-space: nowrap;
271
- }
272
- .value {
273
- flex: 1;
274
- }
275
- }
276
- }
277
- }
483
+ .titleright {
484
+ font-size: 14px;
485
+ color: #266fe8;
278
486
  }
279
- .purchaser {
280
- ul {
281
- li {
282
- display: flex;
283
- font-size: 16px;
284
- height: 50px;
285
- align-items: center;
286
- gap: 45px;
287
- .label {
288
- width: 80px;
289
- white-space: nowrap;
290
- position: relative;
291
- .van-field__label--required {
292
- position: absolute;
293
- top: 0;
294
- left: -8px;
295
- }
296
- }
297
- .input {
298
- flex-grow: 1;
299
- color: #999999;
487
+ }
488
+ .marPX {
489
+ margin-bottom: 12px;
490
+ }
300
491
 
301
- input {
302
- width: 100%;
303
- color: #999999;
304
- outline: none;
305
- font-size: 16px;
306
- border: none;
307
- }
308
- .errColor {
309
- color: red;
310
- font-size: 12px;
311
- }
312
- }
313
- }
314
- }
492
+ table {
493
+ background-color: #fff;
494
+ border-radius: 4px;
495
+ border: 1px solid #f2f4f7;
496
+ width: 100%;
497
+ border-spacing: 0;
498
+ }
499
+ thead {
500
+ background-color: #f2f4f7;
501
+ font-size: 12px;
502
+ color: #666666;
503
+ th {
504
+ padding: 12px 0;
505
+ text-align: center;
506
+ }
507
+ }
508
+ tbody {
509
+ td {
510
+ text-align: center;
511
+ padding: 10px 0;
512
+ white-space: nowrap;
315
513
  }
316
514
  }
317
515
  .submit {