kts-component-invoice-operate 3.2.145 → 3.2.147

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