kts-component-invoice-operate 3.2.13 → 3.2.15

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