kts-component-invoice-operate 3.1.2 → 3.1.4

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.
Files changed (117) hide show
  1. package/.dumi/theme/builtins/API.tsx +66 -66
  2. package/.editorconfig +16 -16
  3. package/.fatherrc.ts +4 -4
  4. package/.prettierignore +7 -7
  5. package/.prettierrc +11 -11
  6. package/.umirc.ts +8 -8
  7. package/README.md +5 -5
  8. package/dist/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/IGood/index.d.ts +2 -2
  9. package/dist/Invoice/ui/GoodsList/hook/useColumns/autoFillFn/index.d.ts +1 -1
  10. package/dist/index.esm.js +2715 -3859
  11. package/dist/index.js +2715 -3859
  12. package/docs/index.md +5 -5
  13. package/docs-dist/umi.js +1 -1
  14. package/index.html +12 -12
  15. package/package.json +59 -59
  16. package/src/Invoice/InvoiceController/InvoiceControllerForm/index.ts +94 -94
  17. package/src/Invoice/InvoiceController/InvoiceControllerState/BuyerState/index.tsx +88 -88
  18. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/EndowCode/index.tsx +90 -90
  19. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/IColumnsReplenish/index.ts +10 -10
  20. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/IGood/index.ts +72 -72
  21. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/ImportGoods/index.ts +80 -80
  22. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/LineAttributeType/index.ts +5 -5
  23. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/ProductComparison/index.ts +9 -9
  24. package/src/Invoice/InvoiceController/InvoiceControllerState/GoodsListState/index.ts +88 -88
  25. package/src/Invoice/InvoiceController/InvoiceControllerState/index.ts +42 -42
  26. package/src/Invoice/InvoiceController/fns/addGood.ts +11 -11
  27. package/src/Invoice/InvoiceController/fns/addGoodDiscount.ts +125 -125
  28. package/src/Invoice/InvoiceController/fns/delGood.ts +43 -43
  29. package/src/Invoice/InvoiceController/fns/getGoodsSearch.ts +23 -23
  30. package/src/Invoice/InvoiceController/fns/saveEditGood.ts +23 -23
  31. package/src/Invoice/InvoiceController/fns/setEditGood.ts +16 -16
  32. package/src/Invoice/InvoiceController/fns/setGoods.ts +10 -10
  33. package/src/Invoice/InvoiceController/fns/updateInvoiceNo.ts +8 -8
  34. package/src/Invoice/InvoiceController/index.ts +61 -61
  35. package/src/Invoice/_test/buyerNameSearch/index.tsx +41 -41
  36. package/src/Invoice/_test/deduction/index.tsx +935 -935
  37. package/src/Invoice/_test/draft/index.tsx +40 -40
  38. package/src/Invoice/_test/easiest/index.tsx +5 -5
  39. package/src/Invoice/_test/endowCode/index.tsx +1095 -1095
  40. package/src/Invoice/_test/goodsMenuExpand/index.tsx +32 -32
  41. package/src/Invoice/_test/importBuyer/index.tsx +74 -74
  42. package/src/Invoice/_test/importGoods/index.tsx +515 -515
  43. package/src/Invoice/_test/invoiceType/index.tsx +59 -59
  44. package/src/Invoice/_test/isInvoiceNo/index.tsx +12 -12
  45. package/src/Invoice/_test/replaceHead/index.tsx +22 -22
  46. package/src/Invoice/_test/retrieveData/index.tsx +22 -22
  47. package/src/Invoice/_test/seller/index.tsx +28 -28
  48. package/src/Invoice/_test/setDataSource/index.tsx +22 -22
  49. package/src/Invoice/_test/unit/index.tsx +19 -19
  50. package/src/Invoice/index.less +12 -12
  51. package/src/Invoice/index.md +53 -53
  52. package/src/Invoice/index.tsx +104 -104
  53. package/src/Invoice/tools/calculate/index.ts +97 -97
  54. package/src/Invoice/tools/coolingFn/index.ts +17 -17
  55. package/src/Invoice/tools/evaluate/index.ts +7 -7
  56. package/src/Invoice/tools/idGenerator/index.ts +2 -2
  57. package/src/Invoice/tools/itemName/index.ts +46 -46
  58. package/src/Invoice/tools/lazyFn/index.ts +19 -19
  59. package/src/Invoice/tools/strringFn/index.ts +40 -40
  60. package/src/Invoice/ui/AddComparisonDrawer/index.tsx +149 -149
  61. package/src/Invoice/ui/Buyer/index.less +219 -219
  62. package/src/Invoice/ui/Buyer/index.tsx +114 -114
  63. package/src/Invoice/ui/Buyer/ui/BuyerNameInput/index.tsx +166 -166
  64. package/src/Invoice/ui/Buyer/ui/ImportBuyerButton/index.tsx +21 -21
  65. package/src/Invoice/ui/EndowCodeDrawer/index.less +8 -8
  66. package/src/Invoice/ui/EndowCodeDrawer/index.tsx +441 -441
  67. package/src/Invoice/ui/GoodsList/hook/useColumns/autoFillFn/index.ts +490 -490
  68. package/src/Invoice/ui/GoodsList/hook/useColumns/index.tsx +603 -603
  69. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/ItemNameInput/index.less +9 -9
  70. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/ItemNameInput/index.tsx +34 -34
  71. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowEditButton/index.tsx +30 -30
  72. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/hook/_useAddComparison/index.tsx +43 -43
  73. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/hook/useAddDiscount/index.tsx +76 -76
  74. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/hook/useDelItem/index.tsx +35 -35
  75. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/hook/useEndowCode/index.tsx +34 -34
  76. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/index.less +13 -13
  77. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowMenu/index.tsx +98 -98
  78. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/RowSaveButton/index.tsx +14 -14
  79. package/src/Invoice/ui/GoodsList/hook/useColumns/ui/TitleText/index.tsx +20 -20
  80. package/src/Invoice/ui/GoodsList/hook/useDeduction/index.tsx +24 -24
  81. package/src/Invoice/ui/GoodsList/hook/useOnRow/index.tsx +39 -39
  82. package/src/Invoice/ui/GoodsList/hook/useRowSelection/index.tsx +111 -111
  83. package/src/Invoice/ui/GoodsList/hook/useToGenerateId/index.ts +8 -8
  84. package/src/Invoice/ui/GoodsList/hook/useWindowClick/index.tsx +23 -23
  85. package/src/Invoice/ui/GoodsList/index.less +170 -170
  86. package/src/Invoice/ui/GoodsList/index.tsx +177 -177
  87. package/src/Invoice/ui/GoodsList/ui/AddRowButton/index.tsx +61 -61
  88. package/src/Invoice/ui/GoodsList/ui/BulkMenu/hooks/useAddDiscountRowButton/index.less +21 -21
  89. package/src/Invoice/ui/GoodsList/ui/BulkMenu/hooks/useAddDiscountRowButton/index.tsx +244 -244
  90. package/src/Invoice/ui/GoodsList/ui/BulkMenu/hooks/useCommodityComparisonButton/index.tsx +75 -75
  91. package/src/Invoice/ui/GoodsList/ui/BulkMenu/hooks/useDelRowButton/index.tsx +66 -66
  92. package/src/Invoice/ui/GoodsList/ui/BulkMenu/hooks/useEndowCodeButton/index.tsx +58 -58
  93. package/src/Invoice/ui/GoodsList/ui/BulkMenu/index.tsx +37 -37
  94. package/src/Invoice/ui/GoodsList/ui/DescribeSwitch/index.tsx +36 -36
  95. package/src/Invoice/ui/GoodsList/ui/Search/index.less +10 -10
  96. package/src/Invoice/ui/GoodsList/ui/Search/index.tsx +50 -50
  97. package/src/Invoice/ui/GoodsList/ui/Statistics/index.less +18 -18
  98. package/src/Invoice/ui/GoodsList/ui/Statistics/index.tsx +109 -109
  99. package/src/Invoice/ui/GoodsList/ui/TableRow/index.tsx +27 -27
  100. package/src/Invoice/ui/GoodsList/ui/TableVirtual/index.less +38 -38
  101. package/src/Invoice/ui/GoodsList/ui/TableVirtual/index.tsx +105 -105
  102. package/src/Invoice/ui/GoodsList/ui/TableVirtual.o/index.less +44 -44
  103. package/src/Invoice/ui/GoodsList/ui/TableVirtual.o/index.tsx +96 -96
  104. package/src/Invoice/ui/GoodsList/ui/TaxIncludedSwitch/index.tsx +30 -30
  105. package/src/Invoice/ui/ImportBuyerDrawer/index.tsx +75 -75
  106. package/src/Invoice/ui/ImportGoodsDrawer/index.tsx +174 -174
  107. package/src/Invoice/ui/InvoiceHeader/index.less +68 -68
  108. package/src/Invoice/ui/InvoiceHeader/index.tsx +246 -246
  109. package/src/Invoice/ui/Seller/index.less +113 -113
  110. package/src/Invoice/ui/Seller/index.tsx +98 -98
  111. package/src/Invoice/ui/Sign/index.less +14 -14
  112. package/src/Invoice/ui/Sign/index.tsx +71 -71
  113. package/src/index.ts +6 -6
  114. package/tsconfig.json +31 -31
  115. package/typings.d.ts +3 -3
  116. package/yarn.e.lock +14331 -14331
  117. package/yarn.o.lock +14800 -14800
@@ -1,604 +1,604 @@
1
- import React from 'react';
2
- import { Form, AutoComplete, Select, Button, Input, Spin, Tooltip } from 'kts-components-antd-x3';
3
- import { InputProps } from 'kts-components-antd-x3/lib/input';
4
- import { WrappedFormUtils } from 'kts-components-antd-x3/lib/form/Form';
5
- import { IGood } from '../../../../InvoiceController';
6
- import Invoice from '../../../../';
7
- import RowMenu from './ui/RowMenu';
8
- import TitleText from './ui/TitleText';
9
- import ItemNameInput from './ui/ItemNameInput';
10
- import {
11
- onChangeQuantity,
12
- onChangePriceIncludeTax,
13
- onChangePriceExcludeTax,
14
- onChangeLineAmountIncludeTax,
15
- onChangeLineAmountExcludeTax,
16
- onChangeTaxRate,
17
- onChangeItemName,
18
- } from './autoFillFn';
19
-
20
- export default (form: WrappedFormUtils) => {
21
- const { getFieldDecorator, getFieldValue } = form;
22
-
23
- const controller = Invoice.useInvoiceController();
24
-
25
- /** 是否含税 */
26
- const isTaxIncluded = controller.useMemo(e => e.goodsListState.isTaxIncluded, []);
27
-
28
- /** 组件模式 */
29
- const model = controller.useMemo(e => e.model, []);
30
-
31
- /** 是否显示我方 */
32
- const isMyShow = controller.useMemo(e => e.goodsListState.isMyShow, []);
33
-
34
- /** 正在编辑的货物 */
35
- const editGood = controller.useMemo((e) => e.goodsListState.editGood, []);
36
-
37
- /** 搜索条件 */
38
- const searchValue = controller.useMemo((e) => e.goodsListState.searchValue, []);
39
-
40
- /** 税率列表 */
41
- const taxRateList = controller.useMemo((e) => e.goodsListState.taxRateList, []);
42
-
43
- /** 单位列表 */
44
- const unitList = controller.useMemo((e) => e.goodsListState.unitList, []);
45
-
46
- /** 商品表格补充配置 */
47
- const columnsReplenish = controller.useMemo((e) => e.goodsListState.columnsReplenish, []);
48
-
49
- /** 扣除额 */
50
- const deduction = controller.useMemo((e) => e.goodsListState.deduction, []);
51
-
52
- /** 计算中启动字段 */
53
- const changeField = controller.useMemo((e) => e.calculating, []);
54
-
55
- /** 计算中启动字段 */
56
- const setChangeField = React.useCallback((value: string) => controller.run(async s => { s.calculating = value }), []);
57
-
58
- /** 获取补充校验规则 */
59
- const getReplenishRules = React.useCallback((id: string) => {
60
- return columnsReplenish[id] ? columnsReplenish[id].rules || [] : []
61
- }, [columnsReplenish])
62
-
63
- /** 表头 */
64
- const columns = React.useMemo(() => {
65
- return [
66
- {
67
- title: '序号',
68
- key: 'serialNo',
69
- dataIndex: 'serialNo',
70
- width: 50,
71
- render: (e: number) => <span style={{ padding: '0 10px' }}>{e}</span>,
72
- },
73
- {
74
- title: <TitleText required >项目名称</TitleText>,
75
- key: 'itemName',
76
- render: (_: string, record: IGood) => {
77
- if (editGood?.$index === record.$index) {
78
- return (
79
- <Form.Item>
80
- <div style={{ display: 'flex' }} >
81
- {getFieldDecorator('itemName', {
82
- initialValue: isMyShow ? record.itemNameSelf : record.itemName,
83
- rules: [
84
- ...getReplenishRules('itemName'),
85
- {
86
- validator: async (_, __, callback) => {
87
- await controller.wait();
88
- const value = controller.state.goodsListState.editGood;
89
- if (!value?.itemName && !value?.itemNameSelf) {
90
- callback('货物名称不能为空');
91
- } else {
92
- return;
93
- }
94
- }
95
- }
96
- ]
97
- })(
98
- <ItemNameInput
99
- onChange={() => {
100
- onChangeItemName(controller, form, record);
101
- }}
102
- />
103
- )}
104
- <div className="kts-invoice-operate-goods-list-able-list-itemName-import">
105
- {controller.getGoodsList && model !== 'readOnly' && (
106
- <Tooltip title="点击从商品管理中添加商品信息">
107
- <Button
108
- onClick={controller.pipeline(async s => { s.goodsListState.importGoods.isVisibleDrawer = true })}
109
- type="link"
110
- icon="plus-circle"
111
- />
112
- </Tooltip>
113
- )}
114
- </div>
115
- </div>
116
- </Form.Item>
117
- );
118
- } else {
119
- return (
120
- <MyItemNameDiv
121
- valueT={formatSearch(record.itemNameSelf, searchValue)}
122
- valueF={formatSearch(record.itemName, searchValue)}
123
- isMyShow={isMyShow}
124
- />
125
- )
126
- }
127
- },
128
- },
129
- {
130
- title: <TitleText rules={columnsReplenish['itemModelName']?.rules} >货物规格型号</TitleText>,
131
- key: 'itemModelName',
132
- width: 119,
133
- render: (_: string, record: IGood) => {
134
- if (editGood?.$index === record.$index) {
135
- return (
136
- <Form.Item>
137
- {getFieldDecorator('itemModelName', {
138
- initialValue: isMyShow ? editGood.itemModelNameSelf : editGood.itemModelName,
139
- rules: getReplenishRules('itemModelName'),
140
- })(
141
- <MyInput
142
- onChange={async () => {
143
- await controller.wait()
144
- const key = isMyShow ? 'itemModelNameSelf' : 'itemModelName';
145
- const value = {} as any;
146
- value[key] = form.getFieldsValue().itemModelName;
147
- controller.setEditGood(value);
148
- }}
149
- />,
150
- )}
151
- </Form.Item>
152
- );
153
- } else {
154
- return (
155
- <MyItemNameDiv
156
- valueT={formatSearch(record.itemModelNameSelf, searchValue)}
157
- valueF={formatSearch(record.itemModelName, searchValue)}
158
- isMyShow={isMyShow}
159
- />
160
- )
161
- }
162
- },
163
- },
164
- {
165
- title: <TitleText rules={columnsReplenish['unit']?.rules} >单位</TitleText>,
166
- key: 'unit',
167
- width: 70,
168
- render: (_: string, record: IGood) => {
169
- if (editGood?.$index === record.$index) {
170
- return (
171
- <Form.Item>
172
- {getFieldDecorator('unit', {
173
- initialValue: editGood.unit,
174
- rules: getReplenishRules('unit'),
175
- })(
176
- <AutoComplete
177
- style={{ width: '100%' }}
178
- dataSource={unitList}
179
- onChange={async () => {
180
- await controller.wait()
181
- // const key = isMyShow ? 'unit' : 'unitOther';
182
- // const value = {} as any;
183
- // value[key] = form.getFieldsValue().unit;
184
- controller.setEditGood({ unit: form.getFieldsValue().unit });
185
- }}
186
- />,
187
- )}
188
- </Form.Item>
189
- );
190
- } else {
191
- return <span style={{ padding: '0 10px' }}>{record.unit}</span>;
192
- }
193
- },
194
- },
195
- {
196
- title: <TitleText rules={columnsReplenish['quantity']?.rules} >数量</TitleText>,
197
- dataIndex: 'quantity',
198
- key: 'quantity',
199
- align: 'right',
200
- width: 149,
201
- render: (value: string, record: IGood) => {
202
- if (editGood?.$index === record.$index) {
203
- return (
204
- <Form.Item>
205
- {getFieldDecorator('quantity', {
206
- initialValue: editGood.quantity,
207
- rules: [
208
- ...getReplenishRules('quantity'),
209
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '数量必须为数字' },
210
- {
211
- validator: async (_, value, callback) => {
212
- await controller.wait();
213
- const isvalue = !!value || value === 0;
214
- const isPrice = !!getFieldValue(isTaxIncluded ? 'priceIncludeTax' : 'priceExcludeTax') || getFieldValue(isTaxIncluded ? 'priceIncludeTax' : 'priceExcludeTax') === 0;
215
- if (isvalue || isPrice === isvalue) return;
216
- callback('请输入数量');
217
- }
218
- }
219
- ],
220
- })(
221
- <MyInput
222
- style={{ textAlign: 'right' }}
223
- maxLength={16}
224
- loading={isCipher(changeField, "quantity")}
225
- onChange={async () => {
226
- setChangeField('quantity');
227
- await onChangeQuantity(controller, form, record);
228
- }}
229
- />,
230
- )}
231
- </Form.Item>
232
- );
233
- } else {
234
- return <span style={{ padding: '0 10px' }}>{value}</span>;
235
- }
236
- },
237
- },
238
- {
239
- title: <TitleText rules={columnsReplenish['priceIncludeTax']?.rules} >单价(含税)</TitleText>,
240
- dataIndex: 'priceIncludeTax',
241
- key: 'priceIncludeTax',
242
- align: 'right',
243
- width: 149,
244
- render: (value: string, record: IGood) => {
245
- if (editGood?.$index === record.$index) {
246
- return (
247
- <Form.Item>
248
- {getFieldDecorator('priceIncludeTax', {
249
- initialValue: editGood.priceIncludeTax,
250
- rules: [
251
- ...getReplenishRules('priceIncludeTax'),
252
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '单价必须为数字' },
253
- {
254
- validator: async (_, value, callback) => {
255
- await controller.wait();
256
- const isQuantity = !!getFieldValue('quantity') || getFieldValue('quantity') === 0;
257
- const isvalue = !!value || value === 0;
258
- if (isvalue || isQuantity === isvalue) return;
259
- callback('请输入单价');
260
- }
261
- }
262
- ],
263
- })(
264
- <MyInput
265
- style={{ textAlign: 'right' }}
266
- maxLength={16}
267
- loading={isCipher(changeField, 'priceIncludeTax')}
268
- onChange={() => {
269
- setChangeField('priceIncludeTax');
270
- onChangePriceIncludeTax(controller, form, record);
271
- }}
272
- />,
273
- )}
274
- </Form.Item>
275
- );
276
- } else {
277
- return <span style={{ padding: '0 10px' }}>{value}</span>;
278
- }
279
- },
280
- },
281
- {
282
- title: <TitleText rules={columnsReplenish['priceExcludeTax']?.rules} >单价(不含税)</TitleText>,
283
- dataIndex: 'priceExcludeTax',
284
- key: 'priceExcludeTax',
285
- align: 'right',
286
- width: 149,
287
- render: (value: string, record: IGood) => {
288
- if (editGood?.$index === record.$index) {
289
- return (
290
- <Form.Item>
291
- {getFieldDecorator('priceExcludeTax', {
292
- initialValue: editGood.priceExcludeTax,
293
- rules: [
294
- ...getReplenishRules('priceExcludeTax'),
295
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '单价必须为数字' },
296
- {
297
- validator: async (_, value, callback) => {
298
- await controller.wait();
299
- const isQuantity = !!getFieldValue('quantity') || getFieldValue('quantity') === 0;
300
- const isvalue = !!value || value === 0;
301
- if (isvalue || isQuantity === isvalue) return;
302
- callback('请输入单价');
303
- }
304
- }
305
- ],
306
- })(
307
- <MyInput
308
- style={{ textAlign: 'right' }}
309
- maxLength={16}
310
- loading={isCipher(changeField, 'priceExcludeTax')}
311
- onChange={() => {
312
- setChangeField('priceExcludeTax');
313
- onChangePriceExcludeTax(controller, form, record);
314
- }}
315
- />,
316
- )}
317
- </Form.Item>
318
- );
319
- } else {
320
- return <span style={{ padding: '0 10px' }}>{value}</span>;
321
- }
322
- },
323
- },
324
- {
325
- title: <TitleText required >金额(含税)</TitleText>,
326
- dataIndex: 'lineAmountIncludeTax',
327
- key: 'lineAmountIncludeTax',
328
- width: 119,
329
- align: 'right',
330
- render: (value: string, record: IGood) => {
331
- if (editGood?.$index === record.$index) {
332
- return (
333
- <Form.Item>
334
- {getFieldDecorator('lineAmountIncludeTax', {
335
- initialValue: editGood.lineAmountIncludeTax,
336
- rules: [
337
- ...getReplenishRules('lineAmountIncludeTax'),
338
- { required: true, message: '金额不能为空' },
339
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '金额必须为数字' },
340
- {
341
- validator: async (_, value, callback) => {
342
- if (`${value}`.split('.')[0].length > 9) {
343
- callback('金额整数部分不能大于9位,小数点后最多2位');
344
- }
345
- }
346
- },
347
- {
348
- validator: async (_, value, callback) => {
349
- if (deduction && parseFloat(value) <= deduction) {
350
- callback('扣除额不能大于等于价税合计');
351
- }
352
- }
353
- },
354
- ],
355
- })(
356
- <MyInput
357
- style={{ textAlign: 'right' }}
358
- loading={isCipher(changeField, 'lineAmountIncludeTax')}
359
- onChange={() => {
360
- setChangeField('lineAmountIncludeTax');
361
- onChangeLineAmountIncludeTax(controller, form, record);
362
- }}
363
- />,
364
- )}
365
- </Form.Item>
366
- );
367
- } else {
368
- return <span style={{ padding: '0 10px' }}>{formatSearch(parseFloat(value).toFixed(2), searchValue)}</span>;
369
- }
370
- },
371
- },
372
- {
373
- title: <TitleText required >金额(不含税)</TitleText>,
374
- dataIndex: 'lineAmountExcludeTax',
375
- key: 'lineAmountExcludeTax',
376
- align: 'right',
377
- width: 119,
378
- render: (value: string, record: IGood) => {
379
- if (editGood?.$index === record.$index) {
380
- return (
381
- <Form.Item>
382
- {getFieldDecorator('lineAmountExcludeTax', {
383
- initialValue: editGood.lineAmountExcludeTax,
384
- rules: [
385
- ...getReplenishRules('lineAmountExcludeTax'),
386
- { required: true, message: '金额不能为空' },
387
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '金额必须为数字' },
388
- {
389
- validator: async (_, value: string, callback) => {
390
- if (`${value}`.split('.')[0].length > 9) {
391
- callback('金额整数部分不能大于9位,小数点后最多2位');
392
- }
393
- }
394
- },
395
- ],
396
- })(
397
- <MyInput
398
- style={{ textAlign: 'right' }}
399
- loading={isCipher(changeField, 'lineAmountExcludeTax')}
400
- onChange={() => {
401
- setChangeField('lineAmountExcludeTax');
402
- onChangeLineAmountExcludeTax(controller, form, record);
403
- }}
404
- />,
405
- )}
406
- </Form.Item>
407
- );
408
- } else {
409
- return <span style={{ padding: '0 10px' }}>{formatSearch(parseFloat(value).toFixed(2), searchValue)}</span>;
410
- }
411
- },
412
- },
413
- {
414
- title: <TitleText required >税率%</TitleText>,
415
- dataIndex: 'taxRate',
416
- key: 'taxRate',
417
- align: 'right',
418
- width: 70,
419
- render: (value: string, record: IGood) => {
420
- if (editGood?.$index === record.$index) {
421
- return (
422
- <Form.Item>
423
- {getFieldDecorator('taxRate', {
424
- initialValue: editGood.taxRate,
425
- rules: [
426
- ...getReplenishRules('taxRate'),
427
- { required: true, message: ' ' },
428
- { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: ' ' },
429
- ],
430
- })(
431
- <Select
432
- className="kts-invoice-operate-goods-list-table-tax-rate"
433
- dropdownMenuStyle={{ textAlign: "right" }}
434
- showArrow={false}
435
- style={{ width: '100%' }}
436
- onChange={() => {
437
- setChangeField('taxRate');
438
- onChangeTaxRate(controller, form, record);
439
- }}
440
- >
441
- {taxRateList.map((e, i) => {
442
- return (
443
- <Select.Option key={i} value={e}>
444
- {e}%
445
- </Select.Option>
446
- );
447
- })}
448
- </Select>,
449
- )}
450
- </Form.Item>
451
- );
452
- } else {
453
- return <span style={{ padding: '0 10px' }}>{value}%</span>;
454
- }
455
- },
456
- },
457
- {
458
- title: <TitleText rules={columnsReplenish['taxAmount']?.rules} >税额</TitleText>,
459
- dataIndex: 'taxAmount',
460
- key: 'taxAmount',
461
- align: 'right',
462
- width: 119,
463
- render: (value: string, record: IGood) => {
464
- if (editGood?.$index === record.$index) {
465
- return getFieldDecorator('taxAmount', {
466
- initialValue: editGood.taxAmount,
467
- rules: getReplenishRules('taxAmount'),
468
- })(<MyDiv loading={isCipher(changeField, 'taxAmount')} />);
469
- } else {
470
- return <span style={{ padding: '0 10px' }}>{parseFloat(value).toFixed(2)}</span>;
471
- }
472
- },
473
- },
474
- {
475
- title: '操作',
476
- key: 'operating',
477
- align: 'right',
478
- width: 130,
479
- fixed: 'right',
480
- render: (_value: string, record: IGood) => <RowMenu key={record.lineAttribute} goods={record} />,
481
- },
482
- ]
483
- // 含税不含税
484
- .filter((e) => {
485
- if (isTaxIncluded) {
486
- return !(e.key === 'priceExcludeTax' || e.key === 'lineAmountExcludeTax');
487
- } else {
488
- return !(e.key === 'priceIncludeTax' || e.key === 'lineAmountIncludeTax');
489
- }
490
- })
491
- // 只读
492
- .filter(e => {
493
- if (model === 'readOnly') {
494
- return e.key !== 'operating';
495
- } else {
496
- return true;
497
- }
498
- })
499
- .map((e) => {
500
- return {
501
- ...e,
502
- ellipsis: true,
503
- };
504
- }) as any[];
505
- }, [isTaxIncluded, editGood, controller, changeField, deduction, isMyShow, searchValue, model, columnsReplenish]);
506
-
507
- // React.useEffect(() => {
508
- // clearTimeout(t)
509
- // const t = setTimeout(() => { setChangeField('') }, 1000);
510
- // return () => { clearTimeout(t) }
511
- // }, [changeField]);
512
-
513
- return columns;
514
- };
515
-
516
- /** 字段 */
517
- function isCipher(name?: string, field?: string) {
518
- if (!name || !field) return false;
519
- return name !== field;
520
- }
521
-
522
- class MyInput extends React.Component<InputProps & { loading?: boolean }> {
523
- render() {
524
- if (this.props.loading) {
525
- return (
526
- <Spin size="small">
527
- <Input {...this.props} autoComplete="off" />
528
- </Spin>
529
- )
530
- } else {
531
- return <Input {...this.props} autoComplete="off" />
532
- }
533
- }
534
- }
535
-
536
- class MyDiv extends React.Component<{ value?: any, loading?: boolean }> {
537
-
538
- render() {
539
- if (this.props.loading) {
540
- return (
541
- <Spin size="small">
542
- <span style={{ padding: '0 10px' }}>{this.props.value}</span>
543
- </Spin>
544
- )
545
- } else {
546
- return <span style={{ padding: '0 10px' }}>{this.props.value}</span>
547
- }
548
- }
549
- }
550
-
551
- class MyItemNameDiv extends React.Component<{ valueT?: React.ReactNode, valueF?: React.ReactNode, isMyShow: boolean }> {
552
- render(): React.ReactNode {
553
-
554
- const { isMyShow, valueT, valueF } = this.props;
555
-
556
- if (isMyShow) {
557
- if (valueT) {
558
- return (
559
- <Tooltip title={valueT}>
560
- <span style={{ padding: '0 10px', color: '#0074ff' }}>{valueT}</span>
561
- </Tooltip>
562
- )
563
- } else {
564
- return (
565
- <Tooltip title={valueF}>
566
- <span style={{ padding: '0 10px' }}>{valueF}</span>
567
- </Tooltip>
568
- )
569
- }
570
- } else {
571
- if (valueF) {
572
- return (
573
- <Tooltip title={valueF}>
574
- <span style={{ padding: '0 10px' }}>{valueF}</span>
575
- </Tooltip>
576
- )
577
- } else {
578
- return (
579
- <Tooltip title={valueT}>
580
- <span style={{ padding: '0 10px', color: '#0074ff' }}>{valueT}</span>
581
- </Tooltip>
582
- )
583
- }
584
- }
585
- }
586
- }
587
-
588
- /** 格式搜索结果 */
589
- function formatSearch(value?: string, search?: string) {
590
- if (!value || !search) return value;
591
-
592
- const __html = ucoding(value).split(new RegExp(ucoding(search), 'g')).map(e => dcoding(e)).join(`<span class="kts-invoice-operate-goods-list-table-search-protrude" >${search}</span>`);
593
- return <span dangerouslySetInnerHTML={{ __html }} />
594
- }
595
-
596
- /** 编码 */
597
- function ucoding(v: string): string {
598
- return v.split('').map(e => `U${e.charCodeAt(0)}E`).join('');
599
- }
600
-
601
- /** 解码 */
602
- function dcoding(v: string): string {
603
- return v.split('U').map(e => e ? String.fromCharCode(parseInt(e.replace('E', ''))) : '').join('');
1
+ import React from 'react';
2
+ import { Form, AutoComplete, Select, Button, Input, Spin, Tooltip } from 'kts-components-antd-x3';
3
+ import { InputProps } from 'kts-components-antd-x3/lib/input';
4
+ import { WrappedFormUtils } from 'kts-components-antd-x3/lib/form/Form';
5
+ import { IGood } from '../../../../InvoiceController';
6
+ import Invoice from '../../../../';
7
+ import RowMenu from './ui/RowMenu';
8
+ import TitleText from './ui/TitleText';
9
+ import ItemNameInput from './ui/ItemNameInput';
10
+ import {
11
+ onChangeQuantity,
12
+ onChangePriceIncludeTax,
13
+ onChangePriceExcludeTax,
14
+ onChangeLineAmountIncludeTax,
15
+ onChangeLineAmountExcludeTax,
16
+ onChangeTaxRate,
17
+ onChangeItemName,
18
+ } from './autoFillFn';
19
+
20
+ export default (form: WrappedFormUtils) => {
21
+ const { getFieldDecorator, getFieldValue } = form;
22
+
23
+ const controller = Invoice.useInvoiceController();
24
+
25
+ /** 是否含税 */
26
+ const isTaxIncluded = controller.useMemo(e => e.goodsListState.isTaxIncluded, []);
27
+
28
+ /** 组件模式 */
29
+ const model = controller.useMemo(e => e.model, []);
30
+
31
+ /** 是否显示我方 */
32
+ const isMyShow = controller.useMemo(e => e.goodsListState.isMyShow, []);
33
+
34
+ /** 正在编辑的货物 */
35
+ const editGood = controller.useMemo((e) => e.goodsListState.editGood, []);
36
+
37
+ /** 搜索条件 */
38
+ const searchValue = controller.useMemo((e) => e.goodsListState.searchValue, []);
39
+
40
+ /** 税率列表 */
41
+ const taxRateList = controller.useMemo((e) => e.goodsListState.taxRateList, []);
42
+
43
+ /** 单位列表 */
44
+ const unitList = controller.useMemo((e) => e.goodsListState.unitList, []);
45
+
46
+ /** 商品表格补充配置 */
47
+ const columnsReplenish = controller.useMemo((e) => e.goodsListState.columnsReplenish, []);
48
+
49
+ /** 扣除额 */
50
+ const deduction = controller.useMemo((e) => e.goodsListState.deduction, []);
51
+
52
+ /** 计算中启动字段 */
53
+ const changeField = controller.useMemo((e) => e.calculating, []);
54
+
55
+ /** 计算中启动字段 */
56
+ const setChangeField = React.useCallback((value: string) => controller.run(async s => { s.calculating = value }), []);
57
+
58
+ /** 获取补充校验规则 */
59
+ const getReplenishRules = React.useCallback((id: string) => {
60
+ return columnsReplenish[id] ? columnsReplenish[id].rules || [] : []
61
+ }, [columnsReplenish])
62
+
63
+ /** 表头 */
64
+ const columns = React.useMemo(() => {
65
+ return [
66
+ {
67
+ title: '序号',
68
+ key: 'serialNo',
69
+ dataIndex: 'serialNo',
70
+ width: 50,
71
+ render: (e: number) => <span style={{ padding: '0 10px' }}>{e}</span>,
72
+ },
73
+ {
74
+ title: <TitleText required >项目名称</TitleText>,
75
+ key: 'itemName',
76
+ render: (_: string, record: IGood) => {
77
+ if (editGood?.$index === record.$index) {
78
+ return (
79
+ <Form.Item>
80
+ <div style={{ display: 'flex' }} >
81
+ {getFieldDecorator('itemName', {
82
+ initialValue: isMyShow ? record.itemNameSelf : record.itemName,
83
+ rules: [
84
+ ...getReplenishRules('itemName'),
85
+ {
86
+ validator: async (_, __, callback) => {
87
+ await controller.wait();
88
+ const value = controller.state.goodsListState.editGood;
89
+ if (!value?.itemName && !value?.itemNameSelf) {
90
+ callback('项目名称不能为空');
91
+ } else {
92
+ return;
93
+ }
94
+ }
95
+ }
96
+ ]
97
+ })(
98
+ <ItemNameInput
99
+ onChange={() => {
100
+ onChangeItemName(controller, form, record);
101
+ }}
102
+ />
103
+ )}
104
+ <div className="kts-invoice-operate-goods-list-able-list-itemName-import">
105
+ {controller.getGoodsList && model !== 'readOnly' && (
106
+ <Tooltip title="点击从商品管理中添加商品信息">
107
+ <Button
108
+ onClick={controller.pipeline(async s => { s.goodsListState.importGoods.isVisibleDrawer = true })}
109
+ type="link"
110
+ icon="plus-circle"
111
+ />
112
+ </Tooltip>
113
+ )}
114
+ </div>
115
+ </div>
116
+ </Form.Item>
117
+ );
118
+ } else {
119
+ return (
120
+ <MyItemNameDiv
121
+ valueT={formatSearch(record.itemNameSelf, searchValue)}
122
+ valueF={formatSearch(record.itemName, searchValue)}
123
+ isMyShow={isMyShow}
124
+ />
125
+ )
126
+ }
127
+ },
128
+ },
129
+ {
130
+ title: <TitleText rules={columnsReplenish['itemModelName']?.rules} >规格型号</TitleText>,
131
+ key: 'itemModelName',
132
+ width: 119,
133
+ render: (_: string, record: IGood) => {
134
+ if (editGood?.$index === record.$index) {
135
+ return (
136
+ <Form.Item>
137
+ {getFieldDecorator('itemModelName', {
138
+ initialValue: isMyShow ? editGood.itemModelNameSelf : editGood.itemModelName,
139
+ rules: getReplenishRules('itemModelName'),
140
+ })(
141
+ <MyInput
142
+ onChange={async () => {
143
+ await controller.wait()
144
+ const key = isMyShow ? 'itemModelNameSelf' : 'itemModelName';
145
+ const value = {} as any;
146
+ value[key] = form.getFieldsValue().itemModelName;
147
+ controller.setEditGood(value);
148
+ }}
149
+ />,
150
+ )}
151
+ </Form.Item>
152
+ );
153
+ } else {
154
+ return (
155
+ <MyItemNameDiv
156
+ valueT={formatSearch(record.itemModelNameSelf, searchValue)}
157
+ valueF={formatSearch(record.itemModelName, searchValue)}
158
+ isMyShow={isMyShow}
159
+ />
160
+ )
161
+ }
162
+ },
163
+ },
164
+ {
165
+ title: <TitleText rules={columnsReplenish['unit']?.rules} >单位</TitleText>,
166
+ key: 'unit',
167
+ width: 70,
168
+ render: (_: string, record: IGood) => {
169
+ if (editGood?.$index === record.$index) {
170
+ return (
171
+ <Form.Item>
172
+ {getFieldDecorator('unit', {
173
+ initialValue: editGood.unit,
174
+ rules: getReplenishRules('unit'),
175
+ })(
176
+ <AutoComplete
177
+ style={{ width: '100%' }}
178
+ dataSource={unitList}
179
+ onChange={async () => {
180
+ await controller.wait()
181
+ // const key = isMyShow ? 'unit' : 'unitOther';
182
+ // const value = {} as any;
183
+ // value[key] = form.getFieldsValue().unit;
184
+ controller.setEditGood({ unit: form.getFieldsValue().unit });
185
+ }}
186
+ />,
187
+ )}
188
+ </Form.Item>
189
+ );
190
+ } else {
191
+ return <span style={{ padding: '0 10px' }}>{record.unit}</span>;
192
+ }
193
+ },
194
+ },
195
+ {
196
+ title: <TitleText rules={columnsReplenish['quantity']?.rules} >数量</TitleText>,
197
+ dataIndex: 'quantity',
198
+ key: 'quantity',
199
+ align: 'right',
200
+ width: 149,
201
+ render: (value: string, record: IGood) => {
202
+ if (editGood?.$index === record.$index) {
203
+ return (
204
+ <Form.Item>
205
+ {getFieldDecorator('quantity', {
206
+ initialValue: editGood.quantity,
207
+ rules: [
208
+ ...getReplenishRules('quantity'),
209
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '数量必须为数字' },
210
+ {
211
+ validator: async (_, value, callback) => {
212
+ await controller.wait();
213
+ const isvalue = !!value || value === 0;
214
+ const isPrice = !!getFieldValue(isTaxIncluded ? 'priceIncludeTax' : 'priceExcludeTax') || getFieldValue(isTaxIncluded ? 'priceIncludeTax' : 'priceExcludeTax') === 0;
215
+ if (isvalue || isPrice === isvalue) return;
216
+ callback('请输入数量');
217
+ }
218
+ }
219
+ ],
220
+ })(
221
+ <MyInput
222
+ style={{ textAlign: 'right' }}
223
+ maxLength={16}
224
+ loading={isCipher(changeField, "quantity")}
225
+ onChange={async () => {
226
+ setChangeField('quantity');
227
+ await onChangeQuantity(controller, form, record);
228
+ }}
229
+ />,
230
+ )}
231
+ </Form.Item>
232
+ );
233
+ } else {
234
+ return <span style={{ padding: '0 10px' }}>{value}</span>;
235
+ }
236
+ },
237
+ },
238
+ {
239
+ title: <TitleText rules={columnsReplenish['priceIncludeTax']?.rules} >单价(含税)</TitleText>,
240
+ dataIndex: 'priceIncludeTax',
241
+ key: 'priceIncludeTax',
242
+ align: 'right',
243
+ width: 149,
244
+ render: (value: string, record: IGood) => {
245
+ if (editGood?.$index === record.$index) {
246
+ return (
247
+ <Form.Item>
248
+ {getFieldDecorator('priceIncludeTax', {
249
+ initialValue: editGood.priceIncludeTax,
250
+ rules: [
251
+ ...getReplenishRules('priceIncludeTax'),
252
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '单价必须为数字' },
253
+ {
254
+ validator: async (_, value, callback) => {
255
+ await controller.wait();
256
+ const isQuantity = !!getFieldValue('quantity') || getFieldValue('quantity') === 0;
257
+ const isvalue = !!value || value === 0;
258
+ if (isvalue || isQuantity === isvalue) return;
259
+ callback('请输入单价');
260
+ }
261
+ }
262
+ ],
263
+ })(
264
+ <MyInput
265
+ style={{ textAlign: 'right' }}
266
+ maxLength={16}
267
+ loading={isCipher(changeField, 'priceIncludeTax')}
268
+ onChange={() => {
269
+ setChangeField('priceIncludeTax');
270
+ onChangePriceIncludeTax(controller, form, record);
271
+ }}
272
+ />,
273
+ )}
274
+ </Form.Item>
275
+ );
276
+ } else {
277
+ return <span style={{ padding: '0 10px' }}>{value}</span>;
278
+ }
279
+ },
280
+ },
281
+ {
282
+ title: <TitleText rules={columnsReplenish['priceExcludeTax']?.rules} >单价(不含税)</TitleText>,
283
+ dataIndex: 'priceExcludeTax',
284
+ key: 'priceExcludeTax',
285
+ align: 'right',
286
+ width: 149,
287
+ render: (value: string, record: IGood) => {
288
+ if (editGood?.$index === record.$index) {
289
+ return (
290
+ <Form.Item>
291
+ {getFieldDecorator('priceExcludeTax', {
292
+ initialValue: editGood.priceExcludeTax,
293
+ rules: [
294
+ ...getReplenishRules('priceExcludeTax'),
295
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '单价必须为数字' },
296
+ {
297
+ validator: async (_, value, callback) => {
298
+ await controller.wait();
299
+ const isQuantity = !!getFieldValue('quantity') || getFieldValue('quantity') === 0;
300
+ const isvalue = !!value || value === 0;
301
+ if (isvalue || isQuantity === isvalue) return;
302
+ callback('请输入单价');
303
+ }
304
+ }
305
+ ],
306
+ })(
307
+ <MyInput
308
+ style={{ textAlign: 'right' }}
309
+ maxLength={16}
310
+ loading={isCipher(changeField, 'priceExcludeTax')}
311
+ onChange={() => {
312
+ setChangeField('priceExcludeTax');
313
+ onChangePriceExcludeTax(controller, form, record);
314
+ }}
315
+ />,
316
+ )}
317
+ </Form.Item>
318
+ );
319
+ } else {
320
+ return <span style={{ padding: '0 10px' }}>{value}</span>;
321
+ }
322
+ },
323
+ },
324
+ {
325
+ title: <TitleText required >金额(含税)</TitleText>,
326
+ dataIndex: 'lineAmountIncludeTax',
327
+ key: 'lineAmountIncludeTax',
328
+ width: 119,
329
+ align: 'right',
330
+ render: (value: string, record: IGood) => {
331
+ if (editGood?.$index === record.$index) {
332
+ return (
333
+ <Form.Item>
334
+ {getFieldDecorator('lineAmountIncludeTax', {
335
+ initialValue: editGood.lineAmountIncludeTax,
336
+ rules: [
337
+ ...getReplenishRules('lineAmountIncludeTax'),
338
+ { required: true, message: '金额不能为空' },
339
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '金额必须为数字' },
340
+ {
341
+ validator: async (_, value, callback) => {
342
+ if (`${value}`.split('.')[0].length > 9) {
343
+ callback('金额整数部分不能大于9位,小数点后最多2位');
344
+ }
345
+ }
346
+ },
347
+ {
348
+ validator: async (_, value, callback) => {
349
+ if (deduction && parseFloat(value) <= deduction) {
350
+ callback('扣除额不能大于等于价税合计');
351
+ }
352
+ }
353
+ },
354
+ ],
355
+ })(
356
+ <MyInput
357
+ style={{ textAlign: 'right' }}
358
+ loading={isCipher(changeField, 'lineAmountIncludeTax')}
359
+ onChange={() => {
360
+ setChangeField('lineAmountIncludeTax');
361
+ onChangeLineAmountIncludeTax(controller, form, record);
362
+ }}
363
+ />,
364
+ )}
365
+ </Form.Item>
366
+ );
367
+ } else {
368
+ return <span style={{ padding: '0 10px' }}>{formatSearch(parseFloat(value).toFixed(2), searchValue)}</span>;
369
+ }
370
+ },
371
+ },
372
+ {
373
+ title: <TitleText required >金额(不含税)</TitleText>,
374
+ dataIndex: 'lineAmountExcludeTax',
375
+ key: 'lineAmountExcludeTax',
376
+ align: 'right',
377
+ width: 119,
378
+ render: (value: string, record: IGood) => {
379
+ if (editGood?.$index === record.$index) {
380
+ return (
381
+ <Form.Item>
382
+ {getFieldDecorator('lineAmountExcludeTax', {
383
+ initialValue: editGood.lineAmountExcludeTax,
384
+ rules: [
385
+ ...getReplenishRules('lineAmountExcludeTax'),
386
+ { required: true, message: '金额不能为空' },
387
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: '金额必须为数字' },
388
+ {
389
+ validator: async (_, value: string, callback) => {
390
+ if (`${value}`.split('.')[0].length > 9) {
391
+ callback('金额整数部分不能大于9位,小数点后最多2位');
392
+ }
393
+ }
394
+ },
395
+ ],
396
+ })(
397
+ <MyInput
398
+ style={{ textAlign: 'right' }}
399
+ loading={isCipher(changeField, 'lineAmountExcludeTax')}
400
+ onChange={() => {
401
+ setChangeField('lineAmountExcludeTax');
402
+ onChangeLineAmountExcludeTax(controller, form, record);
403
+ }}
404
+ />,
405
+ )}
406
+ </Form.Item>
407
+ );
408
+ } else {
409
+ return <span style={{ padding: '0 10px' }}>{formatSearch(parseFloat(value).toFixed(2), searchValue)}</span>;
410
+ }
411
+ },
412
+ },
413
+ {
414
+ title: <TitleText required >税率%</TitleText>,
415
+ dataIndex: 'taxRate',
416
+ key: 'taxRate',
417
+ align: 'right',
418
+ width: 70,
419
+ render: (value: string, record: IGood) => {
420
+ if (editGood?.$index === record.$index) {
421
+ return (
422
+ <Form.Item>
423
+ {getFieldDecorator('taxRate', {
424
+ initialValue: editGood.taxRate,
425
+ rules: [
426
+ ...getReplenishRules('taxRate'),
427
+ { required: true, message: ' ' },
428
+ { pattern: /^[+-]?(0|([1-9]\d*))(\.\d+)?$/, message: ' ' },
429
+ ],
430
+ })(
431
+ <Select
432
+ className="kts-invoice-operate-goods-list-table-tax-rate"
433
+ dropdownMenuStyle={{ textAlign: "right" }}
434
+ showArrow={false}
435
+ style={{ width: '100%' }}
436
+ onChange={() => {
437
+ setChangeField('taxRate');
438
+ onChangeTaxRate(controller, form, record);
439
+ }}
440
+ >
441
+ {taxRateList.map((e, i) => {
442
+ return (
443
+ <Select.Option key={i} value={e}>
444
+ {e}%
445
+ </Select.Option>
446
+ );
447
+ })}
448
+ </Select>,
449
+ )}
450
+ </Form.Item>
451
+ );
452
+ } else {
453
+ return <span style={{ padding: '0 10px' }}>{value}%</span>;
454
+ }
455
+ },
456
+ },
457
+ {
458
+ title: <TitleText rules={columnsReplenish['taxAmount']?.rules} >税额</TitleText>,
459
+ dataIndex: 'taxAmount',
460
+ key: 'taxAmount',
461
+ align: 'right',
462
+ width: 119,
463
+ render: (value: string, record: IGood) => {
464
+ if (editGood?.$index === record.$index) {
465
+ return getFieldDecorator('taxAmount', {
466
+ initialValue: editGood.taxAmount,
467
+ rules: getReplenishRules('taxAmount'),
468
+ })(<MyDiv loading={isCipher(changeField, 'taxAmount')} />);
469
+ } else {
470
+ return <span style={{ padding: '0 10px' }}>{parseFloat(value).toFixed(2)}</span>;
471
+ }
472
+ },
473
+ },
474
+ {
475
+ title: '操作',
476
+ key: 'operating',
477
+ align: 'right',
478
+ width: 130,
479
+ fixed: 'right',
480
+ render: (_value: string, record: IGood) => <RowMenu key={record.lineAttribute} goods={record} />,
481
+ },
482
+ ]
483
+ // 含税不含税
484
+ .filter((e) => {
485
+ if (isTaxIncluded) {
486
+ return !(e.key === 'priceExcludeTax' || e.key === 'lineAmountExcludeTax');
487
+ } else {
488
+ return !(e.key === 'priceIncludeTax' || e.key === 'lineAmountIncludeTax');
489
+ }
490
+ })
491
+ // 只读
492
+ .filter(e => {
493
+ if (model === 'readOnly') {
494
+ return e.key !== 'operating';
495
+ } else {
496
+ return true;
497
+ }
498
+ })
499
+ .map((e) => {
500
+ return {
501
+ ...e,
502
+ ellipsis: true,
503
+ };
504
+ }) as any[];
505
+ }, [isTaxIncluded, editGood, controller, changeField, deduction, isMyShow, searchValue, model, columnsReplenish]);
506
+
507
+ // React.useEffect(() => {
508
+ // clearTimeout(t)
509
+ // const t = setTimeout(() => { setChangeField('') }, 1000);
510
+ // return () => { clearTimeout(t) }
511
+ // }, [changeField]);
512
+
513
+ return columns;
514
+ };
515
+
516
+ /** 字段 */
517
+ function isCipher(name?: string, field?: string) {
518
+ if (!name || !field) return false;
519
+ return name !== field;
520
+ }
521
+
522
+ class MyInput extends React.Component<InputProps & { loading?: boolean }> {
523
+ render() {
524
+ if (this.props.loading) {
525
+ return (
526
+ <Spin size="small">
527
+ <Input {...this.props} autoComplete="off" />
528
+ </Spin>
529
+ )
530
+ } else {
531
+ return <Input {...this.props} autoComplete="off" />
532
+ }
533
+ }
534
+ }
535
+
536
+ class MyDiv extends React.Component<{ value?: any, loading?: boolean }> {
537
+
538
+ render() {
539
+ if (this.props.loading) {
540
+ return (
541
+ <Spin size="small">
542
+ <span style={{ padding: '0 10px' }}>{this.props.value}</span>
543
+ </Spin>
544
+ )
545
+ } else {
546
+ return <span style={{ padding: '0 10px' }}>{this.props.value}</span>
547
+ }
548
+ }
549
+ }
550
+
551
+ class MyItemNameDiv extends React.Component<{ valueT?: React.ReactNode, valueF?: React.ReactNode, isMyShow: boolean }> {
552
+ render(): React.ReactNode {
553
+
554
+ const { isMyShow, valueT, valueF } = this.props;
555
+
556
+ if (isMyShow) {
557
+ if (valueT) {
558
+ return (
559
+ <Tooltip title={valueT}>
560
+ <span style={{ padding: '0 10px', color: '#0074ff' }}>{valueT}</span>
561
+ </Tooltip>
562
+ )
563
+ } else {
564
+ return (
565
+ <Tooltip title={valueF}>
566
+ <span style={{ padding: '0 10px' }}>{valueF}</span>
567
+ </Tooltip>
568
+ )
569
+ }
570
+ } else {
571
+ if (valueF) {
572
+ return (
573
+ <Tooltip title={valueF}>
574
+ <span style={{ padding: '0 10px' }}>{valueF}</span>
575
+ </Tooltip>
576
+ )
577
+ } else {
578
+ return (
579
+ <Tooltip title={valueT}>
580
+ <span style={{ padding: '0 10px', color: '#0074ff' }}>{valueT}</span>
581
+ </Tooltip>
582
+ )
583
+ }
584
+ }
585
+ }
586
+ }
587
+
588
+ /** 格式搜索结果 */
589
+ function formatSearch(value?: string, search?: string) {
590
+ if (!value || !search) return value;
591
+
592
+ const __html = ucoding(value).split(new RegExp(ucoding(search), 'g')).map(e => dcoding(e)).join(`<span class="kts-invoice-operate-goods-list-table-search-protrude" >${search}</span>`);
593
+ return <span dangerouslySetInnerHTML={{ __html }} />
594
+ }
595
+
596
+ /** 编码 */
597
+ function ucoding(v: string): string {
598
+ return v.split('').map(e => `U${e.charCodeAt(0)}E`).join('');
599
+ }
600
+
601
+ /** 解码 */
602
+ function dcoding(v: string): string {
603
+ return v.split('U').map(e => e ? String.fromCharCode(parseInt(e.replace('E', ''))) : '').join('');
604
604
  }