Commit 3498a23d251b2de57c5e4eb41e4a11a402ba087e

Authored by 曾国涛
2 parents 8496500b 82078dd3

Merge branch 'invoice'

# Conflicts:
#	src/pages/Order/index.tsx
#	src/services/definition.ts
#	src/services/request.ts
.idea/.name 0 → 100644
  1 +front_project
... ...
.idea/UniappTool.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="cn.fjdmy.uniapp.UniappProjectDataService">
  4 + <option name="generalBasePath" value="$PROJECT_DIR$" />
  5 + <option name="manifestPath" value="$PROJECT_DIR$/manifest.json" />
  6 + <option name="pagesPath" value="$PROJECT_DIR$/pages.json" />
  7 + <option name="scanNum" value="1" />
  8 + <option name="type" value="store" />
  9 + </component>
  10 +</project>
... ...
.idea/codeStyles/codeStyleConfig.xml 0 → 100644
  1 +<component name="ProjectCodeStyleConfiguration">
  2 + <state>
  3 + <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
  4 + </state>
  5 +</component>
... ...
.idea/rcb-settings.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project version="4">
  3 + <component name="ReactBuddyPluginProjectSettings">
  4 + <option name="devServerConfigs">
  5 + <DevServerState>
  6 + <option name="packageJsonPath" value="$PROJECT_DIR$/package.json" />
  7 + <option name="scriptName" value="build" />
  8 + </DevServerState>
  9 + </option>
  10 + </component>
  11 +</project>
... ...
src/pages/Invoice/components/Invoice.tsx 0 → 100644
  1 +import styled from 'styled-components';
  2 +const InvoiceTmpDiv = styled.div`
  3 + font-size: 12px;
  4 + width: 1120px;
  5 + .title {
  6 + font-size: 26px;
  7 + color: #b16363;
  8 + text-align: center;
  9 + line-height: 56px;
  10 + padding-top: 0;
  11 + }
  12 + .extra {
  13 + color: #b15b16;
  14 + .content {
  15 + color: #181818;
  16 + }
  17 + }
  18 + .height84 {
  19 + height: 110px;
  20 + }
  21 + .row {
  22 + border: 2px solid #b16363;
  23 + border-bottom: none;
  24 + color: #b15b16;
  25 + .content {
  26 + color: #181818;
  27 + }
  28 + }
  29 + .last-row {
  30 + .content {
  31 + color: #181818;
  32 + }
  33 + color: #b15b16;
  34 + border-top: 2px solid #b16363;
  35 + }
  36 + .label {
  37 + width: 78px;
  38 + display: inline-block;
  39 + text-align-last: justify;
  40 + text-align: justify;
  41 + }
  42 + .longLabel {
  43 + width: 178px;
  44 + display: inline-block;
  45 + text-align-last: justify;
  46 + text-align: justify;
  47 + }
  48 + .title-label {
  49 + width: 52px;
  50 + }
  51 +`;
  52 +const Row = styled.div`
  53 + .col_1 {
  54 + width: 2.65%;
  55 + borderleft: none;
  56 + }
  57 + .col_4 {
  58 + width: 3.75%;
  59 + }
  60 + .col_9 {
  61 + width: 7.4%;
  62 + }
  63 + .col_2 {
  64 + width: 8.33%;
  65 + }
  66 + .col_3 {
  67 + width: 12.5%;
  68 + }
  69 + .col_5 {
  70 + width: 20.83%;
  71 + }
  72 + .col_6 {
  73 + width: 42.5%;
  74 + }
  75 + .col_7 {
  76 + width: 29.16%;
  77 + }
  78 + .col_8 {
  79 + width: 33.33%;
  80 + }
  81 + .col_14 {
  82 + width: 58.33%;
  83 + }
  84 + .col_15 {
  85 + width: 42.5%;
  86 + }
  87 + .col_17 {
  88 + width: 70.83%;
  89 + }
  90 + .col_18 {
  91 + width: 100%;
  92 + }
  93 + .col_24 {
  94 + width: 100%;
  95 + }
  96 +`;
  97 +const Col = styled.span`
  98 + display: inline-block;
  99 + padding: 8px;
  100 + box-sizing: border-box;
  101 + vertical-align: middle;
  102 + border-left: 2px solid #b16363;
  103 + height: 100%;
  104 + &.no-border {
  105 + border-left: none;
  106 + }
  107 + .text-center {
  108 + text-align: center;
  109 + border-left: none;
  110 + border-right: none;
  111 + }
  112 + &.transparent-border {
  113 + border-left: 2px solid rgba(0, 0, 0, 0);
  114 + }
  115 + &.invoice-number {
  116 + border-left: none;
  117 + color: #b16363;
  118 + padding: 0 0 0 800px;
  119 + font-size: 14px;
  120 + }
  121 +`;
  122 +const UnderLine = styled.div`
  123 + border: 2px solid #b16363;
  124 + width: 325px;
  125 + height: 8px;
  126 + margin: -1% 0 2% 35%;
  127 + border-left: none;
  128 + border-right: none;
  129 +`;
  130 +const InvoiceInfo = styled.span`
  131 + color: black;
  132 +`;
  133 +const TitleDescription = styled.div`
  134 + margin-top: 4.2%;
  135 +`;
  136 +const ProjectContainer = styled.div`
  137 + width: 100%;
  138 + height: 160px;
  139 + border-top: 2px solid #b16363;
  140 + border-right: 2px solid #b16363;
  141 + border-left: 2px solid #b16363;
  142 + overflow: auto;
  143 + .single-project {
  144 + width: 100%;
  145 + height: 30px;
  146 + }
  147 +`;
  148 +export default ({ data }) => {
  149 + return (
  150 + <div>
  151 + <InvoiceTmpDiv>
  152 + <Row>
  153 + <Col className="col_18 invoice-number">
  154 + 发票号码:<InvoiceInfo>{data.invoiceNumber}</InvoiceInfo>
  155 + </Col>
  156 + <Col className="title col_18 no-border">
  157 + 电子发票(增值税专用发票)
  158 + </Col>
  159 + <UnderLine className="UnderLine">
  160 + <div></div>
  161 + </UnderLine>
  162 + </Row>
  163 + <Row className="row height84">
  164 + <Col className="col_1 no-border">购买方信息</Col>
  165 + <Col className="col_15">
  166 + <TitleDescription>
  167 + <span className="label">名称</span>:
  168 + <span className="content">{data.partyAName}</span>
  169 + </TitleDescription>
  170 + <TitleDescription>
  171 + <span className="longLabel">统一社会信用代码/纳税人识别号</span>:
  172 + <span className="content">{data.partyATaxid}</span>
  173 + </TitleDescription>
  174 + </Col>
  175 + <Col className="col_1">销售方信息</Col>
  176 + <Col className="col_6">
  177 + <TitleDescription>
  178 + <span className="label">名称</span>:
  179 + <span className="content">{data.partyBName}</span>
  180 + </TitleDescription>
  181 + <TitleDescription>
  182 + <span className="longLabel">统一社会信用代码/纳税人识别号</span>:
  183 + <span className="content">{data.partyBTaxid}</span>
  184 + </TitleDescription>
  185 + </Col>
  186 + </Row>
  187 + <Row className="row">
  188 + <Col className="col_7 no-border">
  189 + <div className="text-center">项目名称</div>
  190 + </Col>
  191 + <Col className="col_5">
  192 + <div className="text-center">规格型号</div>
  193 + </Col>
  194 + <Col className="">
  195 + <div className="text-center">单位</div>
  196 + </Col>
  197 + <Col className="">
  198 + <div className="text-center">数量</div>
  199 + </Col>
  200 + <Col className="col_2">
  201 + <div className="text-center">单价</div>
  202 + </Col>
  203 + <Col className="col_3">
  204 + <div className="text-center">金额</div>
  205 + </Col>
  206 + <Col className="">
  207 + <div className="text-center">税率/征收率</div>
  208 + </Col>
  209 + <Col className="col_2">
  210 + <div className="text-center">税额</div>
  211 + </Col>
  212 + </Row>
  213 + <Row>
  214 + <ProjectContainer>
  215 + {data &&
  216 + data.invoiceDetails?.map((item) => {
  217 + const {
  218 + taxPrice,
  219 + totalPrice,
  220 + specification,
  221 + projectName,
  222 + quantity,
  223 + price,
  224 + taxRate,
  225 + unit,
  226 + } = item;
  227 + return (
  228 + <div className="single-project" key={item.id}>
  229 + <Col
  230 + className="col_7 transparent-border"
  231 + key={'projectName'}
  232 + >
  233 + <div className="text-center">{projectName}</div>
  234 + </Col>
  235 + <Col
  236 + className="col_5 transparent-border"
  237 + key={'specification'}
  238 + >
  239 + <div className="text-center">{specification}</div>
  240 + </Col>
  241 + <Col className="col_4 transparent-border" key={'unit'}>
  242 + <div className="text-center">{unit}</div>
  243 + </Col>
  244 + <Col className="col_4 transparent-border" key={'quantity'}>
  245 + <div className="text-center">{quantity}</div>
  246 + </Col>
  247 + <Col className="col_2 transparent-border" key={'price'}>
  248 + <div className="text-center">{price}</div>
  249 + </Col>
  250 + <Col
  251 + className="col_3 transparent-border"
  252 + key={'totalPrice'}
  253 + >
  254 + <div className="text-center">{totalPrice}</div>
  255 + </Col>
  256 + <Col className="col_9 transparent-border" key={'taxRate'}>
  257 + <div className="text-center">{taxRate}</div>
  258 + </Col>
  259 + <Col className="col_2 transparent-border" key={'taxPrice'}>
  260 + <div className="text-center">{taxPrice}</div>
  261 + </Col>
  262 + </div>
  263 + );
  264 + })}
  265 + </ProjectContainer>
  266 + </Row>
  267 + <Row className="row">
  268 + <Col className="col_15 no-border">
  269 + 价税合计(大写)
  270 + <InvoiceInfo>{data.totalPriceText}</InvoiceInfo>
  271 + </Col>
  272 + <Col className="no-border">
  273 + (小写)<InvoiceInfo>¥{data.totalPrice}</InvoiceInfo>
  274 + </Col>
  275 + </Row>
  276 + <Row className="row height84">
  277 + <Col className="col_1 no-border">备注</Col>
  278 + <Col className="col_7">
  279 + <InvoiceInfo>{data.comment}</InvoiceInfo>
  280 + </Col>
  281 + </Row>
  282 + <Row className="last-row">
  283 + <Col className="col_6 no-border">
  284 + 开票人:<InvoiceInfo>{data.invoicingPerson}</InvoiceInfo>
  285 + </Col>
  286 + </Row>
  287 + </InvoiceTmpDiv>
  288 + </div>
  289 + );
  290 +};
... ...
src/pages/Invoice/components/InvoiceDetailImportModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { postServiceInvoiceImportInvoiceDetails } from '@/services';
  3 +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components';
  4 +import { Button, Form, message } from 'antd';
  5 +
  6 +export default ({ recordId }) => {
  7 + const [form] = Form.useForm();
  8 + return (
  9 + <ModalForm
  10 + title="新建表单"
  11 + trigger={<Button type="primary">导入明细</Button>}
  12 + form={form}
  13 + autoFocusFirstInput
  14 + modalProps={{
  15 + destroyOnClose: true,
  16 + onCancel: () => console.log('run'),
  17 + }}
  18 + submitTimeout={2000}
  19 + onFinish={async (values) => {
  20 + const formData = new FormData();
  21 + // console.log(fileList[0] as RcFile)
  22 + // formData.append('file', fileList[0] as RcFile);
  23 + formData.append('invoiceRecordId', recordId);
  24 + formData.append('detailsExcel', values.detailsExcel[0].originFileObj);
  25 + // You can use any AJAX library you like
  26 + const res = await postServiceInvoiceImportInvoiceDetails({
  27 + data: formData,
  28 + headers: {
  29 + 'Content-Type':
  30 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  31 + },
  32 + });
  33 + if (res.result === RESPONSE_CODE.SUCCESS) {
  34 + message.success('导入成功');
  35 + return true;
  36 + }
  37 + }}
  38 + >
  39 + <ProFormUploadDragger name="detailsExcel" label="导入明细表" />
  40 + </ModalForm>
  41 + );
  42 +};
... ...
src/pages/Invoice/components/InvoiceDetailTable.tsx 0 → 100644
  1 +import InvoiceDetailImportModal from '@/pages/Invoice/components/InvoiceDetailImportModal';
  2 +import { InvoiceProjectSelect } from '@/pages/Invoice/components/InvoiceProjectSelect';
  3 +import {
  4 + ActionType,
  5 + EditableProTable,
  6 + ProColumns,
  7 +} from '@ant-design/pro-components';
  8 +import { useEffect, useRef, useState } from 'react';
  9 +
  10 +export default ({ recordId, details, updateDetails, readOnly }) => {
  11 + const [editableKeys, setEditableRowKeys] = useState([]);
  12 + const [invoiceProject, setInvoiceProject] = useState({});
  13 + const ref = useRef<ActionType>();
  14 + useEffect(() => {
  15 + updateDetails(details);
  16 + }, []);
  17 +
  18 + useEffect(() => {
  19 + setEditableRowKeys(details?.map((item) => item.tid));
  20 + }, [details]);
  21 + const columns: ProColumns[] = [
  22 + {
  23 + title: '项目名称',
  24 + dataIndex: 'projectName',
  25 + width: 200,
  26 + ellipsis: true,
  27 + readonly: readOnly,
  28 + renderFormItem: () => {
  29 + return (
  30 + <InvoiceProjectSelect
  31 + setInvoiceProject={setInvoiceProject}
  32 + readOnly={readOnly}
  33 + />
  34 + );
  35 + },
  36 + },
  37 + {
  38 + title: '规格型号',
  39 + readonly: readOnly,
  40 + dataIndex: 'specification',
  41 + valueType: 'text',
  42 + ellipsis: true,
  43 + },
  44 + {
  45 + title: '单位',
  46 + readonly: readOnly,
  47 + dataIndex: 'unit',
  48 + valueType: 'text',
  49 + ellipsis: true,
  50 + },
  51 + {
  52 + title: '数量',
  53 + readonly: readOnly,
  54 + dataIndex: 'quantity',
  55 + valueType: 'digit',
  56 + ellipsis: true,
  57 + },
  58 + {
  59 + title: '单价',
  60 + readonly: readOnly,
  61 + dataIndex: 'price',
  62 + valueType: 'digit',
  63 + ellipsis: true,
  64 + },
  65 + {
  66 + title: '金额',
  67 + readonly: readOnly,
  68 + dataIndex: 'totalPrice',
  69 + valueType: 'digit',
  70 + ellipsis: true,
  71 + },
  72 + {
  73 + title: '税率/征收率',
  74 + readonly: true,
  75 + dataIndex: 'taxRate',
  76 + valueType: () => ({
  77 + type: 'percent',
  78 + }),
  79 + ellipsis: true,
  80 + },
  81 + {
  82 + title: '税额',
  83 + readonly: true,
  84 + dataIndex: 'taxPrice',
  85 + valueType: 'digit',
  86 + ellipsis: true,
  87 + },
  88 + {
  89 + title: '操作',
  90 + valueType: 'option',
  91 + width: 100,
  92 + render: () => {
  93 + return null;
  94 + },
  95 + },
  96 + ];
  97 +
  98 + return (
  99 + <>
  100 + <EditableProTable
  101 + columns={columns}
  102 + actionRef={ref}
  103 + rowKey="tid"
  104 + scroll={{
  105 + x: 960,
  106 + }}
  107 + value={details}
  108 + controlled={true}
  109 + recordCreatorProps={
  110 + readOnly
  111 + ? false
  112 + : {
  113 + newRecordType: 'dataSource',
  114 + record: () => ({
  115 + tid: Date.now(),
  116 + }),
  117 + }
  118 + }
  119 + toolBarRender={() => {
  120 + return [
  121 + <InvoiceDetailImportModal key={'import'} recordId={recordId} />,
  122 + ];
  123 + }}
  124 + editable={{
  125 + type: 'multiple',
  126 + editableKeys,
  127 + actionRender: (row, config, defaultDoms) => {
  128 + return [defaultDoms.delete];
  129 + },
  130 +
  131 + onValuesChange: (record, recordList) => {
  132 + //修改recordList中tid为record.tid的元素,将它的specification属性设置为invoiceProject的specification属性
  133 + 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;
  156 + });
  157 + updateDetails(records);
  158 + },
  159 + }}
  160 + />
  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>}*/}
  174 + </>
  175 + );
  176 +};
... ...
src/pages/Invoice/components/InvoiceModal.tsx 0 → 100644
  1 +import Invoice from '@/pages/Invoice/components/Invoice';
  2 +import { postServiceInvoiceGetInvoiceRecord } from '@/services';
  3 +import { ModalForm } from '@ant-design/pro-components';
  4 +import { Form } from 'antd';
  5 +import { useEffect, useState } from 'react';
  6 +
  7 +export default ({ recordId, getRecord, button }) => {
  8 + const [data, setData] = useState<any>({});
  9 + 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) {
  19 + getData();
  20 + }
  21 + }, []);
  22 + const [form] = Form.useForm();
  23 + return (
  24 + <ModalForm
  25 + title="预览发票"
  26 + trigger={button ? button : <a type="primary">预览</a>}
  27 + onOpenChange={(open) => {
  28 + if (open && getRecord) {
  29 + setData(getRecord());
  30 + }
  31 + }}
  32 + width={1200}
  33 + form={form}
  34 + autoFocusFirstInput
  35 + modalProps={{
  36 + destroyOnClose: true,
  37 + }}
  38 + >
  39 + <hr />
  40 + <Invoice data={data} />
  41 + </ModalForm>
  42 + );
  43 +};
... ...
src/pages/Invoice/components/InvoiceProjectSelect.tsx 0 → 100644
  1 +import { postServiceConstListInvoiceDetailNames } from '@/services';
  2 +import { Select, Tooltip } from 'antd';
  3 +import { useState } from 'react';
  4 +
  5 +export const InvoiceProjectSelect = ({
  6 + readOnly,
  7 + value,
  8 + onChange,
  9 + setInvoiceProject,
  10 +}) => {
  11 + const [options, setOptions] = useState<any[]>([]);
  12 + // 定义防抖函数
  13 + let timeoutId = null;
  14 + const fetchOptions = async (keywords) => {
  15 + clearTimeout(timeoutId);
  16 + timeoutId = setTimeout(async () => {
  17 + const res = await postServiceConstListInvoiceDetailNames({
  18 + data: {
  19 + nameLike: keywords,
  20 + },
  21 + });
  22 + const data = res.data;
  23 + console.log('invoiceProject' + JSON.stringify(data));
  24 + setOptions(
  25 + data.map((item) => {
  26 + return {
  27 + label:
  28 + '*' +
  29 + item.productAndServiceCatagoryAbbreviation +
  30 + '*' +
  31 + item?.name,
  32 + value: item.id,
  33 + ...item,
  34 + };
  35 + }),
  36 + );
  37 + // 这里可以放置实际的搜索逻辑,比如发起网络请求等
  38 + }, 500); // 设置延迟时间,单位毫秒
  39 + };
  40 +
  41 + return readOnly ? (
  42 + <Tooltip title={value}>{value}</Tooltip>
  43 + ) : (
  44 + <Select
  45 + key="project"
  46 + /*readonly={readonly}*/
  47 + showSearch
  48 + placeholder="请选择开票项目"
  49 + filterOption={(input, option) => (option?.label ?? '').includes(input)}
  50 + onChange={(e) => {
  51 + setInvoiceProject(options.find((item) => item.value === e));
  52 + onChange(e);
  53 + }}
  54 + defaultValue={value}
  55 + options={options}
  56 + onSearch={(e) => {
  57 + fetchOptions(e);
  58 + }}
  59 + />
  60 + );
  61 +};
... ...
src/pages/Invoice/components/InvoiceRecordDetailModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import InvoiceDetailTable from '@/pages/Invoice/components/InvoiceDetailTable';
  3 +import {
  4 + postServiceConstGetPayeeEnum,
  5 + postServiceConstInvoiceType,
  6 + postServiceConstInvoicingType,
  7 + postServiceInvoiceGetInvoiceRecord,
  8 + postServiceInvoiceModifyRecord,
  9 +} from '@/services';
  10 +import { enumToSelect } from '@/utils';
  11 +import {
  12 + ModalForm,
  13 + ProCard,
  14 + ProForm,
  15 + ProFormFieldSet,
  16 + ProFormInstance,
  17 + ProFormList,
  18 + ProFormSelect,
  19 + ProFormText,
  20 + ProFormTextArea,
  21 +} from '@ant-design/pro-components';
  22 +import { Button, Divider, Form, Space, message } from 'antd';
  23 +import { useEffect, useRef, useState } from 'react';
  24 +
  25 +export default ({ id, setVisible }) => {
  26 + const [readOnly, setReadOnly] = useState(true);
  27 + const [detailTableData, setDetailTableData] = useState([]);
  28 + const [payees, setPayees] = useState([]);
  29 + const [payeeNameOptions, setPayeeNameOptions] = useState([]);
  30 + const formRef = useRef<ProFormInstance>();
  31 + const [form] = Form.useForm();
  32 +
  33 + useEffect(() => {
  34 + console.log('id' + id);
  35 + const getPayees = async () => {
  36 + let res = await postServiceConstGetPayeeEnum();
  37 + setPayees(res.data);
  38 + let payeeNameOptions = res.data.map((item) => {
  39 + return {
  40 + label: item.payeeName,
  41 + value: item.payeeName,
  42 + };
  43 + });
  44 + setPayeeNameOptions(payeeNameOptions);
  45 + };
  46 + getPayees();
  47 + }, []);
  48 + const getRecord = async (id) => {
  49 + let ret = await postServiceInvoiceGetInvoiceRecord({
  50 + query: {
  51 + id: id,
  52 + },
  53 + });
  54 + const updatedInvoiceDetails = ret.data.invoiceDetails?.map(
  55 + (item, index) => ({
  56 + ...item, // 保留原有属性
  57 + tid: index + 1, // 添加tid属性,这里以T开头,后面跟索引+1,仅作示例,实际可根据需求生成tid
  58 + }),
  59 + );
  60 + setDetailTableData(updatedInvoiceDetails);
  61 + };
  62 + useEffect(() => {
  63 + getRecord(id);
  64 + }, []);
  65 +
  66 + const updateDetails = (values) => {
  67 + setDetailTableData(values);
  68 + };
  69 + return (
  70 + <>
  71 + <Space>
  72 + <ModalForm
  73 + open
  74 + title="发票详情"
  75 + formRef={formRef}
  76 + request={async () => {
  77 + let ret = await postServiceInvoiceGetInvoiceRecord({
  78 + query: {
  79 + id: id,
  80 + },
  81 + });
  82 + return ret.data;
  83 + }}
  84 + submitter={{
  85 + render: () => {
  86 + return [
  87 + <Button
  88 + type={readOnly ? 'primary' : 'default'}
  89 + key="ok"
  90 + onClick={() => {
  91 + setReadOnly(!readOnly);
  92 + }}
  93 + >
  94 + {readOnly ? '编辑' : '取消编辑'}
  95 + </Button>,
  96 + <>
  97 + {!readOnly && (
  98 + <Button
  99 + type="primary"
  100 + key="submit"
  101 + onClick={async () => {
  102 + const result = await postServiceInvoiceModifyRecord({
  103 + data: {
  104 + ...form.getFieldsValue(),
  105 + invoiceDetails: [...detailTableData],
  106 + },
  107 + });
  108 + if (result.result === RESPONSE_CODE.SUCCESS) {
  109 + message.success('提交成功');
  110 + }
  111 + setVisible(false);
  112 + return true;
  113 + }}
  114 + >
  115 + 提交
  116 + </Button>
  117 + )}
  118 + </>,
  119 + /*<Button
  120 + type={'default'}
  121 + key="ok"
  122 + onClick={() => {
  123 + setVisible(false)
  124 + }}
  125 + >
  126 + 取消
  127 + </Button>,*/
  128 + ];
  129 + },
  130 + }}
  131 + width={1200}
  132 + form={form}
  133 + autoFocusFirstInput
  134 + modalProps={{
  135 + destroyOnClose: true,
  136 + onCancel: () => {
  137 + setVisible(false);
  138 + },
  139 + }}
  140 + grid={true}
  141 + layout="horizontal"
  142 + rowProps={{
  143 + gutter: [0, 0],
  144 + }}
  145 + submitTimeout={2000}
  146 + onFinish={async (values) => {
  147 + const result = await postServiceInvoiceModifyRecord({
  148 + data: {
  149 + ...values,
  150 + invoiceDetails: {
  151 + ...detailTableData,
  152 + },
  153 + },
  154 + });
  155 + if (result.result === RESPONSE_CODE.SUCCESS) {
  156 + message.success('提交成功');
  157 + }
  158 + return true;
  159 + }}
  160 + >
  161 + <ProCard
  162 + title="基础信息"
  163 + bordered
  164 + //
  165 + headStyle={{}}
  166 + headerBordered
  167 + size={'small'}
  168 + >
  169 + <ProForm.Group>
  170 + <ProFormText
  171 + readonly
  172 + name="id"
  173 + label="订单批号"
  174 + colProps={{
  175 + span: 5,
  176 + }}
  177 + tooltip="最长为 24 位"
  178 + placeholder="请输入名称"
  179 + />
  180 +
  181 + <ProFormText
  182 + readonly
  183 + width="md"
  184 + colProps={{
  185 + span: 5,
  186 + }}
  187 + name="createByName"
  188 + label="销售代表"
  189 + placeholder="请输入名称"
  190 + />
  191 + <ProFormText
  192 + readonly
  193 + width="md"
  194 + colProps={{
  195 + span: 5,
  196 + }}
  197 + name="createTime"
  198 + label="申请时间"
  199 + placeholder="请输入名称"
  200 + />
  201 + <ProFormSelect
  202 + name="type"
  203 + label="发票类型"
  204 + colProps={{
  205 + span: 5,
  206 + }}
  207 + readonly={readOnly}
  208 + request={async () => {
  209 + let invoiceTypeRet = await postServiceConstInvoiceType();
  210 + return enumToSelect(invoiceTypeRet.data);
  211 + }}
  212 + placeholder="Please select a country"
  213 + rules={[
  214 + { required: true, message: 'Please select your country!' },
  215 + ]}
  216 + />
  217 + <ProFormSelect
  218 + name="invoicingType"
  219 + readonly={readOnly}
  220 + label="开具类型"
  221 + colProps={{
  222 + span: 4,
  223 + }}
  224 + request={async () => {
  225 + let invoicingTypeRet = await postServiceConstInvoicingType();
  226 + let options = enumToSelect(invoicingTypeRet.data);
  227 + return options;
  228 + }}
  229 + placeholder="Please select a country"
  230 + rules={[
  231 + { required: true, message: 'Please select your country!' },
  232 + ]}
  233 + />
  234 + <ProFormFieldSet
  235 + name="list"
  236 + label="子订单号"
  237 + transform={(value: any) => ({
  238 + list: value,
  239 + startTime: value[0],
  240 + endTime: value[1],
  241 + })}
  242 + >
  243 + <ProFormList
  244 + name="subOrderIds"
  245 + creatorButtonProps={false}
  246 + itemRender={({}, { record }) => {
  247 + return (
  248 + <>
  249 + <Button
  250 + className="pl-1 pr-0"
  251 + type="link"
  252 + target="_blank"
  253 + href={'/order?subOrderId=' + record}
  254 + >
  255 + {record}
  256 + </Button>
  257 + <Divider type="vertical" />
  258 + </>
  259 + );
  260 + }}
  261 + >
  262 + <ProFormText allowClear={false} width="xs" name={['name']} />
  263 + </ProFormList>
  264 + </ProFormFieldSet>
  265 + </ProForm.Group>
  266 + </ProCard>
  267 + <hr />
  268 + <ProCard title="购方信息" bordered headerBordered size={'small'}>
  269 + <ProForm.Group>
  270 + <ProFormText
  271 + readonly={readOnly}
  272 + width="md"
  273 + colProps={{
  274 + span: 8,
  275 + }}
  276 + name="partyAName"
  277 + label="购方名称"
  278 + placeholder="请输入名称"
  279 + />
  280 + <ProFormText
  281 + readonly={readOnly}
  282 + width="md"
  283 + colProps={{
  284 + span: 8,
  285 + }}
  286 + name="partyATaxid"
  287 + label="购方税号"
  288 + placeholder="请输入名称"
  289 + />
  290 + <ProFormText
  291 + readonly={readOnly}
  292 + width="md"
  293 + colProps={{
  294 + span: 8,
  295 + }}
  296 + label="开户银行"
  297 + name={'partyAOpenBank'}
  298 + placeholder="请输入名称"
  299 + />
  300 + <ProFormText
  301 + readonly={readOnly}
  302 + width="md"
  303 + colProps={{
  304 + span: 8,
  305 + }}
  306 + name="partyABankAccount"
  307 + label="银行账号"
  308 + placeholder="请输入名称"
  309 + />
  310 + <ProFormText
  311 + readonly={readOnly}
  312 + width="md"
  313 + colProps={{
  314 + span: 8,
  315 + }}
  316 + name="partyAAddress"
  317 + label="购方地址"
  318 + placeholder="请输入名称"
  319 + />
  320 + <ProFormText
  321 + readonly={readOnly}
  322 + width="md"
  323 + colProps={{
  324 + span: 8,
  325 + }}
  326 + name="partyAPhoneNumber"
  327 + label="电话"
  328 + placeholder="请输入名称"
  329 + />
  330 + </ProForm.Group>
  331 + </ProCard>
  332 + <hr />
  333 + <ProCard title="销方信息" bordered headerBordered size={'small'}>
  334 + <ProForm.Group>
  335 + <ProFormSelect
  336 + readonly={readOnly}
  337 + width="md"
  338 + name="partyBName"
  339 + options={payeeNameOptions}
  340 + onChange={(value: any) => {
  341 + let payee = payees.find((item: any) => {
  342 + return item.payeeName === value;
  343 + });
  344 + console.log(JSON.stringify(payee));
  345 + form.setFieldsValue({
  346 + partyBTaxid: payee.taxId,
  347 + partyBBankAccount: payee.bankAccount,
  348 + partyBOpenBank: payee.openBank,
  349 + partyBAddress: payee.address,
  350 + partyBPhoneNumber: payee.phoneNumber,
  351 + });
  352 + }}
  353 + label="销方名称"
  354 + colProps={{
  355 + span: 8,
  356 + }}
  357 + placeholder="请输入名称"
  358 + />
  359 +
  360 + <ProFormText
  361 + readonly
  362 + width="md"
  363 + name="partyBTaxid"
  364 + label="销方税号"
  365 + colProps={{
  366 + span: 8,
  367 + }}
  368 + placeholder="请输入名称"
  369 + />
  370 + <ProFormText
  371 + readonly
  372 + width="md"
  373 + name="partyBOpenBank"
  374 + label="开户银行"
  375 + colProps={{
  376 + span: 8,
  377 + }}
  378 + placeholder="请输入名称"
  379 + />
  380 + <ProFormText
  381 + readonly
  382 + width="md"
  383 + name="partyBBankAccount"
  384 + label="银行账号"
  385 + colProps={{
  386 + span: 8,
  387 + }}
  388 + placeholder="请输入名称"
  389 + />
  390 + <ProFormText
  391 + readonly
  392 + width="md"
  393 + colProps={{
  394 + span: 8,
  395 + }}
  396 + name="partyBAddress"
  397 + label="销方地址"
  398 + placeholder="请输入名称"
  399 + />
  400 + <ProFormText
  401 + readonly
  402 + width="md"
  403 + colProps={{
  404 + span: 8,
  405 + }}
  406 + name="partyBPhoneNumber"
  407 + label="电话"
  408 + placeholder="请输入名称"
  409 + />
  410 + </ProForm.Group>
  411 + </ProCard>
  412 + <hr />
  413 + <ProCard title="发票明细" bordered headerBordered size={'small'}>
  414 + <InvoiceDetailTable
  415 + recordId={id}
  416 + details={detailTableData}
  417 + updateDetails={updateDetails}
  418 + readOnly={readOnly}
  419 + />
  420 + </ProCard>
  421 + <hr />
  422 + <ProCard title="备注" bordered headerBordered size={'small'}>
  423 + <ProFormTextArea
  424 + readonly={readOnly}
  425 + name="comment"
  426 + placeholder="请输入备注"
  427 + />
  428 + </ProCard>
  429 + </ModalForm>
  430 + </Space>
  431 + </>
  432 + );
  433 +};
... ...
src/pages/Invoice/components/InvoicingModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { postServiceInvoiceInvoicing } from '@/services';
  3 +import { ModalForm } from '@ant-design/pro-components';
  4 +import { Button, Form, message } from 'antd';
  5 +
  6 +export default ({ selectedRowKeys, reloadRecordTable }) => {
  7 + const [form] = Form.useForm<{ name: string; company: string }>();
  8 + return (
  9 + <ModalForm<{
  10 + name: string;
  11 + company: string;
  12 + }>
  13 + title="开票"
  14 + trigger={
  15 + <Button type="primary" disabled={selectedRowKeys?.length === 0}>
  16 + 开票
  17 + </Button>
  18 + }
  19 + form={form}
  20 + autoFocusFirstInput
  21 + modalProps={{
  22 + destroyOnClose: true,
  23 + onCancel: () => console.log('run'),
  24 + }}
  25 + submitTimeout={2000}
  26 + onFinish={async () => {
  27 + let res = await postServiceInvoiceInvoicing({
  28 + data: {
  29 + invoiceRecordIds: selectedRowKeys,
  30 + },
  31 + });
  32 + if (res.result === RESPONSE_CODE.SUCCESS) {
  33 + message.success(res.message);
  34 + }
  35 + reloadRecordTable();
  36 + message.success('提交成功');
  37 + return true;
  38 + }}
  39 + ></ModalForm>
  40 + );
  41 +};
... ...
src/pages/Invoice/index.tsx
... ... @@ -2,6 +2,9 @@ import ButtonConfirm from &#39;@/components/ButtomConfirm&#39;;
2 2 import EllipsisDiv from '@/components/Div/EllipsisDiv';
3 3 import { RESPONSE_CODE } from '@/constants/enum';
4 4 import AddInvoiceDrawerForm from '@/pages/Invoice/components/AddInvoiceDrawerForm';
  5 +import InvoiceModal from '@/pages/Invoice/components/InvoiceModal';
  6 +import InvoiceRecordDetailModal from '@/pages/Invoice/components/InvoiceRecordDetailModal';
  7 +import InvoicingModal from '@/pages/Invoice/components/InvoicingModal';
5 8 import {
6 9 BANK_STATEMENT_COLUMNS,
7 10 INVOICE_COLUMNS,
... ... @@ -11,15 +14,28 @@ import {
11 14 postServiceBankStatementDeleteBankStatement,
12 15 postServiceBankStatementEditBankStatement,
13 16 postServiceBankStatementQueryBankStatement,
  17 + postServiceConstAfterInvoicingInvoiceRecordStatus,
  18 + postServiceConstBeforeInvoicingInvoiceRecordStatus,
  19 + postServiceConstInvoiceType,
  20 + postServiceConstInvoicingType,
14 21 postServiceInvoiceDeleteInvoice,
  22 + postServiceInvoiceInvoicing,
15 23 postServiceInvoiceQueryInvoice,
  24 + postServiceInvoiceQueryInvoiceRecordList,
  25 + postServiceOrderQuerySalesCode,
16 26 } from '@/services';
17   -import { enumValueToLabel, formatDateTime } from '@/utils';
  27 +import { excelExport } from '@/services/exportRequest';
  28 +import {
  29 + enumToProTableEnumValue,
  30 + enumToSelect,
  31 + enumValueToLabel,
  32 + formatDateTime,
  33 +} from '@/utils';
18 34 import { formatDate } from '@/utils/time';
19 35 import { PlusOutlined } from '@ant-design/icons';
20   -import { ActionType, ProTable } from '@ant-design/pro-components';
21   -import { Button, Tabs, message } from 'antd';
22   -import { useRef, useState } from 'react';
  36 +import { ActionType, ModalForm, ProTable } from '@ant-design/pro-components';
  37 +import { Button, Space, Table, Tabs, message } from 'antd';
  38 +import { useEffect, useRef, useState } from 'react';
23 39 import { INVOCING_STATUS, PAYEE_OPTIONS } from '../Order/constant';
24 40 import BankImportModal from './components/BankImportModal';
25 41 import InvoiceVerificationModal from './components/InvoiceVerificationModal';
... ... @@ -28,10 +44,51 @@ import &#39;./index.less&#39;;
28 44 const InvoicePage = () => {
29 45 const invoiceActionRef = useRef<ActionType>();
30 46 const bankActionRef = useRef<ActionType>();
  47 + const waitDealrecordActionRef = useRef<ActionType>();
  48 + const processedRecordRef = useRef<ActionType>();
  49 + const [invoiceTypeValueEnum, setInvoiceTypeValueEnum] = useState({});
  50 + const [invoicingTypeValueEnum, setInvoicingTypeValueEnum] = useState({});
  51 + const [salesCodeValueEnum, setSalesCodeValueEnum] = useState({});
31 52 const [bankImportModalVisible, setBankImportModalVisible] = useState(false);
32 53 const [invoiceVerificationVisible, setInvoiceVerificationVisible] =
33 54 useState(false);
34 55 const [invoiceId, setInvoiceId] = useState(undefined);
  56 + const [invoiceRecordDetailVisible, setInvoiceRecordDetailVisible] =
  57 + useState(false);
  58 + const [invoiceRecord, setInvoiceRecord] = useState({});
  59 + const [messageApi, contextHolder] = message.useMessage();
  60 +
  61 + useEffect(() => {
  62 + async function extracted() {
  63 + let invoiceTypeRet = await postServiceConstInvoiceType();
  64 + setInvoiceTypeValueEnum(invoiceTypeRet.data);
  65 + }
  66 + extracted().catch(console.error);
  67 + }, []);
  68 +
  69 + useEffect(() => {
  70 + async function extracted() {
  71 + let invoicingTypeRet = await postServiceConstInvoicingType();
  72 + setInvoicingTypeValueEnum(invoicingTypeRet.data);
  73 + }
  74 + extracted().catch(console.error);
  75 + }, []);
  76 +
  77 + useEffect(() => {
  78 + async function extracted() {
  79 + const res = await postServiceOrderQuerySalesCode();
  80 + let map = {};
  81 + res.data?.forEach((item) => {
  82 + map[item.userName] = {
  83 + text: item.userName,
  84 + status: item.userName,
  85 + };
  86 + });
  87 + setSalesCodeValueEnum(map);
  88 + }
  89 +
  90 + extracted().catch(console.error);
  91 + }, []);
35 92  
36 93 const reloadInvoiceTable = () => {
37 94 invoiceActionRef.current?.reload();
... ... @@ -40,6 +97,10 @@ const InvoicePage = () =&gt; {
40 97 const reloadBankStatementTable = () => {
41 98 bankActionRef.current?.reload();
42 99 };
  100 + const reloadRecordTable = () => {
  101 + waitDealrecordActionRef.current?.reload();
  102 + processedRecordRef.current?.reload();
  103 + };
43 104  
44 105 const getTableCellText = (target: any) => {
45 106 if (!target) {
... ... @@ -53,6 +114,454 @@ const InvoicePage = () =&gt; {
53 114 return target;
54 115 };
55 116  
  117 + const waitDealRecordColumns = [
  118 + {
  119 + dataIndex: 'index',
  120 + valueType: 'indexBorder',
  121 + hideInSearch: true,
  122 + ellipsis: true,
  123 + width: 48,
  124 + },
  125 + {
  126 + title: '开票编号',
  127 + valueType: 'text',
  128 + dataIndex: 'id',
  129 + copyable: true,
  130 + hideInSearch: true,
  131 + ellipsis: true,
  132 + width: 100,
  133 + },
  134 + {
  135 + title: '发票状态',
  136 + valueType: 'Text',
  137 + dataIndex: 'statusText',
  138 + ellipsis: true,
  139 + hideInSearch: true,
  140 + },
  141 + {
  142 + title: '申请开票时间',
  143 + dataIndex: 'createTime',
  144 + valueType: 'dateTime',
  145 + hideInSearch: true,
  146 + ellipsis: true,
  147 + },
  148 + {
  149 + title: '销售代表',
  150 + valueType: 'text',
  151 + hideInSearch: true,
  152 + ellipsis: true,
  153 + dataIndex: 'createByName',
  154 + },
  155 + {
  156 + title: '购方名称',
  157 + valueType: 'text',
  158 + dataIndex: 'partyAName',
  159 + hideInSearch: true,
  160 + ellipsis: true,
  161 + },
  162 + {
  163 + title: '购方税号',
  164 + valueType: 'text',
  165 + hideInSearch: true,
  166 + dataIndex: 'partyATaxid',
  167 + ellipsis: true,
  168 + },
  169 + {
  170 + title: '收款单位',
  171 + valueType: 'text',
  172 + hideInSearch: true,
  173 + dataIndex: 'partyBName',
  174 + ellipsis: true,
  175 + },
  176 + {
  177 + title: '开票金额',
  178 + valueType: 'money',
  179 + dataIndex: 'price',
  180 + hideInSearch: true,
  181 + ellipsis: true,
  182 + },
  183 + {
  184 + title: '开具类型',
  185 + valueType: 'Text',
  186 + dataIndex: 'invoicingTypeText',
  187 + hideInSearch: true,
  188 + ellipsis: true,
  189 + },
  190 + {
  191 + title: '发票类型',
  192 + valueType: 'Text',
  193 + dataIndex: 'typeText',
  194 + hideInSearch: true,
  195 + ellipsis: true,
  196 + },
  197 + {
  198 + title: '是否加急',
  199 + valueType: 'Text',
  200 + dataIndex: 'isUrgentText',
  201 + hideInSearch: true,
  202 + ellipsis: true,
  203 + },
  204 + {
  205 + title: '申请备注',
  206 + valueType: 'text',
  207 + dataIndex: 'applyInvoicingNotes',
  208 + hideInSearch: true,
  209 + ellipsis: true,
  210 + },
  211 + {
  212 + title: '购方名称',
  213 + valueType: 'Text',
  214 + dataIndex: 'partyANameLike',
  215 + hideInTable: true,
  216 + },
  217 + {
  218 + title: '收款单位',
  219 + valueType: 'select',
  220 + dataIndex: 'partyB',
  221 + filters: true,
  222 + onFilter: true,
  223 + hideInTable: true,
  224 + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS),
  225 + },
  226 + {
  227 + title: '主订单号',
  228 + valueType: 'Text',
  229 + dataIndex: 'mainOrderId',
  230 + hideInTable: true,
  231 + },
  232 + {
  233 + title: '子订单号',
  234 + valueType: 'Text',
  235 + dataIndex: 'subOrderId',
  236 + hideInTable: true,
  237 + },
  238 + {
  239 + title: '销售代表',
  240 + valueType: 'select',
  241 + dataIndex: 'salesCode',
  242 + filters: true,
  243 + onFilter: true,
  244 + hideInTable: true,
  245 + valueEnum: salesCodeValueEnum,
  246 + },
  247 + {
  248 + title: '发票类型',
  249 + valueType: 'select',
  250 + dataIndex: 'type',
  251 + filters: true,
  252 + onFilter: true,
  253 + hideInTable: true,
  254 + valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum),
  255 + },
  256 + {
  257 + title: '开具类型',
  258 + valueType: 'select',
  259 + dataIndex: 'invoicingType',
  260 + filters: true,
  261 + onFilter: true,
  262 + hideInTable: true,
  263 + valueEnum: enumToProTableEnumValue(invoicingTypeValueEnum),
  264 + },
  265 + {
  266 + title: '开票状态',
  267 + valueType: 'select',
  268 + dataIndex: 'status',
  269 + filters: true,
  270 + onFilter: true,
  271 + hideInTable: true,
  272 + request: async () => {
  273 + const res = await postServiceConstBeforeInvoicingInvoiceRecordStatus();
  274 + return enumToSelect(res.data);
  275 + },
  276 + },
  277 + {
  278 + title: '是否加急',
  279 + valueType: 'select',
  280 + dataIndex: 'isUrgent',
  281 + filters: true,
  282 + onFilter: true,
  283 + hideInTable: true,
  284 + valueEnum: {
  285 + true: {
  286 + text: '是',
  287 + status: true,
  288 + },
  289 + false: {
  290 + text: '否',
  291 + status: false,
  292 + },
  293 + },
  294 + },
  295 + {
  296 + title: '申请开票时间',
  297 + dataIndex: 'createTime',
  298 + valueType: 'dateRange',
  299 + width: 200,
  300 + hideInTable: true,
  301 + search: {
  302 + transform: (value) => {
  303 + if (value) {
  304 + return {
  305 + createTimeGe: value[0],
  306 + createTimeLe: value[1],
  307 + };
  308 + }
  309 + },
  310 + },
  311 + },
  312 + {
  313 + title: '操作',
  314 + valueType: 'option',
  315 + key: 'option',
  316 + render: (text, record) => {
  317 + return [
  318 + /*<InvoiceRecordDetailModal
  319 + key="detail"
  320 + id={record.id}
  321 + subOrderIds={record.subOrderIds}
  322 + onClose={()=>{
  323 + waitDealrecordActionRef.current?.reload();
  324 + }
  325 + }
  326 + />*/
  327 + <a
  328 + key="detail"
  329 + onClick={() => {
  330 + setInvoiceRecordDetailVisible(true);
  331 + setInvoiceRecord(record);
  332 + }}
  333 + >
  334 + 详情
  335 + </a>,
  336 + <InvoiceModal key="invoiceModal" recordId={record.id} />,
  337 + ];
  338 + },
  339 + },
  340 + ];
  341 +
  342 + const processedRecordColumns = [
  343 + {
  344 + dataIndex: 'index',
  345 + valueType: 'indexBorder',
  346 + },
  347 + {
  348 + title: '开票编号',
  349 + valueType: 'text',
  350 + dataIndex: 'id',
  351 + copyable: true,
  352 + ellipsis: true,
  353 + },
  354 + {
  355 + title: '发票号码',
  356 + valueType: 'text',
  357 + dataIndex: 'invoiceNumber',
  358 + copyable: true,
  359 + ellipsis: true,
  360 + },
  361 + {
  362 + title: '开票日期',
  363 + dataIndex: 'invoicingTime',
  364 + valueType: 'dateTime',
  365 + hideInSearch: true,
  366 + ellipsis: true,
  367 + },
  368 + {
  369 + title: '发票类型',
  370 + valueType: 'Text',
  371 + dataIndex: 'typeText',
  372 + hideInSearch: true,
  373 + ellipsis: true,
  374 + },
  375 + {
  376 + title: '发票状态',
  377 + valueType: 'Text',
  378 + dataIndex: 'statusText',
  379 + hideInSearch: true,
  380 + ellipsis: true,
  381 + },
  382 + {
  383 + title: '购方名称',
  384 + valueType: 'text',
  385 + dataIndex: 'partyAName',
  386 + hideInSearch: true,
  387 + ellipsis: true,
  388 + },
  389 + {
  390 + title: '购方税号',
  391 + valueType: 'text',
  392 + dataIndex: 'partyATaxid',
  393 + ellipsis: true,
  394 + },
  395 + {
  396 + title: '收款单位',
  397 + valueType: 'text',
  398 + dataIndex: 'partyBName',
  399 + hideInSearch: true,
  400 + ellipsis: true,
  401 + },
  402 + {
  403 + title: '联系人',
  404 + valueType: 'text',
  405 + dataIndex: 'contacts',
  406 + hideInSearch: true,
  407 + ellipsis: true,
  408 + },
  409 + {
  410 + title: '申请人',
  411 + valueType: 'text',
  412 + dataIndex: 'createByName',
  413 + hideInSearch: true,
  414 + ellipsis: true,
  415 + },
  416 + {
  417 + title: '开票金额(元)',
  418 + valueType: 'money',
  419 + dataIndex: 'price',
  420 + hideInSearch: true,
  421 + ellipsis: true,
  422 + },
  423 + {
  424 + title: '备注',
  425 + valueType: 'text',
  426 + dataIndex: 'contacts',
  427 + hideInSearch: true,
  428 + ellipsis: true,
  429 + },
  430 + {
  431 + title: '失败原因',
  432 + valueType: 'text',
  433 + dataIndex: 'failureReason',
  434 + hideInSearch: true,
  435 + ellipsis: true,
  436 + },
  437 +
  438 + {
  439 + title: '购方名称',
  440 + valueType: 'text',
  441 + dataIndex: 'partyANameLike',
  442 + hideInTable: true,
  443 + },
  444 + {
  445 + title: '发票类型',
  446 + valueType: 'select',
  447 + dataIndex: 'type',
  448 + filters: true,
  449 + onFilter: true,
  450 + hideInTable: true,
  451 + valueEnum: enumToProTableEnumValue(invoiceTypeValueEnum),
  452 + },
  453 +
  454 + {
  455 + title: '开票状态',
  456 + valueType: 'select',
  457 + dataIndex: 'status',
  458 + filters: true,
  459 + onFilter: true,
  460 + hideInTable: true,
  461 + request: async () => {
  462 + const res = await postServiceConstAfterInvoicingInvoiceRecordStatus();
  463 + return enumToSelect(res.data);
  464 + },
  465 + },
  466 + {
  467 + title: '销售代表',
  468 + valueType: 'select',
  469 + dataIndex: 'salesCode',
  470 + filters: true,
  471 + onFilter: true,
  472 + hideInTable: true,
  473 + valueEnum: salesCodeValueEnum,
  474 + },
  475 + {
  476 + title: '联系人',
  477 + valueType: 'text',
  478 + dataIndex: 'contactsLike',
  479 + hideInTable: true,
  480 + },
  481 + {
  482 + title: '开票日期',
  483 + dataIndex: 'invoicingTime',
  484 + valueType: 'dateRange',
  485 + hideInTable: true,
  486 + search: {
  487 + transform: (value) => {
  488 + if (value) {
  489 + return {
  490 + invoicingTimeGe: value[0],
  491 + invoicingTimeLe: value[1],
  492 + };
  493 + }
  494 + },
  495 + },
  496 + },
  497 + {
  498 + title: '收款单位',
  499 + valueType: 'select',
  500 + dataIndex: 'partyB',
  501 + filters: true,
  502 + onFilter: true,
  503 + hideInTable: true,
  504 + valueEnum: enumToProTableEnumValue(PAYEE_OPTIONS),
  505 + },
  506 + {
  507 + title: '操作',
  508 + valueType: 'option',
  509 + key: 'option',
  510 + render: (text, record) => [
  511 + <a
  512 + key="detail"
  513 + onClick={() => {
  514 + setInvoiceRecordDetailVisible(true);
  515 + setInvoiceRecord(record);
  516 + }}
  517 + >
  518 + 详情
  519 + </a>,
  520 + <>
  521 + {record.status === 'SUCCESS' && (
  522 + <>
  523 + {record.status === 'SUCCESS' && (
  524 + <a href={record.invoiceAddress} download>
  525 + 下载发票
  526 + </a>
  527 + )}
  528 + </>
  529 + )}
  530 + </>,
  531 + <>
  532 + {record.status === 'FAIL' && (
  533 + <ModalForm
  534 + title="提示"
  535 + trigger={
  536 + <Button type="link" danger>
  537 + 重试
  538 + </Button>
  539 + }
  540 + autoFocusFirstInput
  541 + modalProps={{
  542 + destroyOnClose: true,
  543 + }}
  544 + submitTimeout={2000}
  545 + onFinish={async () => {
  546 + const res = await postServiceInvoiceInvoicing({
  547 + data: {
  548 + invoiceRecordIds: [record.id],
  549 + },
  550 + });
  551 + if (res) {
  552 + message.success(res.message);
  553 + processedRecordRef?.current?.reload();
  554 + }
  555 + return true;
  556 + }}
  557 + >
  558 + 确定重试订单信息吗?
  559 + </ModalForm>
  560 + )}
  561 + </>,
  562 + ],
  563 + },
  564 + ];
56 565 /**
57 566 * 加载发票列表表格的各个列格式
58 567 */
... ... @@ -296,6 +805,166 @@ const InvoicePage = () =&gt; {
296 805 const tabsItems = [
297 806 {
298 807 key: 1,
  808 + label: '待处理',
  809 + children: (
  810 + <ProTable
  811 + columns={waitDealRecordColumns}
  812 + actionRef={waitDealrecordActionRef}
  813 + cardBordered
  814 + pagination={{
  815 + pageSize: 10,
  816 + }}
  817 + rowSelection={{
  818 + selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
  819 + alwaysShowAlert: true,
  820 + }}
  821 + tableAlertOptionRender={({ selectedRowKeys, selectedRows }) => {
  822 + console.log(selectedRows);
  823 + console.log(selectedRowKeys);
  824 + return (
  825 + <Space size={16}>
  826 + <InvoicingModal
  827 + reloadRecordTable={reloadRecordTable}
  828 + key="button"
  829 + selectedRowKeys={selectedRowKeys}
  830 + />
  831 + </Space>
  832 + );
  833 + }}
  834 + request={async (params) => {
  835 + let res = await postServiceInvoiceQueryInvoiceRecordList({
  836 + data: {
  837 + ...params,
  838 + statusIn: [
  839 + 'WAITING_FOR_INVOICING',
  840 + 'AUDITING',
  841 + 'AUDITING_NOT_PASSED',
  842 + 'CANCELED',
  843 + ],
  844 + needBuildDetails: false,
  845 + needBuildSubOrders: true,
  846 + },
  847 + });
  848 + return {
  849 + data: res?.data?.data,
  850 + total: res?.data?.total || 0,
  851 + };
  852 + }}
  853 + columnsState={{
  854 + persistenceKey: 'pro-table-singe-demos',
  855 + persistenceType: 'localStorage',
  856 + defaultValue: {
  857 + option: { fixed: 'right', disable: true },
  858 + },
  859 + onChange(value) {
  860 + console.log('value: ', value);
  861 + },
  862 + }}
  863 + rowKey="id"
  864 + search={{
  865 + labelWidth: 'auto',
  866 + }}
  867 + options={{
  868 + setting: {
  869 + listsHeight: 400,
  870 + },
  871 + }}
  872 + form={{}}
  873 + dateFormatter="string"
  874 + headerTitle="待开票列表"
  875 + scroll={{ x: 1400, y: 360 }}
  876 + />
  877 + ),
  878 + },
  879 + {
  880 + key: 2,
  881 + label: '开票记录',
  882 + children: (
  883 + <ProTable
  884 + columns={processedRecordColumns}
  885 + actionRef={processedRecordRef}
  886 + cardBordered
  887 + pagination={{
  888 + pageSize: 10,
  889 + }}
  890 + editable={{
  891 + type: 'multiple',
  892 + onSave: async (rowKey, data) => {
  893 + await postServiceBankStatementEditBankStatement({ data: data });
  894 + },
  895 + actionRender: (row, config, defaultDom) => [
  896 + defaultDom.save,
  897 + defaultDom.cancel,
  898 + ],
  899 + }}
  900 + search={{
  901 + labelWidth: 'auto',
  902 + defaultCollapsed: false,
  903 + optionRender: (searchConfig, formProps, dom) => [
  904 + ...dom,
  905 + <Button
  906 + key="out"
  907 + onClick={() => {
  908 + const values = searchConfig?.form?.getFieldsValue();
  909 + console.log(values);
  910 + messageApi.open({
  911 + type: 'loading',
  912 + content: '正在导出文件...',
  913 + });
  914 + excelExport(
  915 + '/api/service/invoice/exportInvoiceRecords',
  916 + {
  917 + ...values,
  918 + statusIn: ['INVOICING', 'SUCCESS', 'FAIL'],
  919 + },
  920 + () => {
  921 + messageApi.destroy();
  922 + },
  923 + );
  924 + }}
  925 + >
  926 + 导出
  927 + </Button>,
  928 + ],
  929 + }}
  930 + request={async (params) => {
  931 + let res = await postServiceInvoiceQueryInvoiceRecordList({
  932 + data: {
  933 + ...params,
  934 + statusIn: ['INVOICING', 'SUCCESS', 'FAIL'],
  935 + },
  936 + });
  937 + return {
  938 + data: res?.data?.data,
  939 + total: res?.data?.total || 0,
  940 + };
  941 + }}
  942 + columnsState={{
  943 + persistenceKey: 'pro-table-singe-demos',
  944 + persistenceType: 'localStorage',
  945 + defaultValue: {
  946 + option: { fixed: 'right', disable: true },
  947 + },
  948 + onChange(value) {
  949 + console.log('value: ', value);
  950 + },
  951 + }}
  952 + rowKey="id"
  953 + options={{
  954 + setting: {
  955 + listsHeight: 400,
  956 + },
  957 + }}
  958 + form={{}}
  959 + dateFormatter="string"
  960 + headerTitle="待开票列表"
  961 + scroll={{ x: 1400, y: 360 }}
  962 + toolBarRender={() => []}
  963 + />
  964 + ),
  965 + },
  966 + {
  967 + key: 3,
299 968 label: '发票管理',
300 969 children: (
301 970 <ProTable
... ... @@ -352,7 +1021,7 @@ const InvoicePage = () =&gt; {
352 1021 ),
353 1022 },
354 1023 {
355   - key: 2,
  1024 + key: 4,
356 1025 label: '银行流水',
357 1026 children: (
358 1027 <ProTable
... ... @@ -461,6 +1130,16 @@ const InvoicePage = () =&gt; {
461 1130 ) : (
462 1131 ''
463 1132 )}
  1133 + {invoiceRecordDetailVisible ? (
  1134 + <InvoiceRecordDetailModal
  1135 + key="detail"
  1136 + id={invoiceRecord.id}
  1137 + setVisible={setInvoiceRecordDetailVisible}
  1138 + />
  1139 + ) : (
  1140 + ''
  1141 + )}
  1142 + {contextHolder}
464 1143 </div>
465 1144 );
466 1145 };
... ...
src/pages/Order/components/CheckModal.tsx
... ... @@ -8,7 +8,11 @@ import {
8 8 postServiceOrderLeaderAudit,
9 9 postServiceOrderToProcureAudit,
10 10 } from '@/services';
11   -import { ModalForm, ProFormTextArea } from '@ant-design/pro-components';
  11 +import {
  12 + ModalForm,
  13 + ProFormTextArea,
  14 + ProList,
  15 +} from '@ant-design/pro-components';
12 16 import {
13 17 Button,
14 18 Col,
... ... @@ -17,6 +21,8 @@ import {
17 21 Image,
18 22 Modal,
19 23 Row,
  24 + Space,
  25 + Tag,
20 26 UploadFile,
21 27 message,
22 28 } from 'antd';
... ... @@ -28,6 +34,7 @@ import {
28 34 COMFIR_RECEIPT_IMAGES_NUMBER,
29 35 } from '../constant';
30 36 // import { cloneDeep } from 'lodash';
  37 +import InvoiceSubOrderInfoTable from '@/pages/Order/components/InvoiceSubOrderInfoTable';
31 38 import { enumValueToLabel, transImageFile } from '@/utils';
32 39 import { PlusOutlined } from '@ant-design/icons';
33 40 import { cloneDeep } from 'lodash';
... ... @@ -62,7 +69,6 @@ export default ({
62 69  
63 70 const [afterSalesInfo, setAfterSalesInfo] = useState<any>();
64 71 const [prepaidProofImages, setPrepaidProofImages] = useState<any[]>([]);
65   -
66 72 /**
67 73 * 审核类型
68 74 */
... ... @@ -674,6 +680,57 @@ export default ({
674 680 ) : (
675 681 ''
676 682 )}
  683 + {checkType(CHECK_TYPE.CONFIRM_REISSUE) && (
  684 + <>
  685 + <InvoiceSubOrderInfoTable
  686 + subOrderIds={subOrderIds}
  687 + ></InvoiceSubOrderInfoTable>
  688 + </>
  689 + )}
  690 + {checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING) ? (
  691 + <>
  692 + <ProList
  693 + rowKey="id"
  694 + headerTitle="发票信息"
  695 + metas={{
  696 + title: {
  697 + dataIndex: 'name',
  698 + },
  699 + avatar: {
  700 + dataIndex: 'image',
  701 + editable: false,
  702 + },
  703 + description: {
  704 + dataIndex: 'desc',
  705 + },
  706 + subTitle: {
  707 + render: () => {
  708 + return (
  709 + <Space size={0}>
  710 + <Tag color="blue">Ant Design</Tag>
  711 + <Tag color="#5BD8A6">TechUI</Tag>
  712 + </Space>
  713 + );
  714 + },
  715 + },
  716 + actions: {
  717 + render: (text, row, index, action) => [
  718 + <a
  719 + onClick={() => {
  720 + action?.startEditable(row.id);
  721 + }}
  722 + key="link"
  723 + >
  724 + 编辑
  725 + </a>,
  726 + ],
  727 + },
  728 + }}
  729 + ></ProList>
  730 + </>
  731 + ) : (
  732 + ''
  733 + )}
677 734 </ModalForm>
678 735  
679 736 <Modal
... ...
src/pages/Order/components/InvoiceSubOrderInfoTable.tsx 0 → 100644
  1 +import { postServiceOrderGetReissueInfo } from '@/services';
  2 +import type { ProColumns } from '@ant-design/pro-components';
  3 +import { ProTable } from '@ant-design/pro-components';
  4 +import { Button, Divider } from 'antd';
  5 +import { useEffect, useState } from 'react';
  6 +
  7 +const columns: ProColumns[] = [
  8 + {
  9 + title: '发票号码',
  10 + width: 80,
  11 + dataIndex: 'invoiceNumber',
  12 + render: (_) => _,
  13 + },
  14 + {
  15 + title: '关联订单',
  16 + dataIndex: 'subOrderIds',
  17 + render: (_, { subOrderIds }) => {
  18 + console.log(JSON.stringify(_));
  19 + console.log(JSON.stringify(subOrderIds));
  20 + return (
  21 + <>
  22 + {subOrderIds.map((subOrderId, index) => {
  23 + return (
  24 + <>
  25 + <Button
  26 + key={index}
  27 + className="pl-1 pr-0"
  28 + type="link"
  29 + target="_blank"
  30 + href={'/order?id=' + subOrderId}
  31 + >
  32 + {subOrderId}
  33 + </Button>
  34 + <Divider type="vertical" />
  35 + </>
  36 + );
  37 + })}
  38 + </>
  39 + );
  40 + },
  41 + },
  42 +];
  43 +
  44 +export default ({ subOrderIds }) => {
  45 + const [reissueInfos, setReissueInfos] = useState([]);
  46 + useEffect(() => {
  47 + console.log('info');
  48 + const getReissueInfo = async () => {
  49 + let res = await postServiceOrderGetReissueInfo({
  50 + data: subOrderIds,
  51 + });
  52 + setReissueInfos(res.data);
  53 + };
  54 + getReissueInfo();
  55 + }, []);
  56 + return (
  57 + <ProTable
  58 + dataSource={reissueInfos}
  59 + rowKey="key"
  60 + pagination={false}
  61 + size={'small'}
  62 + //设置左右下边距为0
  63 + options={false}
  64 + columns={columns}
  65 + search={false}
  66 + dateFormatter="string"
  67 + headerTitle="发票信息"
  68 + />
  69 + );
  70 +};
... ...
src/pages/Order/components/InvoicingDrawerForm.tsx
  1 +// import { PlusOutlined } from '@ant-design/icons';
  2 +import InvoiceModal from '@/pages/Invoice/components/InvoiceModal';
  3 +import {
  4 + postServiceConstGetPayeeEnum,
  5 + postServiceConstInvoiceType,
  6 + postServiceConstInvoicingType,
  7 + postServiceConstListInvoiceDetailNames,
  8 + postServiceInvoiceApplyInvoice,
  9 +} from '@/services';
  10 +import { enumToSelect } from '@/utils';
1 11 import {
2 12 DrawerForm,
3   - ProForm,
4   - ProFormDateRangePicker,
  13 + ProCard,
  14 + ProFormDigit,
  15 + ProFormGroup,
  16 + ProFormList,
  17 + ProFormMoney,
5 18 ProFormSelect,
6 19 ProFormText,
  20 + ProFormTextArea,
7 21 } from '@ant-design/pro-components';
8   -import { Form, message } from 'antd';
9   -
10   -const waitTime = (time: number = 100) => {
11   - return new Promise((resolve) => {
12   - setTimeout(() => {
13   - resolve(true);
14   - }, time);
15   - });
16   -};
17   -
18   -export default ({ subOrders, totalPayment, onClose }) => {
19   - const [form] = Form.useForm<{ name: string; company: string }>();
  22 +import { Button, Form } from 'antd';
  23 +import { useEffect } from 'react';
20 24  
  25 +export default ({ dataList, mainOrder, setVisible, onClose }) => {
  26 + // let subOrderIds = dataList?.map((item) => {
  27 + // return item.id;
  28 + // });
  29 + const [form] = Form.useForm();
  30 + useEffect(() => {}, []);
21 31 return (
22   - <DrawerForm<{
23   - name: string;
24   - company: string;
25   - }>
26   - title="新建表单"
  32 + <DrawerForm
  33 + open
  34 + title="合并开票"
27 35 resize={{
28 36 onResize() {
29 37 console.log('resize!');
30 38 },
31 39 maxWidth: window.innerWidth * 0.8,
32   - minWidth: 300,
  40 + minWidth: 400,
33 41 }}
34 42 form={form}
35   - /*trigger={
36   - <Button type="primary">
37   - <PlusOutlined />
38   - 新建表单
39   - </Button>
40   - }*/
41   - open={true}
42 43 autoFocusFirstInput
43 44 drawerProps={{
44 45 destroyOnClose: true,
45 46 }}
  47 + submitter={{
  48 + render: (props, defaultDoms) => {
  49 + return [
  50 + <InvoiceModal
  51 + key={'invoicePreview'}
  52 + button={<Button type="primary"> 发票预览 </Button>}
  53 + getRecord={form.getFieldsValue}
  54 + />,
  55 + ...defaultDoms,
  56 + ];
  57 + },
  58 + }}
46 59 submitTimeout={2000}
47 60 onFinish={async (values) => {
48   - await waitTime(2000);
49   - console.log(values);
50   - console.log(subOrders);
51   - console.log(totalPayment);
52   - message.success('提交成功');
  61 + postServiceInvoiceApplyInvoice({
  62 + data: {
  63 + ...values,
  64 + subOrderIds: dataList.map((item) => {
  65 + return item.id;
  66 + }),
  67 + },
  68 + });
53 69 onClose();
54   - // 不返回不会关闭弹框
55   - return true;
  70 + }}
  71 + onOpenChange={(val) => {
  72 + return !val && setVisible();
56 73 }}
57 74 >
58   - <ProForm.Group>
59   - <ProFormText
60   - name="name"
61   - width="md"
62   - label="签约客户名称"
63   - tooltip="最长为 24 位"
64   - placeholder="请输入名称"
65   - />
66   - <ProFormText
67   - rules={[
68   - {
69   - required: true,
70   - },
71   - ]}
72   - width="md"
73   - name="company"
74   - label="我方公司名称"
75   - placeholder="请输入名称"
76   - />
77   - </ProForm.Group>
78   - <ProForm.Group>
79   - <ProFormText
80   - width="md"
81   - name="contract"
82   - label="合同名称"
83   - placeholder="请输入名称"
84   - />
85   - <ProFormDateRangePicker name="contractTime" label="合同生效时间" />
86   - </ProForm.Group>
87   - <ProForm.Group>
88   - <ProFormSelect
89   - options={[
90   - {
91   - value: 'chapter',
92   - label: '盖章后生效',
93   - },
94   - ]}
95   - width="xs"
96   - name="useMode"
97   - label="合同约定生效方式"
98   - />
99   - <ProFormSelect
100   - width="xs"
101   - options={[
102   - {
103   - value: 'time',
104   - label: '履行完终止',
105   - },
106   - ]}
107   - formItemProps={{
108   - style: {
109   - margin: 0,
110   - },
111   - }}
112   - name="unusedMode"
113   - label="合同约定失效效方式"
114   - />
115   - </ProForm.Group>
116   - <ProFormText width="sm" name="id" label="主合同编号" />
  75 + <ProFormList
  76 + name="subOrderIdObjs"
  77 + readonly={true}
  78 + label="开票订单"
  79 + initialValue={dataList.map((item) => {
  80 + return {
  81 + value: item.id,
  82 + };
  83 + })}
  84 + deleteIconProps={false}
  85 + >
  86 + <ProFormGroup key="group">
  87 + <ProFormText readonly={true} name="value" label="" />
  88 + </ProFormGroup>
  89 + </ProFormList>
  90 + <ProFormText
  91 + rules={[
  92 + {
  93 + required: true,
  94 + },
  95 + ]}
  96 + width="md"
  97 + name="partyAName"
  98 + label="购方名称"
  99 + initialValue={mainOrder.institution}
  100 + placeholder="请输入名称"
  101 + />
117 102 <ProFormText
118   - name="project"
119   - disabled
120   - label="项目名称"
121   - initialValue="xxxx项目"
  103 + rules={[
  104 + {
  105 + required: true,
  106 + },
  107 + ]}
  108 + width="md"
  109 + name="partyATaxid"
  110 + label="购方税号"
  111 + placeholder="请输入名称"
122 112 />
123 113 <ProFormText
124   - width="xs"
125   - name="mangerName"
126   - disabled
127   - label="商务经理"
128   - initialValue="启途"
  114 + width="md"
  115 + name="partyAOpenBank"
  116 + label="开户银行"
  117 + placeholder="请输入名称"
  118 + />
  119 + <ProFormText
  120 + width="md"
  121 + name="partyABankAccount"
  122 + label="开户行账号"
  123 + placeholder="请输入名称"
  124 + />
  125 + <ProFormMoney
  126 + label="开票金额"
  127 + name="price"
  128 + locale="zh-CN"
  129 + rules={[{ required: true, message: '请填写开票金额!' }]}
  130 + initialValue={dataList.reduce((accumulator, currentValue) => {
  131 + return accumulator + currentValue.subOrderPayment;
  132 + }, 0)}
  133 + />
  134 + <ProFormSelect
  135 + name="invoicingType"
  136 + label="开具类型"
  137 + request={async () => {
  138 + let invoicingTypeRet = await postServiceConstInvoicingType();
  139 + let options = enumToSelect(invoicingTypeRet.data);
  140 + return options;
  141 + }}
  142 + placeholder="请选择开具类型"
  143 + rules={[{ required: true, message: '请选择开具类型!' }]}
  144 + />
  145 + <ProFormSelect
  146 + name="type"
  147 + label="开票类型"
  148 + placeholder="请选择开票类型"
  149 + rules={[{ required: true, message: '请选择开票类型!' }]}
  150 + request={async () => {
  151 + let invoiceTypeRet = await postServiceConstInvoiceType();
  152 + let options = enumToSelect(invoiceTypeRet.data);
  153 + return options;
  154 + }}
  155 + />
  156 + <ProFormSelect
  157 + name="partyB"
  158 + label="开票收款单位"
  159 + request={async () => {
  160 + const res = await postServiceConstGetPayeeEnum();
  161 + let options = res?.data?.map((payee: any) => {
  162 + return {
  163 + ...payee,
  164 + label: payee.payeeName,
  165 + value: payee.name,
  166 + };
  167 + });
  168 + return options;
  169 + }}
  170 + onChange={(_, option) => {
  171 + if (option) {
  172 + form.setFieldsValue({
  173 + partyBName: option.payeeName,
  174 + partyBTaxid: option.taxId,
  175 + });
  176 + }
  177 + }}
  178 + placeholder="请选择收款单位"
  179 + rules={[{ required: true, message: '请选择收款单位!' }]}
  180 + />
  181 + <ProFormText
  182 + name="partyBName"
  183 + label="开票收款单位名称"
  184 + hidden
  185 + rules={[{ required: true, message: '请选择收款单位!' }]}
  186 + />
  187 + <ProFormText
  188 + name="partyBTaxid"
  189 + label="开票收款单位税号"
  190 + hidden
  191 + rules={[{ required: true, message: '请选择收款单位!' }]}
  192 + />
  193 + <ProFormSelect
  194 + name="isUrgent"
  195 + label="是否加急"
  196 + valueEnum={{
  197 + true: '是',
  198 + false: '否',
  199 + }}
  200 + placeholder="请选择是否加急"
  201 + rules={[{ required: true, message: '请选择是否加急!' }]}
  202 + />
  203 + <ProFormList
  204 + name="invoiceDetails"
  205 + label="开票明细"
  206 + initialValue={dataList.map((item) => {
  207 + return {
  208 + subOrderId: item.id,
  209 + projectName: item.productName,
  210 + specification: item.parameters,
  211 + unit: item.unit,
  212 + quantity: item.quantity,
  213 + price: item.productPrice,
  214 + totalPrice: item.totalPayment,
  215 + };
  216 + })}
  217 + rules={[
  218 + {
  219 + required: true,
  220 + validator: async (_, value) => {
  221 + console.log(value);
  222 + if (value && value.length > 0) {
  223 + return;
  224 + }
  225 + throw new Error('至少要有一项!');
  226 + },
  227 + },
  228 + ]}
  229 + itemRender={(doms, listMeta) => {
  230 + console.log(listMeta);
  231 + return (
  232 + <ProCard
  233 + bordered
  234 + extra={doms.action}
  235 + title={'明细' + (listMeta.index + 1)}
  236 + style={{
  237 + marginBlockEnd: 8,
  238 + }}
  239 + >
  240 + <ProFormText
  241 + key={'subOrderId' + listMeta.index}
  242 + name="subOrderId"
  243 + label="子订单id"
  244 + hidden
  245 + />
  246 + <ProFormSelect
  247 + key={'projectName' + listMeta.index}
  248 + width="md"
  249 + showSearch
  250 + name="projectName"
  251 + request={async (value) => {
  252 + const keywords = value.keyWords;
  253 + const res = await postServiceConstListInvoiceDetailNames({
  254 + data: {
  255 + nameLike: keywords,
  256 + },
  257 + });
  258 + let options = res?.data?.map((c: any) => {
  259 + return {
  260 + ...c,
  261 + label:
  262 + '*' +
  263 + c.productAndServiceCatagoryAbbreviation +
  264 + '*' +
  265 + c.name,
  266 + value:
  267 + '*' +
  268 + c.productAndServiceCatagoryAbbreviation +
  269 + '*' +
  270 + c?.name,
  271 + key: c.id,
  272 + };
  273 + });
  274 + return options;
  275 + }}
  276 + fieldProps={{
  277 + filterOption() {
  278 + return true;
  279 + },
  280 + }}
  281 + onChange={(_, option) => {
  282 + let index = listMeta.index;
  283 + let copyList = form.getFieldValue('invoiceDetails');
  284 + let currentData = copyList[index];
  285 + currentData.projectName =
  286 + '*' +
  287 + option.productAndServiceCatagoryAbbreviation +
  288 + '*' +
  289 + option.name;
  290 + currentData.specification = option.specification;
  291 + currentData.unit = option.unit;
  292 + form.setFieldValue('invoiceDetails', copyList);
  293 + }}
  294 + debounceTime={1000}
  295 + label="项目名称"
  296 + placeholder="请输入名称"
  297 + />
  298 + <ProFormText
  299 + key={'specification' + listMeta.index}
  300 + name="specification"
  301 + label="规格型号"
  302 + placeholder="请输入名称"
  303 + />
  304 + <ProFormText
  305 + key={'unit' + listMeta.index}
  306 + name="unit"
  307 + label="单位"
  308 + placeholder="请输入名称"
  309 + />
  310 + <ProFormDigit
  311 + key={'quantity' + listMeta.index}
  312 + label="数量"
  313 + name="quantity"
  314 + min={0}
  315 + />
  316 + <ProFormDigit
  317 + key={'price' + listMeta.index}
  318 + label="单价"
  319 + name="price"
  320 + min={0}
  321 + />
  322 + <ProFormMoney
  323 + key={'totalPrice' + listMeta.index}
  324 + label="金额"
  325 + name="totalPrice"
  326 + locale="zh-CN"
  327 + />
  328 + </ProCard>
  329 + );
  330 + }}
  331 + ></ProFormList>
  332 + <ProFormTextArea
  333 + name="applyInvoicingNotes"
  334 + label="备注"
  335 + placeholder="请输入名称"
129 336 />
130 337 </DrawerForm>
131 338 );
... ...
src/pages/Order/components/ReissueModal.tsx
... ... @@ -13,7 +13,7 @@ import {
13 13 import { Form } from 'antd';
14 14 import { useEffect, useState } from 'react';
15 15  
16   -export default ({ setVisible, mainOrder, onClose }) => {
  16 +export default ({ setVisible, subOrders, onClose }) => {
17 17 const [invoiceSelectList, setInvoiceSelectList] = useState([]);
18 18 const [mainOrders, setMainOrders] = useState('');
19 19 const [submitting, setSubmitting] = useState(false);
... ... @@ -21,10 +21,9 @@ export default ({ setVisible, mainOrder, onClose }) =&gt; {
21 21 const [form] = Form.useForm<{ invoiceId: string; notes: string }>();
22 22  
23 23 let getInvoiceSelectList = async () => {
24   - console.log(mainOrder);
25 24 const res = await postServiceInvoiceFindInvoice({
26 25 data: {
27   - mainOrderId: mainOrder.id,
  26 + subOrderIdIn: subOrders.map((item) => item.id),
28 27 },
29 28 });
30 29 setInvoiceSelectList([]);
... ...
src/pages/Order/constant.ts
... ... @@ -117,11 +117,10 @@ export const CHECK_TYPE = {
117 117 */
118 118 export const getNeedInvoicing = (subOrder: any) => {
119 119 if (subOrder.invoicingTime !== null && subOrder.invoicingTime !== undefined) {
120   - if (subOrder.afterInvoicingStatus === 'REISSUE') {
121   - return '重新开票';
122   - } else {
123   - return '已开票';
124   - }
  120 + return '已开票';
  121 + }
  122 + if (subOrder.afterInvoicingStatus === 'REISSUE') {
  123 + return '重新开票';
125 124 }
126 125 if (subOrder.invoicingStatus === 'UN_INVOICE') {
127 126 return '不需开票';
... ... @@ -232,6 +231,7 @@ export const AFTER_INVOICING_STATUS = {
232 231 URGENT_INVOICE_AUDIT_NOTPASS: '加急审核失败',
233 232 PARTIAL_INVOICING: '部分开票',
234 233 COMPLETE_INVOICING: '完全开票',
  234 + INVOICING: '开票中',
235 235 REISSUE: '重新开票',
236 236 };
237 237  
... ... @@ -277,6 +277,7 @@ export const TAGS_COLOR = new Map&lt;string, string&gt;([
277 277 ['AUDIT_PASS', 'success'],
278 278 ['AUDIT_NOTPASS', 'error'],
279 279 ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'],
  280 + ['INVOICING', 'processing'],
280 281 ['SALES_CONFIRM', 'warning'],
281 282 ['URGENT_INVOICE_AUDIT_NOTPASS', 'red'],
282 283 ['REISSUE', 'processing'],
... ... @@ -426,6 +427,12 @@ export const MAIN_ORDER_COLUMNS = [
426 427 hideInTable: true,
427 428 },
428 429 {
  430 + title: '子订单编号',
  431 + dataIndex: 'subOrderId',
  432 + valueType: 'text',
  433 + hideInTable: true,
  434 + },
  435 + {
429 436 title: '销售代表',
430 437 dataIndex: 'salesCode',
431 438 valueType: 'text',
... ...
src/pages/Order/index.tsx
... ... @@ -6,6 +6,8 @@ import ReissueModal from &#39;@/pages/Order/components/ReissueModal&#39;;
6 6 import {
7 7 postKingdeeRepSalBillOutbound,
8 8 postKingdeeRepSalOrderSave,
  9 + postServiceConstCanApplyAfterInvoicingStatus,
  10 + postServiceInvoiceCancelApply,
9 11 postServiceOrderCancelSend,
10 12 postServiceOrderGetCurrentOptNode,
11 13 postServiceOrderNoNeedSend,
... ... @@ -127,8 +129,6 @@ const OrderPage = () =&gt; {
127 129 const [allMainChecked, setAllMainChecked] = useState(false);
128 130 const [imagesViewerModalVisible, setImagesViewerModalVisible] =
129 131 useState<boolean>(false);
130   - const [InvoicingDrawerFormVisible, setInvoicingDrawerFormVisible] =
131   - useState<boolean>(false);
132 132 const [data, setData] = useState([]); //列表数据
133 133 const [notesEditVisible, setNotesEditVisible] = useState<boolean>(false);
134 134 const [financialMergeDrawerVisible, setFinancialMergeDrawerVisible] =
... ... @@ -159,6 +159,8 @@ const OrderPage = () =&gt; {
159 159 useState<boolean>(false);
160 160 const [procureConvertModalVisible, setProcureConvertModalVisible] =
161 161 useState<boolean>(false);
  162 + const [invoicingDrawerFormVisible, setInvoicingDrawerFormVisible] =
  163 + useState<boolean>(false);
162 164 const [confirmReceiptVisible, setConfirmReceiptVisible] =
163 165 useState<boolean>(false);
164 166 const [productionTimeModalVisible, setProductionTimeModalVisible] =
... ... @@ -197,6 +199,8 @@ const OrderPage = () =&gt; {
197 199 shippingWarehouseChangeModalVisible,
198 200 setShippingWarehouseChangeModalVisible,
199 201 ] = useState(false);
  202 + const [canApplyAfterInvoicingStatus, setCanApplyAfterInvoicingStatus] =
  203 + useState([]);
200 204 const [ids, setIds] = useState([]);
201 205 const [recordOptNode, setRecordOptNode] = useState(null);
202 206 const roleCode = userInfo?.roleSmallVO?.code;
... ... @@ -223,13 +227,43 @@ const OrderPage = () =&gt; {
223 227 };
224 228  
225 229 const refreshTable = () => {
226   - console.log('刷新表格');
227 230 mainTableRef.current?.reload();
228 231 //刷新表格数据的时候,取消选中行
229 232 setSelectedRows([]);
230 233 setSelectedSubOrderKeys([]);
231 234 };
232 235  
  236 + /*useEffect(() => {
  237 + let initAfterInvoicingStatus = async () => {
  238 + const afteInvoicingStatus = await getAfterInvoicingStatus();
  239 + setAfterInvoicingStatus(afteInvoicingStatus);
  240 + };
  241 + initAfterInvoicingStatus();
  242 + }, []);*/
  243 +
  244 + useEffect(() => {
  245 + // 使用URLSearchParams来解析查询参数
  246 + const params = new URLSearchParams(location.search);
  247 + const id = params.get('id');
  248 + const subOrderId = params.get('subOrderId');
  249 + if (id) {
  250 + mainTableFormRef.current?.setFieldValue('id', id);
  251 + }
  252 + if (subOrderId) {
  253 + mainTableFormRef.current?.setFieldValue('subOrderId', subOrderId);
  254 + }
  255 + }, []);
  256 +
  257 + useEffect(() => {
  258 + const initEnum = async () => {
  259 + let invoiceTypeRet = await postServiceConstCanApplyAfterInvoicingStatus();
  260 + if (invoiceTypeRet.result === RESPONSE_CODE.SUCCESS) {
  261 + setCanApplyAfterInvoicingStatus(invoiceTypeRet.data);
  262 + }
  263 + };
  264 + initEnum();
  265 + }, []);
  266 +
233 267 /**
234 268 * 复制订单到剪贴板
235 269 * @param record
... ... @@ -583,9 +617,6 @@ const OrderPage = () =&gt; {
583 617 mainOrderSelectedMap.clear();
584 618 subOrderSelectedMap.clear();
585 619 }
586   -
587   - console.log(mainOrderSelectedMap);
588   - console.log(subOrderSelectedMap);
589 620 };
590 621  
591 622 //表头渲染
... ... @@ -1324,8 +1355,8 @@ const OrderPage = () =&gt; {
1324 1355 type="link"
1325 1356 onClick={() => {
1326 1357 setCurrentMainId(record.id);
  1358 + setCurretnOptSubId(optRecord.id);
1327 1359 setReissueVisible(true);
1328   - console.log(reissueVisible);
1329 1360 }}
1330 1361 >
1331 1362 重新开票
... ... @@ -1356,7 +1387,6 @@ const OrderPage = () =&gt; {
1356 1387 className="p-0"
1357 1388 type="link"
1358 1389 onClick={() => {
1359   - console.log('here');
1360 1390 setCurrentMainId(record.id);
1361 1391 setCurretnOptSubId(optRecord.id);
1362 1392 setCheckVisible(true);
... ... @@ -1466,7 +1496,7 @@ const OrderPage = () =&gt; {
1466 1496 ''
1467 1497 )}
1468 1498  
1469   - {optRecord.subPath?.includes('saleCancelInvoicing') ? (
  1499 + {/*{optRecord.subPath?.includes('saleCancelInvoicing') ? (
1470 1500 <ButtonConfirm
1471 1501 className="p-0"
1472 1502 title="确认取消申请开票?"
... ... @@ -1486,6 +1516,27 @@ const OrderPage = () =&gt; {
1486 1516 />
1487 1517 ) : (
1488 1518 ''
  1519 + )}*/}
  1520 + {optRecord.subPath?.includes('saleCancelInvoicing') ? (
  1521 + <ButtonConfirm
  1522 + className="p-0"
  1523 + title="确认取消申请开票?"
  1524 + text="取消申请"
  1525 + onConfirm={async () => {
  1526 + let res = await postServiceInvoiceCancelApply({
  1527 + data: {
  1528 + subOrderIds: [optRecord.id],
  1529 + },
  1530 + });
  1531 +
  1532 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  1533 + message.success(res.message);
  1534 + refreshTable();
  1535 + }
  1536 + }}
  1537 + />
  1538 + ) : (
  1539 + ''
1489 1540 )}
1490 1541 {optRecord.subPath?.includes('noNeedInvoicingEdit') ? (
1491 1542 <Button
... ... @@ -1701,7 +1752,7 @@ const OrderPage = () =&gt; {
1701 1752 ''
1702 1753 )}
1703 1754  
1704   - {optRecord.subPath?.includes('applyInvoicing') ? (
  1755 + {/*{optRecord.subPath?.includes('applyInvoicing') ? (
1705 1756 <Button
1706 1757 className="p-0"
1707 1758 type="link"
... ... @@ -1716,6 +1767,23 @@ const OrderPage = () =&gt; {
1716 1767 </Button>
1717 1768 ) : (
1718 1769 ''
  1770 + )}*/}
  1771 +
  1772 + {optRecord.subPath?.includes('applyInvoicing') ? (
  1773 + <Button
  1774 + className="p-0"
  1775 + type="link"
  1776 + onClick={() => {
  1777 + setInvoicingDrawerFormVisible(true);
  1778 + createOptObject(optRecord.id, record.id);
  1779 + setIsEdit(false);
  1780 + setIsMainOrder(false);
  1781 + }}
  1782 + >
  1783 + 申请开票
  1784 + </Button>
  1785 + ) : (
  1786 + ''
1719 1787 )}
1720 1788  
1721 1789 {optRecord.subPath?.includes('checkOrder') ? (
... ... @@ -2231,9 +2299,6 @@ const OrderPage = () =&gt; {
2231 2299  
2232 2300 setSelectedSubOrderKeys(newSelectedSubOrderKeys);
2233 2301 setSelectedRows(currentMainOrderSelectedSubOrderList);
2234   -
2235   - console.log(mainOrderSelectedMap);
2236   - console.log(subOrderSelectedMap);
2237 2302 },
2238 2303 selectedRowKeys: selectedSubOrderKeys,
2239 2304 // 自定义选择项参考: https://ant.design/components/table-cn/#components-table-demo-row-selection-custom
... ... @@ -2711,7 +2776,6 @@ const OrderPage = () =&gt; {
2711 2776 onClick={() => {
2712 2777 setCurrentMainId(record.id);
2713 2778 setReissueVisible(true);
2714   - console.log(reissueVisible);
2715 2779 }}
2716 2780 >
2717 2781 重新开票
... ... @@ -3150,7 +3214,7 @@ const OrderPage = () =&gt; {
3150 3214 ''
3151 3215 )}
3152 3216  
3153   - {record.mainPath?.includes('applyInvoicing') ? (
  3217 + {/*{record.mainPath?.includes('applyInvoicing') ? (
3154 3218 <Button
3155 3219 type="link"
3156 3220 className="p-0"
... ... @@ -3185,6 +3249,43 @@ const OrderPage = () =&gt; {
3185 3249 </Button>
3186 3250 ) : (
3187 3251 ''
  3252 + )}*/}
  3253 +
  3254 + {record.mainPath?.includes('applyInvoicing') ? (
  3255 + <Button
  3256 + type="link"
  3257 + className="p-0"
  3258 + onClick={() => {
  3259 + let selectedSubOrders = subOrderSelectedMap.get(
  3260 + record.id,
  3261 + );
  3262 + if (selectedSubOrders === undefined) {
  3263 + selectedSubOrders = record.subOrderInformationLists;
  3264 + }
  3265 + for (let i = 0; i < selectedSubOrders.length; i++) {
  3266 + if (
  3267 + selectedSubOrders[i].invoicingStatus ===
  3268 + 'UN_INVOICE' ||
  3269 + selectedSubOrders[i].afterInvoicingStatus ===
  3270 + 'APPLY_FOR_INVOICING'
  3271 + ) {
  3272 + message.error(
  3273 + '请选择需要开票且未申请开票的子订单进行申请',
  3274 + );
  3275 + return;
  3276 + }
  3277 + }
  3278 +
  3279 + createOptObject(null, record.id);
  3280 + setInvoicingDrawerFormVisible(true);
  3281 + setIsEdit(false);
  3282 + setIsMainOrder(false);
  3283 + }}
  3284 + >
  3285 + 申请开票
  3286 + </Button>
  3287 + ) : (
  3288 + ''
3188 3289 )}
3189 3290  
3190 3291 {record.mainPath?.includes('updateOrder') ? (
... ... @@ -3402,7 +3503,6 @@ const OrderPage = () =&gt; {
3402 3503 selectedSubOrders = record.subOrderInformationLists;
3403 3504 }
3404 3505  
3405   - console.log(selectedSubOrders);
3406 3506 for (let i = 0; i < selectedSubOrders.length; i++) {
3407 3507 if (
3408 3508 selectedSubOrders[i].afterInvoicingStatus !==
... ... @@ -3990,39 +4090,39 @@ const OrderPage = () =&gt; {
3990 4090 //导出按钮配置
3991 4091 const auditItems: MenuProps['items'] = [
3992 4092 {
3993   - label: '领导审核',
3994   - key: '2',
  4093 + label: '后置审核',
  4094 + key: '1',
3995 4095 onClick: async () => {
3996 4096 setIsMainOrder(true);
3997 4097 setCheckVisible(true);
3998   - setOrderCheckType(CHECK_TYPE.LEADER_AUDIT);
  4098 + setOrderCheckType(CHECK_TYPE.WAITING_FOR_POST_AUDIT);
3999 4099 },
4000 4100 },
4001 4101 {
4002   - label: '后置审核',
4003   - key: '1',
  4102 + label: '加急开票审核',
  4103 + key: '2',
4004 4104 onClick: async () => {
4005 4105 setIsMainOrder(true);
4006 4106 setCheckVisible(true);
4007   - setOrderCheckType(CHECK_TYPE.WAITING_FOR_POST_AUDIT);
  4107 + setOrderCheckType(CHECK_TYPE.URGENT_INVOICE_AUDITING);
4008 4108 },
4009 4109 },
4010 4110 {
4011   - label: '修改申请审核',
  4111 + label: '领导审核',
4012 4112 key: '3',
4013 4113 onClick: async () => {
4014 4114 setIsMainOrder(true);
4015 4115 setCheckVisible(true);
4016   - setOrderCheckType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT);
  4116 + setOrderCheckType(CHECK_TYPE.LEADER_AUDIT);
4017 4117 },
4018 4118 },
4019 4119 {
4020   - label: '加急开票审核',
  4120 + label: '修改申请审核',
4021 4121 key: '4',
4022 4122 onClick: async () => {
4023 4123 setIsMainOrder(true);
4024 4124 setCheckVisible(true);
4025   - setOrderCheckType(CHECK_TYPE.URGENT_INVOICE_AUDITING);
  4125 + setOrderCheckType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT);
4026 4126 },
4027 4127 },
4028 4128 ];
... ... @@ -4116,19 +4216,6 @@ const OrderPage = () =&gt; {
4116 4216 );
4117 4217 }
4118 4218  
4119   - <Button
4120   - type="primary"
4121   - key="out"
4122   - onClick={() => {
4123   - setIsEdit(false);
4124   - setIsMainOrder(true);
4125   - setInvoicingDrawerFormVisible(true);
4126   - }}
4127   - disabled={selectedSubOrderKeys?.length === 0}
4128   - >
4129   - 申请开票
4130   - </Button>;
4131   -
4132 4219 if (rolePath?.includes('mergeInvoicing')) {
4133 4220 toolBtns.push(
4134 4221 <Button
... ... @@ -4165,6 +4252,35 @@ const OrderPage = () =&gt; {
4165 4252 );
4166 4253 }
4167 4254  
  4255 + toolBtns.push(
  4256 + <Button
  4257 + type="primary"
  4258 + key="inv"
  4259 + onClick={() => {
  4260 + setIsMainOrder(true);
  4261 + let flat = [...subOrderSelectedMap.values()].flat();
  4262 + //遍历flat,判断afterInvoicingStatusList存在于canApplyAfterInvoicingStatus
  4263 + flat.forEach((item) => {
  4264 + if (
  4265 + item.invoicingStatus === 'UN_INVOICE' ||
  4266 + (item.afterInvoicingStatus !== null &&
  4267 + !canApplyAfterInvoicingStatus.includes(
  4268 + item.afterInvoicingStatus,
  4269 + ))
  4270 + ) {
  4271 + message.error('存在不能进行开票的订单');
  4272 + return;
  4273 + }
  4274 + });
  4275 + //遍历afterInvoicingStatusList
  4276 + setInvoicingDrawerFormVisible(true);
  4277 + }}
  4278 + disabled={selectedSubOrderKeys?.length === 0}
  4279 + >
  4280 + 申请开票
  4281 + </Button>,
  4282 + );
  4283 +
4168 4284 if (rolePath?.includes('addOrder')) {
4169 4285 toolBtns.push(
4170 4286 <Button
... ... @@ -4210,15 +4326,6 @@ const OrderPage = () =&gt; {
4210 4326 return toolBtns;
4211 4327 }
4212 4328  
4213   - useEffect(() => {
4214   - // 使用URLSearchParams来解析查询参数
4215   - const params = new URLSearchParams(location.search);
4216   - const id = params.get('id');
4217   - if (id) {
4218   - mainTableFormRef.current?.setFieldValue('id', id);
4219   - }
4220   - }, []);
4221   -
4222 4329 return (
4223 4330 <div className="order-page-container">
4224 4331 <div id="resizeDiv"></div>
... ... @@ -4282,7 +4389,10 @@ const OrderPage = () =&gt; {
4282 4389 * 第一次进来这个页面,url带有id的话,会自动填充到查询表单中,但是第一次查询params不会带这个id进来
4283 4390 */
4284 4391 let orderIds = mainTableFormRef.current?.getFieldValue('id');
  4392 + let subOrderId =
  4393 + mainTableFormRef.current?.getFieldValue('subOrderId');
4285 4394 params.id = params.id || orderIds;
  4395 + params.subOrderId = params.subOrderId || subOrderId;
4286 4396 if (params.id !== '') {
4287 4397 params.id = params.id?.replace(/ /g, '');
4288 4398 if (params.id?.indexOf(',')) {
... ... @@ -4715,13 +4825,15 @@ const OrderPage = () =&gt; {
4715 4825 <ReissueModal
4716 4826 setVisible={(val: boolean) => {
4717 4827 setReissueVisible(val);
4718   - console.log(reissueVisible);
4719 4828 if (!val) {
4720 4829 clearOptObject();
4721 4830 }
4722 4831 }}
4723   - mainOrder={buildMainOrder()}
4724   - subOrders={buildSubOrders()}
  4832 + subOrders={
  4833 + isMainOrder
  4834 + ? [...subOrderSelectedMap.values()].flat()
  4835 + : buildSubOrders()
  4836 + }
4725 4837 onClose={() => {
4726 4838 setReissueVisible(false);
4727 4839 clearOptObject();
... ... @@ -4780,24 +4892,28 @@ const OrderPage = () =&gt; {
4780 4892 }}
4781 4893 />
4782 4894 )}
4783   -
4784   - {InvoicingDrawerFormVisible && (
  4895 + {invoicingDrawerFormVisible && (
4785 4896 <InvoicingDrawerForm
4786   - subOrders={
  4897 + dataList={
4787 4898 isMainOrder
4788 4899 ? [...subOrderSelectedMap.values()].flat()
4789 4900 : buildSubOrders()
4790 4901 }
4791   - totalPayment={getApplyInvoicingTotalPayment()}
  4902 + setVisible={(val: boolean) => {
  4903 + setInvoicingDrawerFormVisible(val);
  4904 + if (!val) {
  4905 + clearOptObject();
  4906 + }
  4907 + }}
  4908 + mainOrder={isMainOrder ? getFirstMainOrder() : buildMainOrder()}
4792 4909 onClose={() => {
4793   - setApplyForInvoicingVisible(false);
4794   - setIsMainOrder(false);
  4910 + setInvoicingDrawerFormVisible(false);
  4911 + setIsMainOrder(true);
4795 4912 clearOptObject();
4796 4913 refreshTable();
4797 4914 }}
4798   - ></InvoicingDrawerForm>
  4915 + />
4799 4916 )}
4800   -
4801 4917 {contextHolder}
4802 4918 <FloatButton.BackTop visibilityHeight={0} />
4803 4919 </div>
... ...
src/services/exportRequest.ts 0 → 100644
  1 +import axios from 'axios';
  2 +
  3 +export const excelExport = async (
  4 + url: any = '',
  5 + data: any = {},
  6 + exportLoadingDestory: any,
  7 +) => {
  8 + axios({
  9 + url: url,
  10 + method: 'post',
  11 + responseType: 'blob',
  12 + headers: { Authorization: localStorage.getItem('token') },
  13 + data,
  14 + })
  15 + .then((response) => {
  16 + // 我这里在拦截器里直接返回的response.data
  17 + const body = response.data;
  18 + let fileUrl = window.URL.createObjectURL(
  19 + new Blob([body], {
  20 + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
  21 + }),
  22 + );
  23 + let a = document.createElement('a');
  24 + a.style.display = 'none';
  25 + a.href = fileUrl;
  26 + a.download = '开票记录.xlsx';
  27 + document.body.appendChild(a);
  28 + a.click();
  29 + window.URL.revokeObjectURL(a.href);
  30 + document.body.removeChild(a);
  31 + })
  32 + .catch((error) => {
  33 + // 处理错误
  34 + console.error('导出错误', error);
  35 + })
  36 + .finally(() => {
  37 + exportLoadingDestory();
  38 + });
  39 +};
... ...
src/utils/index.ts
... ... @@ -10,6 +10,7 @@ function enumToSelect(data: any) {
10 10  
11 11 //将枚举的value值转换为label
12 12 function enumValueToLabel(value: any, enumObj: any) {
  13 + console.log(value, enumObj);
13 14 if (enumObj !== undefined) {
14 15 return enumObj[value];
15 16 }
... ...