kts-component-invoice-operate 3.1.12 → 3.1.13

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