Commit a6c77b1602389c981e91e7da4d4a6de356222762
1 parent
04358c9a
feat(invoice): optimize invoice components and add Chinese currency conversion utility
- Add dynamic invoice type display in Invoice.tsx. - Refactor InvoiceDetailTable.tsx to simplify code and remove unnecessary comments. - Optimize data processing and UI display in InvoiceModal.tsx. - Improve component structure and add orderId mapping in InvoiceRecordDetailModal.tsx. - Enhance InvoicingDrawerForm.tsx with total price calculation and validation.- Implement Chinese currency conversion function in numberUtil.ts. - Various code cleanups and documentation improvements.
Showing
10 changed files
with
246 additions
and
87 deletions
src/pages/Invoice/components/Invoice.tsx
@@ -154,7 +154,11 @@ export default ({ data }) => { | @@ -154,7 +154,11 @@ export default ({ data }) => { | ||
154 | 发票号码:<InvoiceInfo>{data.invoiceNumber}</InvoiceInfo> | 154 | 发票号码:<InvoiceInfo>{data.invoiceNumber}</InvoiceInfo> |
155 | </Col> | 155 | </Col> |
156 | <Col className="title col_18 no-border"> | 156 | <Col className="title col_18 no-border"> |
157 | - 电子发票(增值税专用发票) | 157 | + 电子发票( |
158 | + {data.type === 'SPECIAL_TICKET' | ||
159 | + ? '增值税专用发票' | ||
160 | + : '增值税普通发票'} | ||
161 | + ) | ||
158 | </Col> | 162 | </Col> |
159 | <UnderLine className="UnderLine"> | 163 | <UnderLine className="UnderLine"> |
160 | <div></div> | 164 | <div></div> |
src/pages/Invoice/components/InvoiceDetailTable.tsx
@@ -3,13 +3,14 @@ import { InvoiceProjectSelect } from '@/pages/Invoice/components/InvoiceProjectS | @@ -3,13 +3,14 @@ import { InvoiceProjectSelect } from '@/pages/Invoice/components/InvoiceProjectS | ||
3 | import { | 3 | import { |
4 | ActionType, | 4 | ActionType, |
5 | EditableProTable, | 5 | EditableProTable, |
6 | + ProCard, | ||
6 | ProColumns, | 7 | ProColumns, |
8 | + ProFormField, | ||
7 | } from '@ant-design/pro-components'; | 9 | } from '@ant-design/pro-components'; |
8 | import { useEffect, useRef, useState } from 'react'; | 10 | import { useEffect, useRef, useState } from 'react'; |
9 | 11 | ||
10 | export default ({ recordId, details, updateDetails, readOnly }) => { | 12 | export default ({ recordId, details, updateDetails, readOnly }) => { |
11 | const [editableKeys, setEditableRowKeys] = useState([]); | 13 | const [editableKeys, setEditableRowKeys] = useState([]); |
12 | - const [invoiceProject, setInvoiceProject] = useState({}); | ||
13 | const ref = useRef<ActionType>(); | 14 | const ref = useRef<ActionType>(); |
14 | useEffect(() => { | 15 | useEffect(() => { |
15 | updateDetails(details); | 16 | updateDetails(details); |
@@ -26,12 +27,7 @@ export default ({ recordId, details, updateDetails, readOnly }) => { | @@ -26,12 +27,7 @@ export default ({ recordId, details, updateDetails, readOnly }) => { | ||
26 | ellipsis: true, | 27 | ellipsis: true, |
27 | readonly: readOnly, | 28 | readonly: readOnly, |
28 | renderFormItem: () => { | 29 | renderFormItem: () => { |
29 | - return ( | ||
30 | - <InvoiceProjectSelect | ||
31 | - setInvoiceProject={setInvoiceProject} | ||
32 | - readOnly={readOnly} | ||
33 | - /> | ||
34 | - ); | 30 | + return <InvoiceProjectSelect readOnly={readOnly} />; |
35 | }, | 31 | }, |
36 | }, | 32 | }, |
37 | { | 33 | { |
@@ -131,46 +127,27 @@ export default ({ recordId, details, updateDetails, readOnly }) => { | @@ -131,46 +127,27 @@ export default ({ recordId, details, updateDetails, readOnly }) => { | ||
131 | onValuesChange: (record, recordList) => { | 127 | onValuesChange: (record, recordList) => { |
132 | //修改recordList中tid为record.tid的元素,将它的specification属性设置为invoiceProject的specification属性 | 128 | //修改recordList中tid为record.tid的元素,将它的specification属性设置为invoiceProject的specification属性 |
133 | const records = recordList.map((item) => { | 129 | const records = recordList.map((item) => { |
134 | - if ( | ||
135 | - record && | ||
136 | - item.tid === record.tid && | ||
137 | - item.projectName !== | ||
138 | - '*' + | ||
139 | - invoiceProject.productAndServiceCatagoryAbbreviation + | ||
140 | - '*' + | ||
141 | - invoiceProject?.name && | ||
142 | - item.specification !== invoiceProject?.specification | ||
143 | - ) { | ||
144 | - console.log(item.projectName); | ||
145 | - console.log(invoiceProject?.name); | ||
146 | - item.projectName = | ||
147 | - '*' + | ||
148 | - invoiceProject.productAndServiceCatagoryAbbreviation + | ||
149 | - '*' + | ||
150 | - invoiceProject?.name; | ||
151 | - item.specification = invoiceProject?.specification; | ||
152 | - item.unit = invoiceProject?.unit; | ||
153 | - item.taxRate = invoiceProject?.taxRate * 100; | ||
154 | - } | ||
155 | return item; | 130 | return item; |
156 | }); | 131 | }); |
157 | updateDetails(records); | 132 | updateDetails(records); |
158 | }, | 133 | }, |
159 | }} | 134 | }} |
160 | /> | 135 | /> |
161 | - {/*{<ProCard title="表格数据" headerBordered collapsible defaultCollapsed> | ||
162 | - <ProFormField | ||
163 | - ignoreFormItem | ||
164 | - fieldProps={{ | ||
165 | - style: { | ||
166 | - width: '100%', | ||
167 | - }, | ||
168 | - }} | ||
169 | - mode="read" | ||
170 | - valueType="jsonCode" | ||
171 | - text={JSON.stringify(details)} | ||
172 | - /> | ||
173 | - </ProCard>}*/} | 136 | + { |
137 | + <ProCard title="表格数据" headerBordered collapsible defaultCollapsed> | ||
138 | + <ProFormField | ||
139 | + ignoreFormItem | ||
140 | + fieldProps={{ | ||
141 | + style: { | ||
142 | + width: '100%', | ||
143 | + }, | ||
144 | + }} | ||
145 | + mode="read" | ||
146 | + valueType="jsonCode" | ||
147 | + text={JSON.stringify(details)} | ||
148 | + /> | ||
149 | + </ProCard> | ||
150 | + } | ||
174 | </> | 151 | </> |
175 | ); | 152 | ); |
176 | }; | 153 | }; |
src/pages/Invoice/components/InvoiceModal.tsx
@@ -6,15 +6,15 @@ import { useEffect, useState } from 'react'; | @@ -6,15 +6,15 @@ import { useEffect, useState } from 'react'; | ||
6 | 6 | ||
7 | export default ({ recordId, getRecord, button }) => { | 7 | export default ({ recordId, getRecord, button }) => { |
8 | const [data, setData] = useState<any>({}); | 8 | const [data, setData] = useState<any>({}); |
9 | + const getData = async () => { | ||
10 | + let ret = await postServiceInvoiceGetInvoiceRecord({ | ||
11 | + query: { | ||
12 | + id: recordId, | ||
13 | + }, | ||
14 | + }); | ||
15 | + setData(ret.data); | ||
16 | + }; | ||
9 | useEffect(() => { | 17 | useEffect(() => { |
10 | - const getData = async () => { | ||
11 | - let ret = await postServiceInvoiceGetInvoiceRecord({ | ||
12 | - query: { | ||
13 | - id: recordId, | ||
14 | - }, | ||
15 | - }); | ||
16 | - setData(ret.data); | ||
17 | - }; | ||
18 | if (recordId) { | 18 | if (recordId) { |
19 | getData(); | 19 | getData(); |
20 | } | 20 | } |
@@ -25,8 +25,12 @@ export default ({ recordId, getRecord, button }) => { | @@ -25,8 +25,12 @@ export default ({ recordId, getRecord, button }) => { | ||
25 | title="预览发票" | 25 | title="预览发票" |
26 | trigger={button ? button : <a type="primary">预览</a>} | 26 | trigger={button ? button : <a type="primary">预览</a>} |
27 | onOpenChange={(open) => { | 27 | onOpenChange={(open) => { |
28 | - if (open && getRecord) { | ||
29 | - setData(getRecord()); | 28 | + if (open) { |
29 | + if (getRecord) { | ||
30 | + setData(getRecord()); | ||
31 | + } else { | ||
32 | + getData(); | ||
33 | + } | ||
30 | } | 34 | } |
31 | }} | 35 | }} |
32 | width={1200} | 36 | width={1200} |
src/pages/Invoice/components/InvoiceProjectSelect.tsx
@@ -2,12 +2,7 @@ import { postServiceConstListInvoiceDetailNames } from '@/services'; | @@ -2,12 +2,7 @@ import { postServiceConstListInvoiceDetailNames } from '@/services'; | ||
2 | import { Select, Tooltip } from 'antd'; | 2 | import { Select, Tooltip } from 'antd'; |
3 | import { useState } from 'react'; | 3 | import { useState } from 'react'; |
4 | 4 | ||
5 | -export const InvoiceProjectSelect = ({ | ||
6 | - readOnly, | ||
7 | - value, | ||
8 | - onChange, | ||
9 | - setInvoiceProject, | ||
10 | -}) => { | 5 | +export const InvoiceProjectSelect = ({ readOnly, value, onChange }) => { |
11 | const [options, setOptions] = useState<any[]>([]); | 6 | const [options, setOptions] = useState<any[]>([]); |
12 | // 定义防抖函数 | 7 | // 定义防抖函数 |
13 | let timeoutId = null; | 8 | let timeoutId = null; |
@@ -20,16 +15,22 @@ export const InvoiceProjectSelect = ({ | @@ -20,16 +15,22 @@ export const InvoiceProjectSelect = ({ | ||
20 | }, | 15 | }, |
21 | }); | 16 | }); |
22 | const data = res.data; | 17 | const data = res.data; |
23 | - console.log('invoiceProject' + JSON.stringify(data)); | 18 | + |
24 | setOptions( | 19 | setOptions( |
25 | data.map((item) => { | 20 | data.map((item) => { |
21 | + console.log(item); | ||
26 | return { | 22 | return { |
23 | + key: item.id, | ||
27 | label: | 24 | label: |
28 | '*' + | 25 | '*' + |
29 | item.productAndServiceCatagoryAbbreviation + | 26 | item.productAndServiceCatagoryAbbreviation + |
30 | '*' + | 27 | '*' + |
31 | item?.name, | 28 | item?.name, |
32 | - value: item.id, | 29 | + value: |
30 | + '*' + | ||
31 | + item.productAndServiceCatagoryAbbreviation + | ||
32 | + '*' + | ||
33 | + item?.name, | ||
33 | ...item, | 34 | ...item, |
34 | }; | 35 | }; |
35 | }), | 36 | }), |
@@ -48,7 +49,6 @@ export const InvoiceProjectSelect = ({ | @@ -48,7 +49,6 @@ export const InvoiceProjectSelect = ({ | ||
48 | placeholder="请选择开票项目" | 49 | placeholder="请选择开票项目" |
49 | filterOption={(input, option) => (option?.label ?? '').includes(input)} | 50 | filterOption={(input, option) => (option?.label ?? '').includes(input)} |
50 | onChange={(e) => { | 51 | onChange={(e) => { |
51 | - setInvoiceProject(options.find((item) => item.value === e)); | ||
52 | onChange(e); | 52 | onChange(e); |
53 | }} | 53 | }} |
54 | defaultValue={value} | 54 | defaultValue={value} |
src/pages/Invoice/components/InvoiceRecordDetailModal.tsx
@@ -51,6 +51,7 @@ export default ({ id, setVisible }) => { | @@ -51,6 +51,7 @@ export default ({ id, setVisible }) => { | ||
51 | id: id, | 51 | id: id, |
52 | }, | 52 | }, |
53 | }); | 53 | }); |
54 | + console.log(ret.data); | ||
54 | const updatedInvoiceDetails = ret.data.invoiceDetails?.map( | 55 | const updatedInvoiceDetails = ret.data.invoiceDetails?.map( |
55 | (item, index) => ({ | 56 | (item, index) => ({ |
56 | ...item, // 保留原有属性 | 57 | ...item, // 保留原有属性 |
@@ -79,7 +80,23 @@ export default ({ id, setVisible }) => { | @@ -79,7 +80,23 @@ export default ({ id, setVisible }) => { | ||
79 | id: id, | 80 | id: id, |
80 | }, | 81 | }, |
81 | }); | 82 | }); |
82 | - return ret.data; | 83 | + const data = ret.data; |
84 | + const orderIdMap = data.orderIdMap; | ||
85 | + const orderIdList = []; | ||
86 | + //遍历orderIdMap属性。 | ||
87 | + for (const key in orderIdMap) { | ||
88 | + if (key in Object.getOwnPropertyNames(orderIdMap)) { | ||
89 | + const orderId = { | ||
90 | + mainId: key, | ||
91 | + subIds: orderIdMap[key], | ||
92 | + }; | ||
93 | + orderIdList.push(orderId); | ||
94 | + } | ||
95 | + } | ||
96 | + return { | ||
97 | + ...data, | ||
98 | + orderIdList: orderIdList, | ||
99 | + }; | ||
83 | }} | 100 | }} |
84 | submitter={{ | 101 | submitter={{ |
85 | render: () => { | 102 | render: () => { |
@@ -233,7 +250,7 @@ export default ({ id, setVisible }) => { | @@ -233,7 +250,7 @@ export default ({ id, setVisible }) => { | ||
233 | /> | 250 | /> |
234 | <ProFormFieldSet | 251 | <ProFormFieldSet |
235 | name="list" | 252 | name="list" |
236 | - label="子订单号" | 253 | + label="订单号" |
237 | transform={(value: any) => ({ | 254 | transform={(value: any) => ({ |
238 | list: value, | 255 | list: value, |
239 | startTime: value[0], | 256 | startTime: value[0], |
@@ -241,21 +258,37 @@ export default ({ id, setVisible }) => { | @@ -241,21 +258,37 @@ export default ({ id, setVisible }) => { | ||
241 | })} | 258 | })} |
242 | > | 259 | > |
243 | <ProFormList | 260 | <ProFormList |
244 | - name="subOrderIds" | 261 | + name="orderIdList" |
245 | creatorButtonProps={false} | 262 | creatorButtonProps={false} |
246 | itemRender={({}, { record }) => { | 263 | itemRender={({}, { record }) => { |
247 | return ( | 264 | return ( |
248 | - <> | 265 | + <Space> |
249 | <Button | 266 | <Button |
267 | + key={record.mainId} | ||
250 | className="pl-1 pr-0" | 268 | className="pl-1 pr-0" |
251 | type="link" | 269 | type="link" |
252 | target="_blank" | 270 | target="_blank" |
253 | - href={'/order?subOrderId=' + record} | 271 | + href={'/order?id=' + record.mainId} |
254 | > | 272 | > |
255 | - {record} | 273 | + {record.mainId} |
256 | </Button> | 274 | </Button> |
275 | + ( | ||
276 | + {record.subIds.map((item) => { | ||
277 | + return ( | ||
278 | + <Button | ||
279 | + key={item} | ||
280 | + className="pl-1 pr-0" | ||
281 | + type="link" | ||
282 | + target="_blank" | ||
283 | + href={'/order?subOrderId=' + item} | ||
284 | + > | ||
285 | + {item} | ||
286 | + </Button> | ||
287 | + ); | ||
288 | + })} | ||
289 | + ) | ||
257 | <Divider type="vertical" /> | 290 | <Divider type="vertical" /> |
258 | - </> | 291 | + </Space> |
259 | ); | 292 | ); |
260 | }} | 293 | }} |
261 | > | 294 | > |
src/pages/Invoice/index.tsx
@@ -319,14 +319,14 @@ const InvoicePage = () => { | @@ -319,14 +319,14 @@ const InvoicePage = () => { | ||
319 | render: (text, record) => { | 319 | render: (text, record) => { |
320 | return [ | 320 | return [ |
321 | /*<InvoiceRecordDetailModal | 321 | /*<InvoiceRecordDetailModal |
322 | - key="detail" | ||
323 | - id={record.id} | ||
324 | - subOrderIds={record.subOrderIds} | ||
325 | - onClose={()=>{ | ||
326 | - waitDealrecordActionRef.current?.reload(); | ||
327 | - } | ||
328 | - } | ||
329 | - />*/ | 322 | + key="detail" |
323 | + id={record.id} | ||
324 | + subOrderIds={record.subOrderIds} | ||
325 | + onClose={()=>{ | ||
326 | + waitDealrecordActionRef.current?.reload(); | ||
327 | + } | ||
328 | + } | ||
329 | + />*/ | ||
330 | <a | 330 | <a |
331 | key="detail" | 331 | key="detail" |
332 | onClick={() => { | 332 | onClick={() => { |
src/pages/Order/components/InvoicingDrawerForm.tsx
@@ -9,6 +9,7 @@ import { | @@ -9,6 +9,7 @@ import { | ||
9 | postServiceInvoiceQueryCompanyInfo, | 9 | postServiceInvoiceQueryCompanyInfo, |
10 | } from '@/services'; | 10 | } from '@/services'; |
11 | import { enumToSelect } from '@/utils'; | 11 | import { enumToSelect } from '@/utils'; |
12 | +import { convertCurrency } from '@/utils/numberUtil'; | ||
12 | import { | 13 | import { |
13 | DrawerForm, | 14 | DrawerForm, |
14 | ProCard, | 15 | ProCard, |
@@ -51,7 +52,19 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -51,7 +52,19 @@ export default ({ dataList, setVisible, onClose }) => { | ||
51 | <InvoiceModal | 52 | <InvoiceModal |
52 | key={'invoicePreview'} | 53 | key={'invoicePreview'} |
53 | button={<Button type="primary"> 发票预览 </Button>} | 54 | button={<Button type="primary"> 发票预览 </Button>} |
54 | - getRecord={form.getFieldsValue} | 55 | + getRecord={() => { |
56 | + const totalPrice = dataList.reduce( | ||
57 | + (accumulator, currentValue) => { | ||
58 | + return accumulator + currentValue.subOrderPayment; | ||
59 | + }, | ||
60 | + 0, | ||
61 | + ); | ||
62 | + return { | ||
63 | + ...form.getFieldsValue(), | ||
64 | + totalPrice: totalPrice, | ||
65 | + totalPriceText: convertCurrency(totalPrice), | ||
66 | + }; | ||
67 | + }} | ||
55 | />, | 68 | />, |
56 | ...defaultDoms, | 69 | ...defaultDoms, |
57 | ]; | 70 | ]; |
@@ -148,6 +161,7 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -148,6 +161,7 @@ export default ({ dataList, setVisible, onClose }) => { | ||
148 | width="md" | 161 | width="md" |
149 | name="partyATaxid" | 162 | name="partyATaxid" |
150 | label="购方税号" | 163 | label="购方税号" |
164 | + rules={[{ required: true, message: '购方税号必填' }]} | ||
151 | placeholder="请输入名称" | 165 | placeholder="请输入名称" |
152 | /> | 166 | /> |
153 | <ProFormText | 167 | <ProFormText |
@@ -244,6 +258,7 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -244,6 +258,7 @@ export default ({ dataList, setVisible, onClose }) => { | ||
244 | name="invoiceDetails" | 258 | name="invoiceDetails" |
245 | label="开票明细" | 259 | label="开票明细" |
246 | initialValue={dataList.map((item) => { | 260 | initialValue={dataList.map((item) => { |
261 | + console.log('item:' + JSON.stringify(item)); | ||
247 | return { | 262 | return { |
248 | subOrderId: item.id, | 263 | subOrderId: item.id, |
249 | /*projectName: item.productName,*/ | 264 | /*projectName: item.productName,*/ |
@@ -251,7 +266,7 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -251,7 +266,7 @@ export default ({ dataList, setVisible, onClose }) => { | ||
251 | unit: item.unit, | 266 | unit: item.unit, |
252 | quantity: item.quantity, | 267 | quantity: item.quantity, |
253 | price: item.productPrice, | 268 | price: item.productPrice, |
254 | - totalPrice: item.totalPayment, | 269 | + totalPrice: item.subOrderPayment, |
255 | }; | 270 | }; |
256 | })} | 271 | })} |
257 | rules={[ | 272 | rules={[ |
@@ -342,13 +357,36 @@ export default ({ dataList, setVisible, onClose }) => { | @@ -342,13 +357,36 @@ export default ({ dataList, setVisible, onClose }) => { | ||
342 | label="规格型号" | 357 | label="规格型号" |
343 | rules={[ | 358 | rules={[ |
344 | { | 359 | { |
345 | - message: '规格型号不能超过20个字符!', | ||
346 | - max: 20, | ||
347 | - }, | ||
348 | - { | ||
349 | message: '规格型号不能为空!', | 360 | message: '规格型号不能为空!', |
350 | required: true, | 361 | required: true, |
351 | }, | 362 | }, |
363 | + { | ||
364 | + validator: (_, value) => { | ||
365 | + let len = 0; | ||
366 | + // 判断是否为全角字符 | ||
367 | + for (let i = 0; i < value.length; i++) { | ||
368 | + // 获取字符的Unicode值 | ||
369 | + const code = value.charCodeAt(i); | ||
370 | + // 判断是否为全角字符 | ||
371 | + if ( | ||
372 | + (code >= 0xff01 && code <= 0xff5e) || | ||
373 | + (code >= 0x4e00 && code <= 0x9fff) | ||
374 | + ) { | ||
375 | + len += 2; // 全角字符 | ||
376 | + } else { | ||
377 | + len += 1; // 半角字符 | ||
378 | + } | ||
379 | + } | ||
380 | + console.log(value); | ||
381 | + console.log(len); | ||
382 | + if (len <= 40) { | ||
383 | + return Promise.resolve(); | ||
384 | + } | ||
385 | + return Promise.reject( | ||
386 | + new Error('规格型号不能超过40个字符!'), | ||
387 | + ); | ||
388 | + }, | ||
389 | + }, | ||
352 | ]} | 390 | ]} |
353 | placeholder="请输入名称" | 391 | placeholder="请输入名称" |
354 | /> | 392 | /> |
src/pages/Order/components/OrderDrawer.tsx
@@ -1721,10 +1721,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1721,10 +1721,7 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1721 | optionItemRender(item) { | 1721 | optionItemRender(item) { |
1722 | if (item.type === 'add') { | 1722 | if (item.type === 'add') { |
1723 | return ( | 1723 | return ( |
1724 | - <div | ||
1725 | - style={{ fontSize: '11px' }} | ||
1726 | - title={item.name + '(新增商品信息)'} | ||
1727 | - > | 1724 | + <div title={item.name + '(新增商品信息)'}> |
1728 | <span style={{ color: '#333333' }}> | 1725 | <span style={{ color: '#333333' }}> |
1729 | {item.label} | 1726 | {item.label} |
1730 | </span> | 1727 | </span> |
@@ -1735,7 +1732,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | @@ -1735,7 +1732,6 @@ export default ({ onClose, data, subOrders, orderOptType }) => { | ||
1735 | } | 1732 | } |
1736 | return ( | 1733 | return ( |
1737 | <div | 1734 | <div |
1738 | - style={{ fontSize: '11px' }} | ||
1739 | title={ | 1735 | title={ |
1740 | item.label + | 1736 | item.label + |
1741 | ' | ' + | 1737 | ' | ' + |
src/services/definition.ts
@@ -768,6 +768,9 @@ export interface ApplyInvoiceDto { | @@ -768,6 +768,9 @@ export interface ApplyInvoiceDto { | ||
768 | */ | 768 | */ |
769 | isUrgentText?: string; | 769 | isUrgentText?: string; |
770 | logicDelete?: boolean; | 770 | logicDelete?: boolean; |
771 | + orderIdMap?: { | ||
772 | + [propertyName: string]: Array<number>; | ||
773 | + }; | ||
771 | /** | 774 | /** |
772 | * @description | 775 | * @description |
773 | * 买方注册地址 | 776 | * 买方注册地址 |
@@ -1500,6 +1503,9 @@ export interface InvoiceRecordDto { | @@ -1500,6 +1503,9 @@ export interface InvoiceRecordDto { | ||
1500 | */ | 1503 | */ |
1501 | isUrgentText?: string; | 1504 | isUrgentText?: string; |
1502 | logicDelete?: boolean; | 1505 | logicDelete?: boolean; |
1506 | + orderIdMap?: { | ||
1507 | + [propertyName: string]: Array<number>; | ||
1508 | + }; | ||
1503 | /** | 1509 | /** |
1504 | * @description | 1510 | * @description |
1505 | * 买方注册地址 | 1511 | * 买方注册地址 |
src/utils/numberUtil.ts
@@ -7,3 +7,104 @@ export function getRandomNumber(numDigits: number) { | @@ -7,3 +7,104 @@ export function getRandomNumber(numDigits: number) { | ||
7 | const max = Math.pow(10, numDigits) - 1; | 7 | const max = Math.pow(10, numDigits) - 1; |
8 | return Math.floor(Math.random() * (max - min + 1)) + min; | 8 | return Math.floor(Math.random() * (max - min + 1)) + min; |
9 | } | 9 | } |
10 | + | ||
11 | +//代码如下所示: | ||
12 | +export function convertCurrency(moneyParm) { | ||
13 | + let money = moneyParm; | ||
14 | + //汉字的数字 | ||
15 | + let cnNums = new Array( | ||
16 | + '零', | ||
17 | + '壹', | ||
18 | + '贰', | ||
19 | + '叁', | ||
20 | + '肆', | ||
21 | + '伍', | ||
22 | + '陆', | ||
23 | + '柒', | ||
24 | + '捌', | ||
25 | + '玖', | ||
26 | + ); | ||
27 | + //基本单位 | ||
28 | + let cnIntRadice = new Array('', '拾', '佰', '仟'); | ||
29 | + //对应整数部分扩展单位 | ||
30 | + let cnIntUnits = new Array('', '万', '亿', '兆'); | ||
31 | + //对应小数部分单位 | ||
32 | + let cnDecUnits = new Array('角', '分', '毫', '厘'); | ||
33 | + //整数金额时后面跟的字符 | ||
34 | + let cnInteger = '整'; | ||
35 | + //整型完以后的单位 | ||
36 | + let cnIntLast = '圆'; | ||
37 | + //最大处理的数字 | ||
38 | + let maxNum = 999999999999999.9999; | ||
39 | + //金额整数部分 | ||
40 | + let integerNum; | ||
41 | + //金额小数部分 | ||
42 | + let decimalNum; | ||
43 | + //输出的中文金额字符串 | ||
44 | + let chineseStr = ''; | ||
45 | + //分离金额后用的数组,预定义 | ||
46 | + let parts; | ||
47 | + if (money === '') { | ||
48 | + return ''; | ||
49 | + } | ||
50 | + money = parseFloat(money); | ||
51 | + if (money >= maxNum) { | ||
52 | + //超出最大处理数字 | ||
53 | + return ''; | ||
54 | + } | ||
55 | + if (money === 0) { | ||
56 | + chineseStr = cnNums[0] + cnIntLast + cnInteger; | ||
57 | + return chineseStr; | ||
58 | + } | ||
59 | + //转换为字符串 | ||
60 | + let moneyText = money.toString(); | ||
61 | + if (moneyText.indexOf('.') === -1) { | ||
62 | + integerNum = moneyText; | ||
63 | + decimalNum = ''; | ||
64 | + } else { | ||
65 | + parts = moneyText.split('.'); | ||
66 | + integerNum = parts[0]; | ||
67 | + decimalNum = parts[1].substr(0, 4); | ||
68 | + } | ||
69 | + //获取整型部分转换 | ||
70 | + if (parseInt(integerNum, 10) > 0) { | ||
71 | + let zeroCount = 0; | ||
72 | + let IntLen = integerNum.length; | ||
73 | + for (let i = 0; i < IntLen; i++) { | ||
74 | + const n = integerNum.substr(i, 1); | ||
75 | + const p = IntLen - i - 1; | ||
76 | + const q = p / 4; | ||
77 | + const m = p % 4; | ||
78 | + if (n === '0') { | ||
79 | + zeroCount++; | ||
80 | + } else { | ||
81 | + if (zeroCount > 0) { | ||
82 | + chineseStr += cnNums[0]; | ||
83 | + } | ||
84 | + //归零 | ||
85 | + zeroCount = 0; | ||
86 | + chineseStr += cnNums[parseInt(n)] + cnIntRadice[m]; | ||
87 | + } | ||
88 | + if (m === 0 && zeroCount < 4) { | ||
89 | + chineseStr += cnIntUnits[q]; | ||
90 | + } | ||
91 | + } | ||
92 | + chineseStr += cnIntLast; | ||
93 | + } | ||
94 | + //小数部分 | ||
95 | + if (decimalNum !== '') { | ||
96 | + let decLen = decimalNum.length; | ||
97 | + for (let k = 0; k < decLen; k++) { | ||
98 | + let n = decimalNum.substr(k, 1); | ||
99 | + if (n !== '0') { | ||
100 | + chineseStr += cnNums[Number(n)] + cnDecUnits[k]; | ||
101 | + } | ||
102 | + } | ||
103 | + } | ||
104 | + if (chineseStr === '') { | ||
105 | + chineseStr += cnNums[0] + cnIntLast + cnInteger; | ||
106 | + } else if (decimalNum === '') { | ||
107 | + chineseStr += cnInteger; | ||
108 | + } | ||
109 | + return chineseStr; | ||
110 | +} |