Commit 795fbf6da1f56cb8701620022d0502be74a7420a

Authored by 曾国涛
2 parents 4a8e9287 7899437a

Merge branch 'master' into invoice

# Conflicts:
#	src/pages/Order/constant.ts
#	src/services/definition.ts
#	src/services/request.ts

Too many changes to show.

To preserve performance only 29 of 41 files are displayed.

.umirc.ts
@@ -66,6 +66,20 @@ export default defineConfig({ @@ -66,6 +66,20 @@ export default defineConfig({
66 access: 'canReadAdminAndFinanceAndSales', 66 access: 'canReadAdminAndFinanceAndSales',
67 }, 67 },
68 { 68 {
  69 + name: '课题组管理',
  70 + path: '/researchGroup',
  71 + component: './ResearchGroup',
  72 + icon: 'AccountBookOutlined',
  73 + access: 'canReadAdminAndSales',
  74 + },
  75 + {
  76 + name: '分期账单',
  77 + path: '/instalment',
  78 + component: './Instalment',
  79 + icon: 'BookOutlined',
  80 + access: 'canReadLinda',
  81 + },
  82 + {
69 name: '打印', 83 name: '打印',
70 path: '/print', 84 path: '/print',
71 component: './OrderPrint', 85 component: './OrderPrint',
src/access.ts
1 export default (initialState: API.UserInfo) => { 1 export default (initialState: API.UserInfo) => {
2 // 在这里按照初始化数据定义项目中的权限,统一管理 2 // 在这里按照初始化数据定义项目中的权限,统一管理
3 // 参考文档 https://umijs.org/docs/max/access 3 // 参考文档 https://umijs.org/docs/max/access
4 - const { roleSmallVO } = initialState; 4 + const { roleSmallVO, username } = initialState;
5 const canReadAdmin = roleSmallVO?.code === 'admin'; 5 const canReadAdmin = roleSmallVO?.code === 'admin';
6 const canReadProcure = roleSmallVO?.code === 'procure'; 6 const canReadProcure = roleSmallVO?.code === 'procure';
7 const canReadFinance = roleSmallVO?.code === 'finance'; 7 const canReadFinance = roleSmallVO?.code === 'finance';
@@ -11,9 +11,11 @@ export default (initialState: API.UserInfo) => { @@ -11,9 +11,11 @@ export default (initialState: API.UserInfo) => {
11 return { 11 return {
12 canReadAdmin: canReadAdmin, 12 canReadAdmin: canReadAdmin,
13 canReadProcure: canReadProcure, 13 canReadProcure: canReadProcure,
  14 + canReadLinda: username === 'Linda' || username === '吴量',
14 canReadAdminAndFinance: canReadFinance || canReadAdmin, 15 canReadAdminAndFinance: canReadFinance || canReadAdmin,
15 canReadSales: canReadSales, 16 canReadSales: canReadSales,
16 canReadAdminAndFinanceAndSales: 17 canReadAdminAndFinanceAndSales:
17 canReadFinance || canReadAdmin || canReadSales, 18 canReadFinance || canReadAdmin || canReadSales,
  19 + canReadAdminAndSales: canReadAdmin || canReadSales,
18 }; 20 };
19 }; 21 };
src/pages/Instalment/components/comfire/comfire.tsx 0 → 100644
  1 +import { ModalForm } from '@ant-design/pro-components';
  2 +import { Form, message } from 'antd';
  3 +import { useState } from 'react';
  4 +
  5 +const waitTime = (time: number = 100) => {
  6 + return new Promise((resolve) => {
  7 + setTimeout(() => {
  8 + resolve(true);
  9 + }, time);
  10 + });
  11 +};
  12 +
  13 +export default ({ currtDid, sureDelete }) => {
  14 + const [form] = Form.useForm<{ name: string; company: string }>();
  15 + const [ids, setIds] = useState([]);
  16 +
  17 + function getIds() {
  18 + setIds([]);
  19 + setIds(currtDid);
  20 + }
  21 + return (
  22 + <ModalForm<{
  23 + name: string;
  24 + company: string;
  25 + }>
  26 + trigger={
  27 + <a
  28 + onClick={() => {
  29 + getIds();
  30 + }}
  31 + >
  32 + 删除
  33 + </a>
  34 + }
  35 + form={form}
  36 + autoFocusFirstInput
  37 + width={190}
  38 + modalProps={{
  39 + destroyOnClose: true,
  40 + }}
  41 + onFinish={async () => {
  42 + await waitTime(100);
  43 + sureDelete([ids]);
  44 + message.success('提交成功');
  45 + return true;
  46 + }}
  47 + >
  48 + <br />
  49 + <h2>确定删除吗</h2>
  50 + </ModalForm>
  51 + );
  52 +};
src/pages/Instalment/components/detail/detail.tsx 0 → 100644
  1 +import {
  2 + postOrderErpOrderStagesAdd,
  3 + postOrderErpOrderStagesPayWaySaveOrUpdate,
  4 + postOrderErpOrderStagesSearch,
  5 + postOrderErpOrderStagesUpload,
  6 +} from '@/services';
  7 +import { PlusOutlined } from '@ant-design/icons';
  8 +import {
  9 + ModalForm,
  10 + ProCard,
  11 + ProForm,
  12 + ProFormDatePicker,
  13 + ProFormText,
  14 + ProFormTextArea,
  15 + ProFormUploadButton,
  16 +} from '@ant-design/pro-components';
  17 +import { Button, Form, message } from 'antd';
  18 +import { RcFile } from 'antd/es/upload';
  19 +import { useEffect, useState } from 'react';
  20 +import PayWayDetail from '../payWayDetail/payWayDetail';
  21 +import ProductDetail from '../productDetail/productDetail';
  22 +
  23 +const waitTime = (time: number = 100) => {
  24 + return new Promise((resolve) => {
  25 + setTimeout(() => {
  26 + resolve(true);
  27 + }, time);
  28 + });
  29 +};
  30 +
  31 +export default ({ toReload }) => {
  32 + const [form] = Form.useForm<{ name: string; company: string }>();
  33 + const [contextBody, setContextBody] = useState<OrderStagesWithListItem>({
  34 + id: undefined,
  35 + contract: undefined,
  36 + dateRange: undefined,
  37 + terminal: undefined,
  38 + orderStagesDeviceVoList: [],
  39 + totalPrice: undefined,
  40 + payWay: '30/30/30/10',
  41 + annex: undefined,
  42 + remark: undefined,
  43 + });
  44 + const [editProductBody, setEditProductBody] = useState([]);
  45 + const [total, setTotal] = useState(0);
  46 + const [payWayBody, setPayWayBody] = useState([]);
  47 + const [otherBody, setOtherBody] = useState([]);
  48 + const [isDis] = useState(true);
  49 +
  50 + type OrderStagesWithListItem = {
  51 + //文件编号
  52 + id?: number;
  53 + //合同编号
  54 + contract?: string;
  55 + //供应商名称
  56 + vendor?: string;
  57 + //签合同日期
  58 + dateRange?: Date;
  59 + //终端名称
  60 + terminal?: string;
  61 + orderStagesDeviceVoList: orderStagesDevice[];
  62 + //合同总金额
  63 + totalPrice?: number;
  64 + //付款方式
  65 + payWay?: string;
  66 + //附件
  67 + annex?: string;
  68 + //备注
  69 + remark?: string;
  70 + };
  71 +
  72 + type orderStagesDevice = {
  73 + //设备id
  74 + dId: number;
  75 + //设备名称
  76 + deviceName: string;
  77 + //设备型号
  78 + deviceModel: string;
  79 + //数量
  80 + count: number;
  81 + //单价
  82 + unitPrice: number;
  83 + //总价
  84 + price: number;
  85 + };
  86 +
  87 + function setSave(value) {
  88 + setOtherBody(value);
  89 + }
  90 +
  91 + useEffect(() => {
  92 + setContextBody({ ...contextBody, totalPrice: total });
  93 + form.setFieldValue('totalPrice', total);
  94 + }, [total]);
  95 +
  96 + const handleInputChange = (value: string, no: number, priceNow?: number) => {
  97 + if (value === '') {
  98 + message.info('请输入比例!');
  99 + } else {
  100 + let totalPay = 0;
  101 + const payValue: string[] = value.split('/');
  102 + let body:
  103 + | ((prevState: never[]) => never[])
  104 + | { proportion: string; payPrice: number }[] = [];
  105 + if (no === 1) {
  106 + if (payValue.length !== 4) {
  107 + message.warning('比例个数总和不为4个!');
  108 + } else {
  109 + payValue.forEach((item) => {
  110 + totalPay += Number(item);
  111 + });
  112 + }
  113 + if (totalPay !== 100) {
  114 + message.warning('比例总和不为100!');
  115 + } else {
  116 + message.success('输入有效!');
  117 + payValue.forEach((item) => {
  118 + body.push({
  119 + proportion: item + '%',
  120 + payPrice: (Number(item) * total) / 100,
  121 + });
  122 + });
  123 + setPayWayBody(body);
  124 + }
  125 + } else {
  126 + payValue.forEach((item) => {
  127 + totalPay += Number(item);
  128 + });
  129 + payValue.forEach((item) => {
  130 + body.push({
  131 + proportion: item + '%',
  132 + payPrice: (Number(item) * priceNow) / 100,
  133 + });
  134 + });
  135 + setPayWayBody(body);
  136 + }
  137 + }
  138 + };
  139 +
  140 + function getEditProductBody(value) {
  141 + setEditProductBody(value);
  142 + let price = 0;
  143 + value.map((obj) => (price += obj.count * obj.unitPrice));
  144 + setTotal(price);
  145 + setContextBody({ ...contextBody, orderStagesDeviceVoList: value });
  146 + if (contextBody.payWay === '') {
  147 + handleInputChange('30/30/30/10', 0, price);
  148 + } else {
  149 + handleInputChange(contextBody.payWay, 0, price);
  150 + }
  151 + }
  152 +
  153 + function refresh() {
  154 + setEditProductBody([]);
  155 + setContextBody({
  156 + id: undefined,
  157 + contract: undefined,
  158 + dateRange: undefined,
  159 + terminal: undefined,
  160 + orderStagesDeviceVoList: [],
  161 + totalPrice: undefined,
  162 + payWay: '30/30/30/10',
  163 + annex: undefined,
  164 + remark: undefined,
  165 + });
  166 + handleInputChange('30/30/30/10', 0, 0);
  167 + }
  168 +
  169 + return (
  170 + <ModalForm<OrderStagesWithListItem>
  171 + title="新建"
  172 + trigger={
  173 + <Button
  174 + key="button"
  175 + icon={<PlusOutlined />}
  176 + type="primary"
  177 + onClick={() => refresh()}
  178 + >
  179 + 新增
  180 + </Button>
  181 + }
  182 + form={form}
  183 + autoFocusFirstInput
  184 + modalProps={{
  185 + destroyOnClose: true,
  186 + }}
  187 + submitTimeout={2000}
  188 + onFinish={async (values) => {
  189 + console.log(values);
  190 + if (editProductBody.length === 0) {
  191 + message.error('请填写产品数据');
  192 + return false;
  193 + }
  194 + let remakeValue = [];
  195 +
  196 + const formData = new FormData();
  197 + let toSendEdit = {
  198 + id: values.id || contextBody.id,
  199 + contract: values.contract || contextBody.contract,
  200 + vendor: values.vendor || contextBody.vendor,
  201 + dateRange: values.dateRange || contextBody.dateRange,
  202 + terminal: values.terminal || contextBody.terminal,
  203 + orderStagesDeviceDoList:
  204 + values.orderStagesDeviceVoList ||
  205 + contextBody.orderStagesDeviceVoList,
  206 + totalPrice: values.totalPrice || contextBody.totalPrice,
  207 + payWay: values.payWay || contextBody.payWay,
  208 + annex: contextBody.annex,
  209 + remark: values.remark || contextBody.remark,
  210 + };
  211 + if (values.annex) {
  212 + formData.append('file', values.annex[0].originFileObj as RcFile);
  213 + const res = await postOrderErpOrderStagesUpload({
  214 + data: formData,
  215 + headers: {
  216 + 'Content-Type':
  217 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  218 + },
  219 + });
  220 + if (res.data) {
  221 + toSendEdit.annex = res.data;
  222 + }
  223 + }
  224 + const isSaveOrUpdate = await postOrderErpOrderStagesAdd({
  225 + data: { ...toSendEdit },
  226 + });
  227 +
  228 + if (isSaveOrUpdate) {
  229 + const promises = [];
  230 +
  231 + otherBody.forEach((item) => {
  232 + let remakeItem = {
  233 + ossId: item.ossId,
  234 + number: item.id,
  235 + dateRange: item.payDate,
  236 + fileName: item.fileName,
  237 + };
  238 + if (
  239 + typeof item.fileUrl === 'object' &&
  240 + item.fileUrl instanceof File
  241 + ) {
  242 + const formData = new FormData();
  243 + formData.append('file', item.fileUrl as RcFile);
  244 + const uploadPromise = async () => {
  245 + const res = await postOrderErpOrderStagesUpload({
  246 + data: formData,
  247 + headers: {
  248 + 'Content-Type':
  249 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  250 + },
  251 + });
  252 + if (res.data) {
  253 + remakeItem.fileUrl = res.data;
  254 + }
  255 + };
  256 + promises.push(uploadPromise());
  257 + }
  258 + remakeValue.push(remakeItem);
  259 + });
  260 +
  261 + let makeEnd = [];
  262 + const getRetrunIDPromise = async () => {
  263 + let returnOssID = await postOrderErpOrderStagesSearch({
  264 + data: { contract: values.contract || contextBody.contract },
  265 + });
  266 + console.log(returnOssID.data);
  267 +
  268 + if (returnOssID) {
  269 + makeEnd = remakeValue.map((item) => {
  270 + return { ...item, ossId: returnOssID.data[0].id };
  271 + });
  272 + }
  273 + };
  274 +
  275 + promises.push(getRetrunIDPromise());
  276 + Promise.all(promises).then(async () => {
  277 + await postOrderErpOrderStagesPayWaySaveOrUpdate({
  278 + data: makeEnd,
  279 + });
  280 + });
  281 + toReload();
  282 + }
  283 + await waitTime(2000);
  284 + message.success('提交成功');
  285 + return true;
  286 + }}
  287 + >
  288 + <ProCard title="基本信息" headerBordered bordered>
  289 + <ProForm.Group>
  290 + <ProFormText
  291 + width="md"
  292 + name="vendor"
  293 + rules={[{ required: true, message: '此项为必填项' }]}
  294 + label="供应商名称"
  295 + placeholder="请输入"
  296 + initialValue={contextBody.vendor}
  297 + />
  298 +
  299 + <ProFormText
  300 + width="md"
  301 + name="terminal"
  302 + rules={[{ required: true, message: '此项为必填项' }]}
  303 + label="终端名称"
  304 + placeholder="请输入"
  305 + initialValue={contextBody.terminal}
  306 + />
  307 +
  308 + <ProFormDatePicker
  309 + name="dateRange"
  310 + width="md"
  311 + label="签合同日期"
  312 + placeholder="请选择日期"
  313 + fieldProps={{
  314 + format: (value) => value.format('YYYY-MM-DD'),
  315 + }}
  316 + initialValue={contextBody.dateRange}
  317 + />
  318 +
  319 + <ProFormText
  320 + width="md"
  321 + name="payWay"
  322 + rules={[{ required: true, message: '此项为必填项' }]}
  323 + label="付款比例"
  324 + placeholder="请输入"
  325 + initialValue={contextBody.payWay}
  326 + disabled={!isDis}
  327 + onBlur={(e) => {
  328 + setContextBody({ ...contextBody, payWay: e.target.value });
  329 + handleInputChange(e.target.value, 1);
  330 + }}
  331 + />
  332 +
  333 + <ProFormText
  334 + width="md"
  335 + name="contract"
  336 + rules={[{ required: true, message: '此项为必填项' }]}
  337 + label="合同编号"
  338 + placeholder="请输入"
  339 + initialValue={contextBody.contract}
  340 + />
  341 +
  342 + <ProFormUploadButton
  343 + width="md"
  344 + name="annex"
  345 + max={1}
  346 + label="合同附件"
  347 + />
  348 +
  349 + <ProFormText
  350 + width="md"
  351 + name="totalPrice"
  352 + label="合同金额"
  353 + placeholder="请输入"
  354 + disabled={isDis}
  355 + initialValue={'0'}
  356 + />
  357 + </ProForm.Group>
  358 + </ProCard>
  359 + <ProCard
  360 + title={
  361 + <>
  362 + <span style={{ color: 'red' }}>*</span>产品明细
  363 + </>
  364 + }
  365 + style={{ marginTop: 10 }}
  366 + headerBordered
  367 + bordered
  368 + >
  369 + <ProductDetail
  370 + productBody={[]}
  371 + EditProductBody={getEditProductBody}
  372 + ></ProductDetail>
  373 + </ProCard>
  374 +
  375 + <ProCard
  376 + title="付款信息"
  377 + style={{ marginTop: 10 }}
  378 + headerBordered
  379 + bordered
  380 + >
  381 + <PayWayDetail
  382 + payBody={payWayBody}
  383 + thisId={null}
  384 + currtSave={setSave}
  385 + ></PayWayDetail>
  386 + </ProCard>
  387 +
  388 + <ProCard style={{ marginTop: 10 }} headerBordered bordered>
  389 + <ProFormTextArea
  390 + label="备注"
  391 + name="remark"
  392 + initialValue={contextBody.remark}
  393 + />
  394 + </ProCard>
  395 + </ModalForm>
  396 + );
  397 +};
src/pages/Instalment/components/edit/edit.tsx 0 → 100644
  1 +import {
  2 + postOrderErpOrderStagesPayWaySaveOrUpdate,
  3 + postOrderErpOrderStagesSaveOrUpdate,
  4 + postOrderErpOrderStagesSearch,
  5 + postOrderErpOrderStagesUpload,
  6 +} from '@/services';
  7 +import {
  8 + ModalForm,
  9 + ProCard,
  10 + ProForm,
  11 + ProFormDatePicker,
  12 + ProFormText,
  13 + ProFormTextArea,
  14 + ProFormUploadButton,
  15 +} from '@ant-design/pro-components';
  16 +import { Form, message } from 'antd';
  17 +import { RcFile } from 'antd/es/upload';
  18 +import { useEffect, useState } from 'react';
  19 +import PayWayDetail from '../payWayDetail/payWayDetail';
  20 +import ProductDetail from '../productDetail/productDetail';
  21 +
  22 +const waitTime = (time: number = 100) => {
  23 + return new Promise((resolve) => {
  24 + setTimeout(() => {
  25 + resolve(true);
  26 + }, time);
  27 + });
  28 +};
  29 +
  30 +export default ({ currentContract, toReload }) => {
  31 + const [form] = Form.useForm<{ name: string; company: string }>();
  32 + const [contextBody, setContextBody] = useState({});
  33 + const [total, setTotal] = useState(0);
  34 + const [payWayBody, setPayWayBody] = useState([]);
  35 + const [otherBody, setOtherBody] = useState([]);
  36 +
  37 + type OrderStagesWithListItem = {
  38 + //文件编号
  39 + id: number;
  40 + //合同编号
  41 + contract: string;
  42 + //供应商名称
  43 + vendor: string;
  44 + //签合同日期
  45 + dateRange: Date;
  46 + //终端名称
  47 + terminal: string;
  48 + orderStagesDeviceVoList: orderStagesDevice[];
  49 + //合同总金额
  50 + totalPrice: number;
  51 + //付款方式
  52 + payWay: string;
  53 + //附件
  54 + annex: string;
  55 + //备注
  56 + remark: string;
  57 + };
  58 +
  59 + type orderStagesDevice = {
  60 + //设备id
  61 + dId: number;
  62 + //设备名称
  63 + deviceName: string;
  64 + //设备型号
  65 + deviceModel: string;
  66 + //数量
  67 + count: number;
  68 + //单价
  69 + unitPrice: number;
  70 + //总价
  71 + price: number;
  72 + };
  73 +
  74 + async function refresh() {
  75 + const res = await postOrderErpOrderStagesSearch({
  76 + data: { contract: currentContract },
  77 + });
  78 + const context = res.data[0];
  79 +
  80 + if (context.contract !== null) {
  81 + setContextBody(context);
  82 + setTotal(context.totalPrice);
  83 + form.setFieldValue('totalPrice', context.totalPrice);
  84 + }
  85 + }
  86 +
  87 + function setSave(value) {
  88 + setOtherBody(value);
  89 + }
  90 +
  91 + useEffect(() => {
  92 + setContextBody({ ...contextBody, totalPrice: total });
  93 + form.setFieldValue('totalPrice', total);
  94 + }, [total]);
  95 +
  96 + const handleInputChange = (value: string, no: number, priceNow?: number) => {
  97 + let totalPay = 0;
  98 + const payValue: string[] = value.split('/');
  99 + let body:
  100 + | ((prevState: never[]) => never[])
  101 + | { proportion: string; payPrice: number }[] = [];
  102 + if (no === 1) {
  103 + if (payValue.length !== 4) {
  104 + message.warning('比例个数总和不为4个!');
  105 + } else {
  106 + payValue.forEach((item) => {
  107 + totalPay += Number(item);
  108 + });
  109 + }
  110 + if (totalPay !== 100) {
  111 + message.warning('比例总和不为100!');
  112 + } else {
  113 + message.success('输入有效!');
  114 + const price = total;
  115 + payValue.forEach((item) => {
  116 + body.push({
  117 + proportion: item + '%',
  118 + payPrice: (Number(item) * price) / 100,
  119 + });
  120 + });
  121 + setPayWayBody(body);
  122 + }
  123 + } else {
  124 + payValue.forEach((item) => {
  125 + totalPay += Number(item);
  126 + });
  127 + payValue.forEach((item) => {
  128 + body.push({
  129 + proportion: item + '%',
  130 + payPrice: (Number(item) * priceNow) / 100,
  131 + });
  132 + });
  133 + setPayWayBody(body);
  134 + }
  135 + };
  136 +
  137 + async function getBody() {
  138 + const res = await postOrderErpOrderStagesSearch({
  139 + data: { contract: currentContract },
  140 + });
  141 + const context = res.data[0];
  142 +
  143 + if (context.contract !== null) {
  144 + setContextBody(context);
  145 + setTotal(context.totalPrice);
  146 + form.setFieldValue('totalPrice', context.totalPrice);
  147 + }
  148 + handleInputChange(context.payWay, 0, context.totalPrice);
  149 + }
  150 +
  151 + function getEditProductBody(value) {
  152 + let price = 0;
  153 + value.map((obj) => (price += obj.count * obj.unitPrice));
  154 + setTotal(price);
  155 + setContextBody({ ...contextBody, orderStagesDeviceVoList: value });
  156 + handleInputChange(contextBody.payWay, 0, price);
  157 + }
  158 +
  159 + useEffect(() => {
  160 + getBody();
  161 + }, []);
  162 +
  163 + return (
  164 + <ModalForm<OrderStagesWithListItem>
  165 + title="新建"
  166 + trigger={<a onClick={refresh}>编辑</a>}
  167 + form={form}
  168 + autoFocusFirstInput
  169 + modalProps={{
  170 + destroyOnClose: true,
  171 + }}
  172 + submitTimeout={2000}
  173 + onFinish={async (values) => {
  174 + if (contextBody.orderStagesDeviceVoList.length === 0) {
  175 + message.error('请填写产品数据');
  176 + return false;
  177 + }
  178 + let remakeValue = [];
  179 + const promises = [];
  180 +
  181 + otherBody.forEach((item) => {
  182 + let remakeItem = {
  183 + ossId: contextBody.id,
  184 + number: item.id,
  185 + dateRange: item.payDate,
  186 + fileName: item.fileName,
  187 + };
  188 + if (
  189 + typeof item.fileUrl === 'object' &&
  190 + item.fileUrl instanceof File
  191 + ) {
  192 + const formData = new FormData();
  193 + formData.append('file', item.fileUrl as RcFile);
  194 + const uploadPromise = async () => {
  195 + const res = await postOrderErpOrderStagesUpload({
  196 + data: formData,
  197 + headers: {
  198 + 'Content-Type':
  199 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  200 + },
  201 + });
  202 + if (res.data) {
  203 + remakeItem.fileUrl = res.data;
  204 + }
  205 + };
  206 + promises.push(uploadPromise());
  207 + }
  208 + remakeValue.push(remakeItem);
  209 + });
  210 + Promise.all(promises).then(async () => {
  211 + await postOrderErpOrderStagesPayWaySaveOrUpdate({
  212 + data: remakeValue,
  213 + });
  214 + });
  215 + const formData = new FormData();
  216 + let toSendEdit = {
  217 + id: values.id || contextBody.id,
  218 + contract: values.contract || contextBody.contract,
  219 + vendor: values.vendor || contextBody.vendor,
  220 + dateRange: values.dateRange || contextBody.dateRange,
  221 + terminal: values.terminal || contextBody.terminal,
  222 + orderStagesDeviceDoList:
  223 + values.orderStagesDeviceVoList ||
  224 + contextBody.orderStagesDeviceVoList,
  225 + totalPrice: values.totalPrice || contextBody.totalPrice,
  226 + payWay: values.payWay || contextBody.payWay,
  227 + annex: contextBody.annex,
  228 + remark: values.remark || contextBody.remark,
  229 + };
  230 + if (values.annex) {
  231 + formData.append('file', values.annex[0].originFileObj as RcFile);
  232 + const res = await postOrderErpOrderStagesUpload({
  233 + data: formData,
  234 + headers: {
  235 + 'Content-Type':
  236 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  237 + },
  238 + });
  239 + if (res.data) {
  240 + toSendEdit.annex = res.data;
  241 + }
  242 + }
  243 + const isSaveOrUpdate = await postOrderErpOrderStagesSaveOrUpdate({
  244 + data: { ...toSendEdit },
  245 + });
  246 + if (isSaveOrUpdate) {
  247 + getBody();
  248 + toReload();
  249 + }
  250 + await waitTime(2000);
  251 + message.success('提交成功');
  252 + return true;
  253 + }}
  254 + >
  255 + <ProCard title="基本信息" headerBordered bordered>
  256 + <ProForm.Group>
  257 + <ProFormText
  258 + width="md"
  259 + name="vendor"
  260 + rules={[{ required: true, message: '此项为必填项' }]}
  261 + label="供应商名称"
  262 + placeholder="请输入"
  263 + initialValue={contextBody.vendor}
  264 + />
  265 +
  266 + <ProFormText
  267 + width="md"
  268 + name="terminal"
  269 + rules={[{ required: true, message: '此项为必填项' }]}
  270 + label="终端名称"
  271 + placeholder="请输入"
  272 + initialValue={contextBody.terminal}
  273 + />
  274 +
  275 + <ProFormDatePicker
  276 + name="dateRange"
  277 + width="md"
  278 + label="签合同日期"
  279 + placeholder="请选择日期"
  280 + fieldProps={{
  281 + format: (value) => value.format('YYYY-MM-DD'),
  282 + }}
  283 + initialValue={contextBody.dateRange}
  284 + />
  285 +
  286 + <ProFormText
  287 + width="md"
  288 + name="payWay"
  289 + rules={[{ required: true, message: '此项为必填项' }]}
  290 + label="付款比例"
  291 + placeholder="请输入"
  292 + initialValue={contextBody.payWay}
  293 + onBlur={(e) => {
  294 + handleInputChange(e.target.value, 1);
  295 + }}
  296 + />
  297 +
  298 + <ProFormText
  299 + width="md"
  300 + name="contract"
  301 + rules={[{ required: true, message: '此项为必填项' }]}
  302 + label="合同编号"
  303 + placeholder="请输入"
  304 + initialValue={contextBody.contract}
  305 + />
  306 +
  307 + <ProFormUploadButton
  308 + width="md"
  309 + name="annex"
  310 + max={1}
  311 + label="合同附件"
  312 + />
  313 +
  314 + <ProFormText
  315 + width="md"
  316 + name="totalPrice"
  317 + label="合同金额"
  318 + placeholder="请输入"
  319 + disabled
  320 + initialValue={contextBody.totalPrice}
  321 + />
  322 + </ProForm.Group>
  323 + </ProCard>
  324 +
  325 + <ProCard
  326 + title={
  327 + <>
  328 + <span style={{ color: 'red' }}>*</span>产品明细
  329 + </>
  330 + }
  331 + style={{ marginTop: 10 }}
  332 + headerBordered
  333 + bordered
  334 + >
  335 + <ProductDetail
  336 + productBody={contextBody.orderStagesDeviceVoList}
  337 + EditProductBody={getEditProductBody}
  338 + ></ProductDetail>
  339 + </ProCard>
  340 +
  341 + <ProCard
  342 + title="付款信息"
  343 + style={{ marginTop: 10 }}
  344 + headerBordered
  345 + bordered
  346 + >
  347 + <PayWayDetail
  348 + payBody={payWayBody}
  349 + thisId={contextBody.id}
  350 + currtSave={setSave}
  351 + ></PayWayDetail>
  352 + </ProCard>
  353 +
  354 + <ProCard style={{ marginTop: 10 }} headerBordered bordered>
  355 + <ProFormTextArea
  356 + label="备注"
  357 + name="remark"
  358 + initialValue={contextBody.remark}
  359 + />
  360 + </ProCard>
  361 + </ModalForm>
  362 + );
  363 +};
src/pages/Instalment/components/payWayDetail/payWayDetail.css 0 → 100644
  1 +.payway-detail-index td {
  2 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  3 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  4 + 'WenQuanYi Micro Hei', sans-serif;
  5 + font-size: 14px;
  6 + margin: 0;
  7 +}
  8 +
  9 +.payway-detail-index td .css-dev-only-do-not-override-nllxry {
  10 + margin-bottom: 0 !important;
  11 +}
  12 +
  13 +.dataChoose {
  14 + margin: 0;
  15 +}
src/pages/Instalment/components/payWayDetail/payWayDetail.less 0 → 100644
  1 +.payway-detail-index td {
  2 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  3 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  4 + 'WenQuanYi Micro Hei', sans-serif;
  5 + font-size: 14px;
  6 + margin: 0;
  7 +
  8 + .css-dev-only-do-not-override-nllxry {
  9 + margin-bottom: 0 !important;
  10 + }
  11 +}
  12 +
  13 +.dataChoose {
  14 + margin: 0;
  15 +}
  16 +
  17 +// .pay-way-detail-index td .css-dev-only-do-not-override-nllxry{
  18 +// margin-bottom: 0px !important;
  19 +// }
src/pages/Instalment/components/payWayDetail/payWayDetail.tsx 0 → 100644
  1 +import { postOrderErpOrderStagesPayWaySelect } from '@/services';
  2 +import type { ProColumns } from '@ant-design/pro-components';
  3 +import {
  4 + EditableProTable,
  5 + ProFormDatePicker,
  6 + ProFormRadio,
  7 + ProFormUploadButton,
  8 +} from '@ant-design/pro-components';
  9 +import { message } from 'antd';
  10 +import React, { useEffect, useState } from 'react';
  11 +import './payWayDetail.less';
  12 +
  13 +const waitTime = (time: number = 100) => {
  14 + return new Promise((resolve) => {
  15 + setTimeout(() => {
  16 + resolve(true);
  17 + }, time);
  18 + });
  19 +};
  20 +
  21 +type DataSourceType = {
  22 + id: number;
  23 + payStep?: string;
  24 + proportion?: string;
  25 + ossId?: number;
  26 + payPrice?: number;
  27 + payDate?: Date;
  28 + fileName?: string;
  29 + fileUrl?: string;
  30 +};
  31 +
  32 +export default ({ payBody, thisId, currtSave }) => {
  33 + const defaultData: DataSourceType[] = [
  34 + {
  35 + id: 1,
  36 + payStep: '预付款',
  37 + proportion: undefined,
  38 + payPrice: undefined,
  39 + ossId: undefined,
  40 + payDate: undefined,
  41 + fileName: undefined,
  42 + fileUrl: undefined,
  43 + },
  44 + {
  45 + id: 2,
  46 + payStep: '发贷款',
  47 + proportion: undefined,
  48 + payPrice: undefined,
  49 + ossId: undefined,
  50 + payDate: undefined,
  51 + fileName: undefined,
  52 + fileUrl: undefined,
  53 + },
  54 + {
  55 + id: 3,
  56 + payStep: '验收款',
  57 + proportion: undefined,
  58 + payPrice: undefined,
  59 + ossId: undefined,
  60 + payDate: undefined,
  61 + fileName: undefined,
  62 + fileUrl: undefined,
  63 + },
  64 + {
  65 + id: 4,
  66 + payStep: '质保金',
  67 + proportion: undefined,
  68 + payPrice: undefined,
  69 + ossId: undefined,
  70 + payDate: undefined,
  71 + fileName: undefined,
  72 + fileUrl: undefined,
  73 + },
  74 + ];
  75 +
  76 + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  77 + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>(
  78 + 'hidden',
  79 + );
  80 + const [payWayDetailBody, setPayWayDetailBody] = useState<
  81 + readonly DataSourceType[]
  82 + >([...defaultData]);
  83 + // const [body, setBody] = useState([])
  84 + const [isAccept, setIsAccept] = useState(null);
  85 + // const [isCurrtSave, setIsCurrtSave] = useState(false);
  86 +
  87 + async function getOther(value, arr) {
  88 + const res = await postOrderErpOrderStagesPayWaySelect({
  89 + data: { ossId: value },
  90 + });
  91 + if (res.data) {
  92 + const context = res.data;
  93 + const remake = arr.map((obj) => {
  94 + let currt = obj;
  95 + context.forEach((object) => {
  96 + if (object.number === obj.id) {
  97 + currt = {
  98 + ...obj,
  99 + ossId: value,
  100 + payDate: object.dateRange,
  101 + fileName: object.fileName,
  102 + fileUrl: object.fileUrl,
  103 + };
  104 + return currt;
  105 + }
  106 + });
  107 + return currt;
  108 + });
  109 + setPayWayDetailBody(remake);
  110 + }
  111 + }
  112 +
  113 + function setPayWay(value) {
  114 + const remakeData = payWayDetailBody.map((obj) => {
  115 + return {
  116 + ...obj,
  117 + proportion: value[obj.id - 1]?.proportion,
  118 + payPrice: value[obj.id - 1]?.payPrice,
  119 + };
  120 + });
  121 + // console.log(remakeData);
  122 +
  123 + setPayWayDetailBody(remakeData);
  124 + // console.log(thisId);
  125 +
  126 + if (thisId !== null) {
  127 + getOther(thisId, remakeData);
  128 + }
  129 + }
  130 + // useEffect(() => {
  131 + // getOther(thisId)
  132 + // }, [thisId])
  133 +
  134 + useEffect(() => {
  135 + setPayWay(payBody);
  136 + }, [payBody]);
  137 +
  138 + // function setCurrtSave(value) {
  139 + // // console.log(value);
  140 + // setIsCurrtSave(payWayDetailBody)
  141 + // }
  142 +
  143 + const columns: ProColumns<DataSourceType>[] = [
  144 + {
  145 + title: '编号',
  146 + dataIndex: 'id',
  147 + hideInTable: true,
  148 + editable: false,
  149 + },
  150 + {
  151 + title: '付款信息',
  152 + dataIndex: 'payStep',
  153 + editable: false,
  154 + },
  155 + {
  156 + title: '付款比例',
  157 + dataIndex: 'proportion',
  158 + editable: false,
  159 + },
  160 + {
  161 + title: '付款金额',
  162 + dataIndex: 'payPrice',
  163 + editable: false,
  164 + },
  165 + {
  166 + title: '对应的订单',
  167 + dataIndex: 'ossId',
  168 + editable: false,
  169 + hideInTable: true,
  170 + },
  171 + {
  172 + title: '付款时间',
  173 + dataIndex: 'payDate',
  174 + editable: false,
  175 + render: (text, record) => {
  176 + const handleChange = (value) => {
  177 + const updatedDataSource = payWayDetailBody.map((item) => {
  178 + if (item.id === record.id) {
  179 + return {
  180 + ...item,
  181 + payDate: value,
  182 + };
  183 + }
  184 + return item;
  185 + });
  186 + // console.log(updatedDataSource);
  187 +
  188 + setPayWayDetailBody(updatedDataSource);
  189 + currtSave(updatedDataSource);
  190 + };
  191 +
  192 + return (
  193 + <ProFormDatePicker
  194 + className="dataChoose"
  195 + initialValue={record.payDate}
  196 + value={record.payDate}
  197 + placeholder={'请填写时间'}
  198 + fieldProps={{
  199 + format: (value) => value.format('YYYY-MM-DD'),
  200 + onChange: handleChange,
  201 + }}
  202 + />
  203 + );
  204 + },
  205 + },
  206 + {
  207 + title: '付款单回执',
  208 + dataIndex: 'fileName',
  209 + render: (text, record) => {
  210 + if (isAccept !== record.id) {
  211 + if (
  212 + typeof record.fileUrl === 'object' &&
  213 + record.fileUrl instanceof File
  214 + ) {
  215 + return (
  216 + <a onClick={() => message.error('请先保存')}>{record.fileName}</a>
  217 + );
  218 + } else {
  219 + return <a href={record.fileUrl}>{record.fileName}</a>;
  220 + }
  221 + } else {
  222 + return (
  223 + <ProFormUploadButton
  224 + name={record.id}
  225 + onChange={(value) => {
  226 + // console.log(value);
  227 + // console.log(payWayDetailBody);
  228 + let remakeBody = [];
  229 + let remakeBodyItem = {};
  230 + payWayDetailBody.forEach((item) => {
  231 + if (item.id === record.id) {
  232 + remakeBodyItem = {
  233 + ...item,
  234 + fileUrl: value.file.originFileObj,
  235 + fileName: value.file.name,
  236 + };
  237 + } else {
  238 + remakeBodyItem = { ...item };
  239 + }
  240 + // if (value.fileList.length == 0) {
  241 + // remakeBodyItem = { ...item, fileUrl: undefined, fileName: undefined }
  242 + // }
  243 + remakeBody.push(remakeBodyItem);
  244 + });
  245 + setPayWayDetailBody(remakeBody);
  246 + currtSave(remakeBody);
  247 + }}
  248 + width="md"
  249 + max={1}
  250 + />
  251 + );
  252 + }
  253 + },
  254 + },
  255 + {
  256 + title: '操作',
  257 + valueType: 'option',
  258 + width: 200,
  259 + render: (text, record) => [
  260 + <a
  261 + key="editable"
  262 + onClick={() => {
  263 + if (isAccept !== record.id) {
  264 + setIsAccept(record.id);
  265 + } else {
  266 + setIsAccept(null);
  267 + }
  268 + }}
  269 + >
  270 + {record.fileName !== undefined &&
  271 + record.fileName !== '' &&
  272 + record.fileName !== null
  273 + ? '重新上传'
  274 + : '上传回执'}
  275 + </a>,
  276 + ],
  277 + },
  278 + ];
  279 +
  280 + return (
  281 + <>
  282 + <EditableProTable<DataSourceType>
  283 + rowKey="id"
  284 + className="payway-detail-index"
  285 + toolbar={{ style: { display: 'none' } }}
  286 + ghost={true}
  287 + scroll={{
  288 + x: 960,
  289 + }}
  290 + recordCreatorProps={
  291 + position !== 'hidden'
  292 + ? {
  293 + position: position as 'top',
  294 + record: () => ({ id: (Math.random() * 1000000).toFixed(0) }),
  295 + }
  296 + : false
  297 + }
  298 + loading={false}
  299 + toolBarRender={() => [
  300 + <ProFormRadio.Group
  301 + key="render"
  302 + fieldProps={{
  303 + value: position,
  304 + onChange: (e) => setPosition(e.target.value),
  305 + }}
  306 + />,
  307 + ]}
  308 + columns={columns}
  309 + request={payWayDetailBody}
  310 + value={payWayDetailBody}
  311 + onChange={(value) => {
  312 + setPayWayDetailBody(value);
  313 + // setCurrtSave(payWayDetailBody)
  314 + }}
  315 + editable={{
  316 + type: 'multiple',
  317 + editableKeys,
  318 + onSave: async () => {
  319 + // console.log(rowKey, data, row);
  320 + await waitTime(2000);
  321 + },
  322 + onChange: setEditableRowKeys,
  323 + }}
  324 + />
  325 + </>
  326 + );
  327 +};
src/pages/Instalment/components/productDetail/productDetail.css 0 → 100644
  1 +.product-detail-index td {
  2 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  3 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  4 + 'WenQuanYi Micro Hei', sans-serif;
  5 + font-size: 14px;
  6 +}
src/pages/Instalment/components/productDetail/productDetail.less 0 → 100644
  1 +.product-detail-index td {
  2 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  3 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  4 + 'WenQuanYi Micro Hei', sans-serif;
  5 + font-size: 14px;
  6 +}
src/pages/Instalment/components/productDetail/productDetail.tsx 0 → 100644
  1 +import type { ProColumns } from '@ant-design/pro-components';
  2 +import { EditableProTable, ProFormRadio } from '@ant-design/pro-components';
  3 +import React, { useEffect, useState } from 'react';
  4 +import './productDetail.less';
  5 +
  6 +const waitTime = (time: number = 100) => {
  7 + return new Promise((resolve) => {
  8 + setTimeout(() => {
  9 + resolve(true);
  10 + }, time);
  11 + });
  12 +};
  13 +
  14 +// type DataSourceType = {
  15 +// count?: number;
  16 +// id: React.Key;
  17 +// deviceModel?: string;
  18 +// deviceName?: string;
  19 +// price?: number;
  20 +// unitPrice?: number;
  21 +// };
  22 +
  23 +export default ({ productBody, EditProductBody }) => {
  24 + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  25 + const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]);
  26 + // const [form] = Form.useForm<{ name: string; company: string }>();
  27 + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>(
  28 + 'bottom',
  29 + );
  30 + function getDataSourece() {
  31 + if (productBody.length !== 0) {
  32 + setDataSource(productBody);
  33 + }
  34 + }
  35 + function setEditProductBody(value) {
  36 + // console.log(value);
  37 + // console.log(dataSource);
  38 +
  39 + const modifiedArray = value.map((obj) => {
  40 + if (obj.dId && Number(obj.dId) <= 1000) {
  41 + return {
  42 + ...obj,
  43 + count: obj.count,
  44 + dId: null,
  45 + deviceModel: obj.deviceModel,
  46 + deviceName: obj.deviceName,
  47 + price: Number(obj.unitPrice) * Number(obj.count),
  48 + unitPrice: obj.unitPrice,
  49 + };
  50 + } else {
  51 + return { ...obj, price: Number(obj.unitPrice) * Number(obj.count) };
  52 + }
  53 + });
  54 + // console.log(modifiedArray);
  55 +
  56 + EditProductBody(modifiedArray);
  57 + setDataSource(value);
  58 + }
  59 +
  60 + useEffect(() => {
  61 + getDataSourece();
  62 + }, [productBody]);
  63 +
  64 + type DataSourceType = {
  65 + id: React.Key;
  66 + count: number;
  67 + dId?: number;
  68 + deviceModel: string;
  69 + deviceName: string;
  70 + price: number;
  71 + unitPrice: number;
  72 + };
  73 +
  74 + const columns: ProColumns<DataSourceType>[] = [
  75 + {
  76 + title: '设备编号',
  77 + dataIndex: 'dId',
  78 + hideInTable: true,
  79 + },
  80 + {
  81 + title: '设备名称',
  82 + dataIndex: 'deviceName',
  83 + formItemProps: () => {
  84 + return {
  85 + rules: [{ required: true, message: '此项为必填项' }],
  86 + };
  87 + },
  88 + },
  89 + {
  90 + title: '设备型号',
  91 + dataIndex: 'deviceModel',
  92 + width: '15%',
  93 + formItemProps: () => {
  94 + return {
  95 + rules: [{ required: true, message: '此项为必填项' }],
  96 + };
  97 + },
  98 + },
  99 + {
  100 + title: '数量',
  101 + dataIndex: 'count',
  102 + formItemProps: () => {
  103 + return {
  104 + rules: [{ required: true, message: '此项为必填项' }],
  105 + };
  106 + },
  107 + },
  108 + {
  109 + title: '单价',
  110 + dataIndex: 'unitPrice',
  111 + formItemProps: () => {
  112 + return {
  113 + rules: [{ required: true, message: '此项为必填项' }],
  114 + };
  115 + },
  116 + },
  117 + {
  118 + title: '总价',
  119 + dataIndex: 'price',
  120 + hideInSetting: true,
  121 + disable: true,
  122 + editable: false,
  123 + render: (_text, record) => [
  124 + <span key={record.dId}>{record.count * record.unitPrice}</span>,
  125 + ],
  126 + },
  127 + {
  128 + title: '操作',
  129 + valueType: 'option',
  130 + width: 200,
  131 + render: (_text, record, _, action) => [
  132 + <a
  133 + key="editable"
  134 + onClick={() => {
  135 + if (record.dId) {
  136 + action?.startEditable?.(record.dId);
  137 + }
  138 + }}
  139 + >
  140 + 编辑
  141 + </a>,
  142 + <a
  143 + key="delete"
  144 + onClick={() => {
  145 + EditProductBody(
  146 + dataSource.filter((item) => item.dId !== record.dId),
  147 + );
  148 + setDataSource(dataSource.filter((item) => item.dId !== record.dId));
  149 + }}
  150 + >
  151 + 删除
  152 + </a>,
  153 + ],
  154 + },
  155 + ];
  156 +
  157 + return (
  158 + <>
  159 + <EditableProTable<DataSourceType>
  160 + className="product-detail-index"
  161 + rowKey="dId"
  162 + toolbar={{ style: { display: 'none' } }}
  163 + ghost={true}
  164 + scroll={{
  165 + x: 960,
  166 + }}
  167 + recordCreatorProps={
  168 + position !== 'hidden'
  169 + ? {
  170 + position: position as 'top',
  171 + record: () => ({ dId: (Math.random() * 1000).toFixed(0) }),
  172 + }
  173 + : false
  174 + }
  175 + loading={false}
  176 + toolBarRender={() => [
  177 + <ProFormRadio.Group
  178 + key="render"
  179 + fieldProps={{
  180 + value: position,
  181 + onChange: (e) => setPosition(e.target.value),
  182 + }}
  183 + />,
  184 + ]}
  185 + columns={columns}
  186 + request={dataSource}
  187 + value={dataSource}
  188 + onChange={setEditProductBody}
  189 + editable={{
  190 + type: 'multiple',
  191 + editableKeys,
  192 + onSave: async () => {
  193 + await waitTime(500);
  194 + },
  195 + onChange: setEditableRowKeys,
  196 + }}
  197 + />
  198 + </>
  199 + );
  200 +};
src/pages/Instalment/components/read/read.tsx 0 → 100644
  1 +import {
  2 + postOrderErpOrderStagesPayWaySaveOrUpdate,
  3 + postOrderErpOrderStagesSaveOrUpdate,
  4 + postOrderErpOrderStagesSearch,
  5 + postOrderErpOrderStagesUpload,
  6 +} from '@/services';
  7 +import {
  8 + ModalForm,
  9 + ProCard,
  10 + ProForm,
  11 + ProFormDatePicker,
  12 + ProFormText,
  13 + ProFormTextArea,
  14 +} from '@ant-design/pro-components';
  15 +import { Form, message } from 'antd';
  16 +import { RcFile } from 'antd/es/upload';
  17 +import { useEffect, useState } from 'react';
  18 +import PayWayDetail from './readPayWay';
  19 +import ProductDetail from './readProduct';
  20 +
  21 +const waitTime = (time: number = 100) => {
  22 + return new Promise((resolve) => {
  23 + setTimeout(() => {
  24 + resolve(true);
  25 + }, time);
  26 + });
  27 +};
  28 +
  29 +export default ({ currentContract }) => {
  30 + const [form] = Form.useForm<{ name: string; company: string }>();
  31 + const [contextBody, setContextBody] = useState({});
  32 + const [, setEditProductBody] = useState([]);
  33 + const [total, setTotal] = useState(0);
  34 + const [payWayBody, setPayWayBody] = useState([]);
  35 + const [otherBody, setOtherBody] = useState([]);
  36 +
  37 + type OrderStagesWithListItem = {
  38 + //文件编号
  39 + id: number;
  40 + //合同编号
  41 + contract: string;
  42 + //供应商名称
  43 + vendor: string;
  44 + //签合同日期
  45 + dateRange: Date;
  46 + //终端名称
  47 + terminal: string;
  48 + orderStagesDeviceVoList: orderStagesDevice[];
  49 + //合同总金额
  50 + totalPrice: number;
  51 + //付款方式
  52 + payWay: string;
  53 + //附件
  54 + annex: string;
  55 + //备注
  56 + remark: string;
  57 + };
  58 +
  59 + type orderStagesDevice = {
  60 + //设备id
  61 + dId: number;
  62 + //设备名称
  63 + deviceName: string;
  64 + //设备型号
  65 + deviceModel: string;
  66 + //数量
  67 + count: number;
  68 + //单价
  69 + unitPrice: number;
  70 + //总价
  71 + price: number;
  72 + };
  73 +
  74 + async function refresh() {
  75 + const res = await postOrderErpOrderStagesSearch({
  76 + data: { contract: currentContract },
  77 + });
  78 + const context = res.data[0];
  79 + // console.log(context);
  80 +
  81 + if (context.contract !== null) {
  82 + setContextBody(context);
  83 + setTotal(context.totalPrice);
  84 + form.setFieldValue('totalPrice', context.totalPrice);
  85 + }
  86 + }
  87 +
  88 + function setSave(value) {
  89 + // console.log(value);
  90 + setOtherBody(value);
  91 + }
  92 +
  93 + useEffect(() => {
  94 + setContextBody({ ...contextBody, totalPrice: total });
  95 + form.setFieldValue('totalPrice', total);
  96 + }, [total]);
  97 +
  98 + const handleInputChange = (value: string, no: number, priceNow?: number) => {
  99 + let totalPay = 0;
  100 + const payValue: string[] = value.split('/');
  101 + let body:
  102 + | ((prevState: never[]) => never[])
  103 + | { proportion: string; payPrice: number }[] = [];
  104 + if (no === 1) {
  105 + if (payValue.length !== 4) {
  106 + message.warning('比例个数总和不为4个!');
  107 + } else {
  108 + payValue.forEach((item) => {
  109 + totalPay += Number(item);
  110 + });
  111 + }
  112 + if (totalPay !== 100) {
  113 + message.warning('比例总和不为100!');
  114 + } else {
  115 + message.success('输入有效!');
  116 + const price = total;
  117 + payValue.forEach((item) => {
  118 + body.push({
  119 + proportion: item + '%',
  120 + payPrice: (Number(item) * price) / 100,
  121 + });
  122 + });
  123 + setPayWayBody(body);
  124 + }
  125 + } else {
  126 + payValue.forEach((item) => {
  127 + totalPay += Number(item);
  128 + });
  129 + payValue.forEach((item) => {
  130 + body.push({
  131 + proportion: item + '%',
  132 + payPrice: (Number(item) * priceNow) / 100,
  133 + });
  134 + });
  135 + setPayWayBody(body);
  136 + }
  137 + };
  138 +
  139 + async function getBody() {
  140 + const res = await postOrderErpOrderStagesSearch({
  141 + data: { contract: currentContract },
  142 + });
  143 + const context = res.data[0];
  144 + // console.log(context);
  145 +
  146 + if (context.contract !== null) {
  147 + setContextBody(context);
  148 + setTotal(context.totalPrice);
  149 + form.setFieldValue('totalPrice', context.totalPrice);
  150 + }
  151 + handleInputChange(context.payWay, 0, context.totalPrice);
  152 + }
  153 +
  154 + useEffect(() => {
  155 + getBody();
  156 + }, []);
  157 +
  158 + function getEditProductBody(value) {
  159 + // console.log(value);
  160 +
  161 + setEditProductBody(value);
  162 + let price = 0;
  163 + value.map((obj) => (price += obj.count * obj.unitPrice));
  164 + setTotal(price);
  165 + setContextBody({ ...contextBody, orderStagesDeviceVoList: value });
  166 + handleInputChange(contextBody.payWay, 0, price);
  167 + }
  168 +
  169 + return (
  170 + <ModalForm<OrderStagesWithListItem>
  171 + title="新建"
  172 + trigger={<a onClick={refresh}>查看</a>}
  173 + form={form}
  174 + autoFocusFirstInput
  175 + modalProps={{
  176 + destroyOnClose: true,
  177 + // onCancel: () => console.log('run'),
  178 + }}
  179 + submitTimeout={2000}
  180 + onFinish={async (values) => {
  181 + // console.log(values);
  182 + // console.log(otherBody);
  183 + let remakeValue = [];
  184 + // 创建一个用于存储所有异步操作的Promise数组
  185 + const promises = [];
  186 +
  187 + otherBody.forEach((item) => {
  188 + let remakeItem = {
  189 + ossId: item.ossId,
  190 + number: item.id,
  191 + dataRange: item.payDate,
  192 + fileName: item.fileName,
  193 + };
  194 + if (
  195 + typeof item.fileUrl === 'object' &&
  196 + item.fileUrl instanceof File
  197 + ) {
  198 + const formData = new FormData();
  199 + formData.append('file', item.fileUrl as RcFile);
  200 + const uploadPromise = async () => {
  201 + const res = await postOrderErpOrderStagesUpload({
  202 + data: formData,
  203 + headers: {
  204 + 'Content-Type':
  205 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  206 + },
  207 + });
  208 + if (res.data) {
  209 + remakeItem.fileUrl = res.data;
  210 + }
  211 + };
  212 + promises.push(uploadPromise());
  213 + }
  214 + remakeValue.push(remakeItem);
  215 + });
  216 +
  217 + // 使用Promise.all等待所有异步操作完成后再执行保存操作
  218 + Promise.all(promises).then(async () => {
  219 + await postOrderErpOrderStagesPayWaySaveOrUpdate({
  220 + data: remakeValue,
  221 + });
  222 + });
  223 + const formData = new FormData();
  224 + // let toSendEdit={...values,orderStagesDeviceVoList:contextBody.orderStagesDeviceVoList};
  225 + let toSendEdit = {
  226 + id: values.id || contextBody.id,
  227 + contract: values.contract || contextBody.contract,
  228 + vendor: values.vendor || contextBody.vendor,
  229 + dateRange: values.dateRange || contextBody.dateRange,
  230 + terminal: values.terminal || contextBody.terminal,
  231 + orderStagesDeviceDoList:
  232 + values.orderStagesDeviceVoList ||
  233 + contextBody.orderStagesDeviceVoList,
  234 + totalPrice: values.totalPrice || contextBody.totalPrice,
  235 + payWay: values.payWay || contextBody.payWay,
  236 + annex: contextBody.annex,
  237 + remark: values.remark || contextBody.remark,
  238 + };
  239 + if (values.annex) {
  240 + formData.append('file', values.annex[0].originFileObj as RcFile);
  241 + const res = await postOrderErpOrderStagesUpload({
  242 + data: formData,
  243 + headers: {
  244 + 'Content-Type':
  245 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  246 + },
  247 + });
  248 + if (res.data) {
  249 + // console.log(values)
  250 + // console.log(contextBody);
  251 + toSendEdit.annex = res.data;
  252 + }
  253 + }
  254 + const isSaveOrUpdate = await postOrderErpOrderStagesSaveOrUpdate({
  255 + data: { ...toSendEdit },
  256 + });
  257 + if (isSaveOrUpdate) {
  258 + // console.log(isSaveOrUpdate);
  259 + getBody();
  260 + }
  261 + await waitTime(2000);
  262 + message.success('提交成功');
  263 + return true;
  264 + }}
  265 + >
  266 + <ProCard title="基本信息" headerBordered bordered>
  267 + <ProForm.Group>
  268 + <ProFormText
  269 + width="md"
  270 + name="vendor"
  271 + label="供应商名称"
  272 + placeholder="请输入"
  273 + initialValue={contextBody.vendor}
  274 + readonly
  275 + />
  276 +
  277 + <ProFormText
  278 + width="md"
  279 + name="terminal"
  280 + label="终端名称"
  281 + placeholder="请输入"
  282 + initialValue={contextBody.terminal}
  283 + readonly
  284 + />
  285 +
  286 + <ProFormDatePicker
  287 + name="dateRange"
  288 + width="md"
  289 + label="签合同日期"
  290 + placeholder="请选择日期"
  291 + fieldProps={{
  292 + format: (value) => value.format('YYYY-MM-DD'),
  293 + }}
  294 + initialValue={contextBody.dateRange}
  295 + readonly
  296 + />
  297 +
  298 + <ProFormText
  299 + width="md"
  300 + name="payWay"
  301 + label="付款比例"
  302 + placeholder="请输入"
  303 + initialValue={contextBody.payWay}
  304 + readonly
  305 + onBlur={(e) => {
  306 + handleInputChange(e.target.value, 1);
  307 + }}
  308 + />
  309 +
  310 + <ProFormText
  311 + width="md"
  312 + name="contract"
  313 + label="合同编号"
  314 + placeholder="请输入"
  315 + initialValue={contextBody.contract}
  316 + readonly
  317 + />
  318 +
  319 + {/* <ProFormText
  320 + width="md"
  321 + name="annex"
  322 + label="合同附件"
  323 + placeholder="请输入"
  324 + initialValue={contextBody.fileUrl}
  325 + readonly
  326 + /> */}
  327 +
  328 + <ProFormText
  329 + width="md"
  330 + name="totalPrice"
  331 + label="合同金额"
  332 + placeholder="请输入"
  333 + disabled
  334 + readonly
  335 + // rules={[{ required: true, message: '此项为必填项' }]}
  336 + // value={contextBody.totalPrice}
  337 + initialValue={contextBody.totalPrice}
  338 + />
  339 + </ProForm.Group>
  340 + </ProCard>
  341 + <ProCard
  342 + title="产品明细"
  343 + style={{ marginTop: 10 }}
  344 + headerBordered
  345 + bordered
  346 + >
  347 + <ProductDetail
  348 + productBody={contextBody.orderStagesDeviceVoList}
  349 + EditProductBody={getEditProductBody}
  350 + ></ProductDetail>
  351 + </ProCard>
  352 +
  353 + <ProCard
  354 + title="付款信息"
  355 + style={{ marginTop: 10 }}
  356 + headerBordered
  357 + bordered
  358 + >
  359 + <PayWayDetail
  360 + payBody={payWayBody}
  361 + thisId={contextBody.id}
  362 + currtSave={setSave}
  363 + ></PayWayDetail>
  364 + </ProCard>
  365 +
  366 + <ProCard style={{ marginTop: 10 }} headerBordered bordered>
  367 + <ProFormTextArea
  368 + label="备注"
  369 + name="remark"
  370 + initialValue={contextBody.remark}
  371 + readonly
  372 + />
  373 + </ProCard>
  374 + </ModalForm>
  375 + );
  376 +};
src/pages/Instalment/components/read/readPayWay.tsx 0 → 100644
  1 +import { postOrderErpOrderStagesPayWaySelect } from '@/services';
  2 +import type { ProColumns } from '@ant-design/pro-components';
  3 +import {
  4 + EditableProTable,
  5 + ProFormRadio,
  6 + ProFormUploadButton,
  7 +} from '@ant-design/pro-components';
  8 +import { message } from 'antd';
  9 +import React, { useEffect, useState } from 'react';
  10 +
  11 +const waitTime = (time: number = 100) => {
  12 + return new Promise((resolve) => {
  13 + setTimeout(() => {
  14 + resolve(true);
  15 + }, time);
  16 + });
  17 +};
  18 +
  19 +type DataSourceType = {
  20 + id: number;
  21 + payStep?: string;
  22 + proportion?: string;
  23 + ossId?: number;
  24 + payPrice?: number;
  25 + payDate?: Date;
  26 + fileName?: string;
  27 + fileUrl?: string;
  28 +};
  29 +
  30 +export default ({ payBody, thisId, currtSave }) => {
  31 + const defaultData: DataSourceType[] = [
  32 + {
  33 + id: 1,
  34 + payStep: '预付款',
  35 + proportion: undefined,
  36 + payPrice: undefined,
  37 + ossId: undefined,
  38 + payDate: undefined,
  39 + fileName: undefined,
  40 + fileUrl: undefined,
  41 + },
  42 + {
  43 + id: 2,
  44 + payStep: '发贷款',
  45 + proportion: undefined,
  46 + payPrice: undefined,
  47 + ossId: undefined,
  48 + payDate: undefined,
  49 + fileName: undefined,
  50 + fileUrl: undefined,
  51 + },
  52 + {
  53 + id: 3,
  54 + payStep: '验收款',
  55 + proportion: undefined,
  56 + payPrice: undefined,
  57 + ossId: undefined,
  58 + payDate: undefined,
  59 + fileName: undefined,
  60 + fileUrl: undefined,
  61 + },
  62 + {
  63 + id: 4,
  64 + payStep: '质保金',
  65 + proportion: undefined,
  66 + payPrice: undefined,
  67 + ossId: undefined,
  68 + payDate: undefined,
  69 + fileName: undefined,
  70 + fileUrl: undefined,
  71 + },
  72 + ];
  73 +
  74 + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  75 + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>(
  76 + 'hidden',
  77 + );
  78 + const [payWayDetailBody, setPayWayDetailBody] = useState<
  79 + readonly DataSourceType[]
  80 + >([...defaultData]);
  81 + const [isAccept] = useState(null);
  82 + // const [isCurrtSave, setIsCurrtSave] = useState(false);
  83 +
  84 + async function getOther(value, arr) {
  85 + const res = await postOrderErpOrderStagesPayWaySelect({
  86 + data: { ossId: value },
  87 + });
  88 + if (res.data) {
  89 + const context = res.data;
  90 + const remake = arr.map((obj) => {
  91 + let currt = obj;
  92 + context.forEach((object) => {
  93 + if (object.number === obj.id) {
  94 + currt = {
  95 + ...obj,
  96 + ossId: value,
  97 + payDate: object.dateRange,
  98 + fileName: object.fileName,
  99 + fileUrl: object.fileUrl,
  100 + };
  101 + return currt;
  102 + }
  103 + });
  104 + return currt;
  105 + });
  106 + setPayWayDetailBody(remake);
  107 + }
  108 + }
  109 +
  110 + function setPayWay(value) {
  111 + const remakeData = payWayDetailBody.map((obj) => {
  112 + return {
  113 + ...obj,
  114 + proportion: value[obj.id - 1]?.proportion,
  115 + payPrice: value[obj.id - 1]?.payPrice,
  116 + };
  117 + });
  118 +
  119 + setPayWayDetailBody(remakeData);
  120 +
  121 + if (thisId !== null) {
  122 + getOther(thisId, remakeData);
  123 + }
  124 + }
  125 + // useEffect(() => {
  126 + // getOther(thisId)
  127 + // }, [thisId])
  128 +
  129 + useEffect(() => {
  130 + setPayWay(payBody);
  131 + }, [payBody]);
  132 +
  133 + // function setCurrtSave(_value) {
  134 + // setIsCurrtSave(payWayDetailBody)
  135 + // }
  136 +
  137 + const columns: ProColumns<DataSourceType>[] = [
  138 + {
  139 + title: '编号',
  140 + dataIndex: 'id',
  141 + hideInTable: true,
  142 + editable: false,
  143 + },
  144 + {
  145 + title: '付款信息',
  146 + dataIndex: 'payStep',
  147 + editable: false,
  148 + },
  149 + {
  150 + title: '付款比例',
  151 + dataIndex: 'proportion',
  152 + editable: false,
  153 + },
  154 + {
  155 + title: '付款金额',
  156 + dataIndex: 'payPrice',
  157 + editable: false,
  158 + },
  159 + {
  160 + title: '对应的订单',
  161 + dataIndex: 'ossId',
  162 + editable: false,
  163 + hideInTable: true,
  164 + },
  165 + {
  166 + title: '付款时间',
  167 + dataIndex: 'payDate',
  168 + editable: false,
  169 + render: (_text, record) => {
  170 + return (
  171 + <span>
  172 + {new Intl.DateTimeFormat('zh-CN', {
  173 + year: 'numeric',
  174 + month: 'long',
  175 + day: 'numeric',
  176 + }).format(record.payDate)}
  177 + </span>
  178 + // <ProFormDatePicker
  179 + // className='dataChoose'
  180 + // initialValue={record.payDate}
  181 + // value={record.payDate}
  182 + // placeholder={"请填写时间"}
  183 + // fieldProps={{
  184 + // format: (value) => value.format('YYYY-MM-DD'),
  185 + // onChange: handleChange,
  186 + // }}
  187 + // />
  188 + );
  189 + },
  190 + },
  191 + {
  192 + title: '付款单回执',
  193 + dataIndex: 'fileName',
  194 + render: (_text, record) => {
  195 + if (isAccept !== record.id) {
  196 + if (
  197 + typeof record.fileUrl === 'object' &&
  198 + record.fileUrl instanceof File
  199 + ) {
  200 + return (
  201 + <a onClick={() => message.error('请先保存')}>{record.fileName}</a>
  202 + );
  203 + } else {
  204 + return <a href={record.fileUrl}>{record.fileName}</a>;
  205 + }
  206 + } else {
  207 + return (
  208 + <ProFormUploadButton
  209 + name={record.id}
  210 + onChange={(value) => {
  211 + let remakeBody = [];
  212 + let remakeBodyItem = {};
  213 + payWayDetailBody.forEach((item) => {
  214 + if (item.id === record.id) {
  215 + remakeBodyItem = {
  216 + ...item,
  217 + fileUrl: value.file.originFileObj,
  218 + fileName: value.file.name,
  219 + };
  220 + } else {
  221 + remakeBodyItem = { ...item };
  222 + }
  223 + if (value.fileList.length === 0) {
  224 + remakeBodyItem = {
  225 + ...item,
  226 + fileUrl: undefined,
  227 + fileName: undefined,
  228 + };
  229 + }
  230 + remakeBody.push(remakeBodyItem);
  231 + });
  232 + setPayWayDetailBody(remakeBody);
  233 + currtSave(remakeBody);
  234 + }}
  235 + width="md"
  236 + max={1}
  237 + />
  238 + );
  239 + }
  240 + },
  241 + },
  242 + ];
  243 +
  244 + return (
  245 + <>
  246 + <EditableProTable<DataSourceType>
  247 + rowKey="id"
  248 + className="payway-detail-index"
  249 + toolbar={{ style: { display: 'none' } }}
  250 + ghost={true}
  251 + scroll={{
  252 + x: 960,
  253 + }}
  254 + recordCreatorProps={
  255 + position !== 'hidden'
  256 + ? {
  257 + position: position as 'top',
  258 + record: () => ({ id: (Math.random() * 1000000).toFixed(0) }),
  259 + }
  260 + : false
  261 + }
  262 + loading={false}
  263 + toolBarRender={() => [
  264 + <ProFormRadio.Group
  265 + key="render"
  266 + fieldProps={{
  267 + value: position,
  268 + onChange: (e) => setPosition(e.target.value),
  269 + }}
  270 + />,
  271 + ]}
  272 + columns={columns}
  273 + request={payWayDetailBody}
  274 + value={payWayDetailBody}
  275 + onChange={(value) => {
  276 + setPayWayDetailBody(value);
  277 + // setCurrtSave(payWayDetailBody)
  278 + }}
  279 + editable={{
  280 + type: 'multiple',
  281 + editableKeys,
  282 + onSave: async () => {
  283 + await waitTime(2000);
  284 + },
  285 + onChange: setEditableRowKeys,
  286 + }}
  287 + />
  288 + </>
  289 + );
  290 +};
src/pages/Instalment/components/read/readProduct.tsx 0 → 100644
  1 +import type { ProColumns } from '@ant-design/pro-components';
  2 +import { EditableProTable, ProFormRadio } from '@ant-design/pro-components';
  3 +import { Form } from 'antd';
  4 +import React, { useEffect, useState } from 'react';
  5 +
  6 +const waitTime = (time: number = 100) => {
  7 + return new Promise((resolve) => {
  8 + setTimeout(() => {
  9 + resolve(true);
  10 + }, time);
  11 + });
  12 +};
  13 +
  14 +// type DataSourceType = {
  15 +// count?: number;
  16 +// id: React.Key;
  17 +// deviceModel?: string;
  18 +// deviceName?: string;
  19 +// price?: number;
  20 +// unitPrice?: number;
  21 +// };
  22 +
  23 +export default ({ productBody, EditProductBody }) => {
  24 + const [editableKeys, setEditableRowKeys] = useState<React.Key[]>([]);
  25 + const [dataSource, setDataSource] = useState<readonly DataSourceType[]>([]);
  26 + const [form] = Form.useForm<{ name: string; company: string }>();
  27 + const [position, setPosition] = useState<'top' | 'bottom' | 'hidden'>(
  28 + 'hidden',
  29 + );
  30 + function getDataSourece() {
  31 + if (productBody.length !== 0) {
  32 + setDataSource(productBody);
  33 + }
  34 + }
  35 + function setEditProductBody(value) {
  36 + const modifiedArray = value.map((obj) => {
  37 + if (obj.dId && Number(obj.dId) <= 1000) {
  38 + return {
  39 + ...obj,
  40 + count: obj.count,
  41 + dId: null,
  42 + deviceModel: obj.deviceModel,
  43 + deviceName: obj.deviceName,
  44 + price: obj.price,
  45 + unitPrice: obj.unitPrice,
  46 + };
  47 + } else {
  48 + return obj;
  49 + }
  50 + });
  51 +
  52 + EditProductBody(modifiedArray);
  53 + setDataSource(value);
  54 + }
  55 +
  56 + useEffect(() => {
  57 + getDataSourece();
  58 + }, [productBody]);
  59 +
  60 + type DataSourceType = {
  61 + id: React.Key;
  62 + count: number;
  63 + dId?: number;
  64 + deviceModel: string;
  65 + deviceName: string;
  66 + price: number;
  67 + unitPrice: number;
  68 + };
  69 +
  70 + const columns: ProColumns<DataSourceType>[] = [
  71 + {
  72 + title: '设备编号',
  73 + dataIndex: 'dId',
  74 + hideInTable: true,
  75 + },
  76 + {
  77 + title: '设备名称',
  78 + dataIndex: 'deviceName',
  79 + formItemProps: () => {
  80 + return {
  81 + rules: [{ required: true, message: '此项为必填项' }],
  82 + };
  83 + },
  84 + },
  85 + {
  86 + title: '设备型号',
  87 + dataIndex: 'deviceModel',
  88 + width: '15%',
  89 + formItemProps: () => {
  90 + return {
  91 + rules: [{ required: true, message: '此项为必填项' }],
  92 + };
  93 + },
  94 + },
  95 + {
  96 + title: '数量',
  97 + dataIndex: 'count',
  98 + onChange: (e) => {
  99 + const unitPrice = form.getFieldValue(`data[${rowIndex}].unitPrice`);
  100 + form.setFieldsValue({
  101 + [`data[${rowIndex}].price`]: e * unitPrice,
  102 + });
  103 + },
  104 + formItemProps: () => {
  105 + return {
  106 + rules: [{ required: true, message: '此项为必填项' }],
  107 + };
  108 + },
  109 + },
  110 + {
  111 + title: '单价',
  112 + dataIndex: 'unitPrice',
  113 + formItemProps: () => {
  114 + return {
  115 + rules: [{ required: true, message: '此项为必填项' }],
  116 + };
  117 + },
  118 + },
  119 + {
  120 + title: '总价',
  121 + dataIndex: 'price',
  122 + formItemProps: () => {
  123 + return {
  124 + rules: [{ required: true, message: '此项为必填项' }],
  125 + };
  126 + },
  127 + },
  128 + ];
  129 +
  130 + return (
  131 + <>
  132 + <EditableProTable<DataSourceType>
  133 + className="product-detail-index"
  134 + rowKey="dId"
  135 + toolbar={{ style: { display: 'none' } }}
  136 + ghost={true}
  137 + scroll={{
  138 + x: 960,
  139 + }}
  140 + recordCreatorProps={
  141 + position !== 'hidden'
  142 + ? {
  143 + position: position as 'top',
  144 + record: () => ({ dId: (Math.random() * 1000).toFixed(0) }),
  145 + }
  146 + : false
  147 + }
  148 + loading={false}
  149 + toolBarRender={() => [
  150 + <ProFormRadio.Group
  151 + key="render"
  152 + fieldProps={{
  153 + value: position,
  154 + onChange: (e) => setPosition(e.target.value),
  155 + }}
  156 + />,
  157 + ]}
  158 + columns={columns}
  159 + request={dataSource}
  160 + value={dataSource}
  161 + onChange={setEditProductBody}
  162 + editable={{
  163 + type: 'multiple',
  164 + editableKeys,
  165 + onSave: async () => {
  166 + await waitTime(500);
  167 + },
  168 + onChange: setEditableRowKeys,
  169 + }}
  170 + />
  171 + </>
  172 + );
  173 +};
src/pages/Instalment/components/title/title.less 0 → 100644
  1 +.item {
  2 + background: '#0092ff';
  3 + padding: '8px 0';
  4 + display: flex;
  5 + flex-flow: row nowrap;
  6 + // flex-direction: row;
  7 + // flex-wrap: nowrap;
  8 + align-content: normal;
  9 + align-items: center;
  10 + padding-bottom: 20px;
  11 +}
  12 +
  13 +// .titleSpan{
  14 +// font-weight: bold;
  15 +// width: 100px;
  16 +// }
  17 +
  18 +// .Btn{
  19 +// background: '#0092ff';
  20 +// padding: '8px 0';
  21 +// display: flex;
  22 +// flex-flow: row nowrap;
  23 +// // flex-direction: row;
  24 +// // flex-wrap: nowrap;
  25 +// align-content: normal;
  26 +// align-items: center;
  27 +// padding-bottom: 20px;
  28 +// justify-content: space-between;
  29 +// width: 160px;
  30 +// }
  31 +
  32 +.title-index td {
  33 + font-family: 'San Francisco', 'Helvetica Neue', Helvetica, Arial,
  34 + 'Microsoft YaHei', 'PingFang SC', 'Hiragino Sans GB', 'Heiti SC',
  35 + 'WenQuanYi Micro Hei', sans-serif;
  36 + font-size: 14px;
  37 +}
src/pages/Instalment/components/title/title.tsx 0 → 100644
  1 +import {
  2 + deleteOrderErpOrderStagesDelect,
  3 + getOrderErpOrderStagesListAll,
  4 + postOrderErpOrderStagesSearch,
  5 +} from '@/services';
  6 +import { orderExport } from '@/services/order';
  7 +import { VerticalAlignTopOutlined } from '@ant-design/icons';
  8 +import type { ProColumns } from '@ant-design/pro-components';
  9 +import { ProTable } from '@ant-design/pro-components';
  10 +import { Button, message } from 'antd';
  11 +import { useRef } from 'react';
  12 +import Comfire from '../comfire/comfire';
  13 +import AddModel from '../detail/detail';
  14 +import EditorModel from '../edit/edit';
  15 +import ReadModel from '../read/read';
  16 +import UploadModel from '../upload/uploadModel';
  17 +import './title.less';
  18 +export const waitTimePromise = async (time: number = 100) => {
  19 + return new Promise((resolve) => {
  20 + setTimeout(() => {
  21 + resolve(true);
  22 + }, time);
  23 + });
  24 +};
  25 +
  26 +export const waitTime = async (time: number = 100) => {
  27 + await waitTimePromise(time);
  28 +};
  29 +
  30 +type OrderStagesItem = {
  31 + //文件编号
  32 + id?: number;
  33 + //合同编号
  34 + contract?: string;
  35 + //供应商名称
  36 + vendor?: string;
  37 + //签合同日期
  38 + dateRange?: Date;
  39 + //终端名称
  40 + terminal?: string;
  41 + //设备编号
  42 + dId?: number;
  43 + //设备名称
  44 + deviceName?: string;
  45 + //设备型号
  46 + deviceModel?: string;
  47 + //数量
  48 + count?: number;
  49 + //单价
  50 + unitPrice?: number;
  51 + //总价
  52 + price?: number;
  53 + //合同总金额
  54 + totalPrice?: number;
  55 + //付款方式
  56 + payWay?: string;
  57 + //附件
  58 + annex?: string;
  59 + //备注
  60 + remark?: string;
  61 +};
  62 +
  63 +type OrderStagesWithListItem = {
  64 + //文件编号
  65 + id: number;
  66 + //合同编号
  67 + contract: string;
  68 + //供应商名称
  69 + vendor: string;
  70 + //签合同日期
  71 + dateRange: Date;
  72 + //终端名称
  73 + terminal: string;
  74 + orderStagesDeviceVoList: orderStagesDevice[];
  75 + //合同总金额
  76 + totalPrice: number;
  77 + //付款方式
  78 + payWay: string;
  79 + //附件
  80 + annex: string;
  81 + //备注
  82 + remark: string;
  83 +};
  84 +
  85 +type orderStagesDevice = {
  86 + //设备id
  87 + dId: number;
  88 + //设备名称
  89 + deviceName: string;
  90 + //设备型号
  91 + deviceModel: string;
  92 + //数量
  93 + count: number;
  94 + //单价
  95 + unitPrice: number;
  96 + //总价
  97 + price: number;
  98 +};
  99 +
  100 +export default () => {
  101 + // const actionRef = useRef<ActionType>();
  102 + // const [TableItem, setTableItem] = useState([]);
  103 +
  104 + interface ActionType {
  105 + reload: (resetPageIndex?: boolean) => void;
  106 + reloadAndRest: () => void;
  107 + reset: () => void;
  108 + clearSelected?: () => void;
  109 + startEditable: (rowKey: Key) => boolean;
  110 + cancelEditable: (rowKey: Key) => boolean;
  111 + }
  112 +
  113 + const ref = useRef<ActionType>({
  114 + reload: () => {
  115 + // implementation for reload
  116 + },
  117 + reloadAndRest: () => {
  118 + // implementation for reloadAndRest
  119 + },
  120 + reset: () => {
  121 + // implementation for reset
  122 + },
  123 + startEditable: () => {
  124 + // implementation for startEditable
  125 + },
  126 + cancelEditable: () => {
  127 + // implementation for cancelEditable
  128 + },
  129 + });
  130 +
  131 + function reload() {
  132 + ref.current.reload();
  133 + }
  134 +
  135 + async function toDelete(value) {
  136 + const res = await deleteOrderErpOrderStagesDelect({
  137 + data: {
  138 + ids: null,
  139 + deviceIds: value,
  140 + },
  141 + });
  142 + if (res) {
  143 + message.success('删除成功');
  144 + ref.current.reload();
  145 + } else {
  146 + message.error('删除失败');
  147 + }
  148 + }
  149 +
  150 + const exportLoadingDestory = () => {
  151 + message.success('导出成功');
  152 + };
  153 +
  154 + async function toExport() {
  155 + // await getOrderErpOrderStagesExport()
  156 + orderExport(
  157 + '/api/order/erp/orderStages/export',
  158 + '分期订单.xlsx',
  159 + 'get',
  160 + {},
  161 + exportLoadingDestory,
  162 + );
  163 + }
  164 +
  165 + const columns: ProColumns<OrderStagesItem>[] = [
  166 + {
  167 + title: '文件编号',
  168 + dataIndex: 'id',
  169 + width: '7%',
  170 + render: (_, record) => {
  171 + if (record.id) {
  172 + const text = record.id.toString();
  173 + const paddedText = '0'.repeat(4 - text.length) + text;
  174 + return paddedText;
  175 + }
  176 + },
  177 + },
  178 + {
  179 + title: '签合同日期',
  180 + dataIndex: 'dateRange',
  181 + valueType: 'date',
  182 + filters: true,
  183 + onFilter: true,
  184 + ellipsis: true,
  185 + width: '8%',
  186 + },
  187 + {
  188 + disable: true,
  189 + title: '合同编号',
  190 + dataIndex: 'contract',
  191 + filters: true,
  192 + onFilter: true,
  193 + ellipsis: true,
  194 + width: '9%',
  195 + },
  196 + {
  197 + disable: true,
  198 + title: '供应商名称',
  199 + dataIndex: 'vendor',
  200 + filters: true,
  201 + onFilter: true,
  202 + ellipsis: true,
  203 + },
  204 + {
  205 + disable: true,
  206 + title: '终端名称',
  207 + dataIndex: 'terminal',
  208 + filters: true,
  209 + onFilter: true,
  210 + ellipsis: true,
  211 + width: '6%',
  212 + },
  213 + {
  214 + disable: true,
  215 + title: '设备名称',
  216 + dataIndex: 'deviceName',
  217 + filters: true,
  218 + onFilter: true,
  219 + ellipsis: true,
  220 + },
  221 + {
  222 + disable: true,
  223 + title: '设备型号',
  224 + dataIndex: 'deviceModel',
  225 + filters: true,
  226 + hideInSearch: true,
  227 + onFilter: false,
  228 + ellipsis: true,
  229 + width: '10%',
  230 + },
  231 + {
  232 + disable: true,
  233 + title: '数量',
  234 + dataIndex: 'count',
  235 + filters: true,
  236 + hideInSearch: true,
  237 + onFilter: false,
  238 + ellipsis: true,
  239 + width: '4%',
  240 + },
  241 + {
  242 + disable: true,
  243 + title: '单价',
  244 + dataIndex: 'unitPrice',
  245 + filters: true,
  246 + hideInSearch: true,
  247 + onFilter: false,
  248 + ellipsis: true,
  249 + width: '5%',
  250 + },
  251 + {
  252 + disable: true,
  253 + title: '总价',
  254 + dataIndex: 'price',
  255 + filters: true,
  256 + hideInSearch: true,
  257 + onFilter: false,
  258 + ellipsis: true,
  259 + width: '5%',
  260 + },
  261 + {
  262 + disable: true,
  263 + title: '合同总金额',
  264 + dataIndex: 'totalPrice',
  265 + filters: true,
  266 + hideInSearch: true,
  267 + onFilter: false,
  268 + ellipsis: true,
  269 + width: '6%',
  270 + },
  271 + {
  272 + disable: true,
  273 + title: '付款方式',
  274 + dataIndex: 'payWay',
  275 + filters: true,
  276 + hideInSearch: true,
  277 + onFilter: false,
  278 + ellipsis: true,
  279 + },
  280 + {
  281 + disable: true,
  282 + title: '附件',
  283 + dataIndex: 'annex',
  284 + filters: true,
  285 + hideInSearch: true,
  286 + onFilter: false,
  287 + ellipsis: true,
  288 + width: '5%',
  289 + render: (_, record) => {
  290 + if (record.id) {
  291 + return <a href={record.annex}>{record.annex}</a>;
  292 + }
  293 + },
  294 + },
  295 + {
  296 + disable: true,
  297 + title: '备注',
  298 + dataIndex: 'remark',
  299 + filters: true,
  300 + hideInSearch: true,
  301 + onFilter: false,
  302 + ellipsis: true,
  303 + width: '5%',
  304 + },
  305 + {
  306 + title: '操作',
  307 + valueType: 'option',
  308 + key: 'option',
  309 + width: '10%',
  310 + render: (_text, record) => {
  311 + if (record?.id) {
  312 + return (
  313 + <>
  314 + <ReadModel currentContract={record.contract}></ReadModel>
  315 + &nbsp;
  316 + <EditorModel
  317 + currentContract={record.contract}
  318 + toReload={reload}
  319 + ></EditorModel>
  320 + &nbsp;
  321 + {/* <a key="delect" target="_blank" rel="noopener noreferrer" onClick={() => { toDelete([record.dId]) }}>
  322 + 删除
  323 + </a> */}
  324 + <Comfire currtDid={record.dId} sureDelete={toDelete}></Comfire>
  325 + </>
  326 + );
  327 + }
  328 + return null;
  329 + },
  330 + },
  331 + ];
  332 +
  333 + return (
  334 + <ProTable<OrderStagesItem>
  335 + className="title-index"
  336 + columnEmptyText=""
  337 + columns={columns}
  338 + actionRef={ref}
  339 + cardBordered
  340 + request={async (params) => {
  341 + // console.log(params);
  342 + if (
  343 + params.id !== null ||
  344 + params.contract !== null ||
  345 + params.vendor !== null ||
  346 + params.terminal !== null ||
  347 + params.deviceName !== null ||
  348 + params.dateRange !== null
  349 + ) {
  350 + // console.log(params.id);
  351 + // console.log(params.contract);
  352 + // console.log(params.vendor);
  353 + let PostOrderErpOrderStagesSearchOption = {
  354 + id: params.id,
  355 + contract: params.contract,
  356 + vendor: params.vendor,
  357 + terminal: params.terminal,
  358 + deviceName: params.deviceName,
  359 + dateRange: params.dateRange,
  360 + };
  361 + let res = await postOrderErpOrderStagesSearch({
  362 + data: { ...PostOrderErpOrderStagesSearchOption },
  363 + });
  364 + await waitTime(2000);
  365 + if (res) {
  366 + // setTableItem(res.data)
  367 + const orderStagesWithList: OrderStagesWithListItem[] = res?.data;
  368 + let orderStagesList: OrderStagesItem[] = [];
  369 + for (let ind = 0; ind < orderStagesWithList.length; ind++) {
  370 + for (
  371 + let index = 0;
  372 + index < orderStagesWithList[ind].orderStagesDeviceVoList.length;
  373 + index++
  374 + ) {
  375 + let item: OrderStagesItem = {
  376 + id: undefined,
  377 + contract: undefined,
  378 + vendor: undefined,
  379 + dateRange: undefined,
  380 + terminal: undefined,
  381 + dId: undefined,
  382 + deviceName: undefined,
  383 + deviceModel: undefined,
  384 + count: undefined,
  385 + unitPrice: undefined,
  386 + price: undefined,
  387 + totalPrice: undefined,
  388 + payWay: undefined,
  389 + annex: undefined,
  390 + remark: undefined,
  391 + };
  392 + if (index === 0) {
  393 + item.id = orderStagesWithList[ind].id;
  394 + item.contract = orderStagesWithList[ind].contract;
  395 + item.vendor = orderStagesWithList[ind].vendor;
  396 + item.dateRange = orderStagesWithList[ind].dateRange;
  397 + item.terminal = orderStagesWithList[ind].terminal;
  398 + item.dId =
  399 + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId;
  400 + item.deviceName =
  401 + orderStagesWithList[ind].orderStagesDeviceVoList[
  402 + index
  403 + ].deviceName;
  404 + item.deviceModel =
  405 + orderStagesWithList[ind].orderStagesDeviceVoList[
  406 + index
  407 + ].deviceModel;
  408 + item.count =
  409 + orderStagesWithList[ind].orderStagesDeviceVoList[
  410 + index
  411 + ].count;
  412 + item.unitPrice =
  413 + orderStagesWithList[ind].orderStagesDeviceVoList[
  414 + index
  415 + ].unitPrice;
  416 + item.price =
  417 + orderStagesWithList[ind].orderStagesDeviceVoList[
  418 + index
  419 + ].price;
  420 + item.totalPrice = orderStagesWithList[ind].totalPrice;
  421 + item.payWay = orderStagesWithList[ind].payWay;
  422 + item.annex = orderStagesWithList[ind].annex;
  423 + item.remark = orderStagesWithList[ind].remark;
  424 + orderStagesList.push(item);
  425 + } else {
  426 + item.id = orderStagesWithList[ind].id;
  427 + item.contract = orderStagesWithList[ind].contract;
  428 + item.vendor = orderStagesWithList[ind].vendor;
  429 + item.dateRange = orderStagesWithList[ind].dateRange;
  430 + item.terminal = orderStagesWithList[ind].terminal;
  431 + item.dId =
  432 + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId;
  433 + item.deviceName =
  434 + orderStagesWithList[ind].orderStagesDeviceVoList[
  435 + index
  436 + ].deviceName;
  437 + item.deviceModel =
  438 + orderStagesWithList[ind].orderStagesDeviceVoList[
  439 + index
  440 + ].deviceModel;
  441 + item.count =
  442 + orderStagesWithList[ind].orderStagesDeviceVoList[
  443 + index
  444 + ].count;
  445 + item.unitPrice =
  446 + orderStagesWithList[ind].orderStagesDeviceVoList[
  447 + index
  448 + ].unitPrice;
  449 + item.price =
  450 + orderStagesWithList[ind].orderStagesDeviceVoList[
  451 + index
  452 + ].price;
  453 + item.totalPrice = orderStagesWithList[ind].totalPrice;
  454 + item.payWay = orderStagesWithList[ind].payWay;
  455 + item.annex = orderStagesWithList[ind].annex;
  456 + item.remark = orderStagesWithList[ind].remark;
  457 + orderStagesList.push(item);
  458 + }
  459 + }
  460 + }
  461 + return {
  462 + data: orderStagesList || [],
  463 + };
  464 + }
  465 + } else {
  466 + let res = await getOrderErpOrderStagesListAll();
  467 + await waitTime(2000);
  468 + if (res) {
  469 + // setTableItem(res.data)
  470 + const orderStagesWithList: OrderStagesWithListItem[] = res?.data;
  471 + let orderStagesList: OrderStagesItem[] = [];
  472 + for (let ind = 0; ind < orderStagesWithList.length; ind++) {
  473 + for (
  474 + let index = 0;
  475 + index < orderStagesWithList[ind].orderStagesDeviceVoList.length;
  476 + index++
  477 + ) {
  478 + let item: OrderStagesItem = {
  479 + id: undefined,
  480 + contract: undefined,
  481 + vendor: undefined,
  482 + dateRange: undefined,
  483 + terminal: undefined,
  484 + dId: undefined,
  485 + deviceName: undefined,
  486 + deviceModel: undefined,
  487 + count: undefined,
  488 + unitPrice: undefined,
  489 + price: undefined,
  490 + totalPrice: undefined,
  491 + payWay: undefined,
  492 + annex: undefined,
  493 + remark: undefined,
  494 + };
  495 + if (index === 0) {
  496 + item.id = orderStagesWithList[ind].id;
  497 + item.contract = orderStagesWithList[ind].contract;
  498 + item.vendor = orderStagesWithList[ind].vendor;
  499 + item.dateRange = orderStagesWithList[ind].dateRange;
  500 + item.terminal = orderStagesWithList[ind].terminal;
  501 + item.dId =
  502 + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId;
  503 + item.deviceName =
  504 + orderStagesWithList[ind].orderStagesDeviceVoList[
  505 + index
  506 + ].deviceName;
  507 + item.deviceModel =
  508 + orderStagesWithList[ind].orderStagesDeviceVoList[
  509 + index
  510 + ].deviceModel;
  511 + item.count =
  512 + orderStagesWithList[ind].orderStagesDeviceVoList[
  513 + index
  514 + ].count;
  515 + item.unitPrice =
  516 + orderStagesWithList[ind].orderStagesDeviceVoList[
  517 + index
  518 + ].unitPrice;
  519 + item.price =
  520 + orderStagesWithList[ind].orderStagesDeviceVoList[
  521 + index
  522 + ].price;
  523 + item.totalPrice = orderStagesWithList[ind].totalPrice;
  524 + item.payWay = orderStagesWithList[ind].payWay;
  525 + item.annex = orderStagesWithList[ind].annex;
  526 + item.remark = orderStagesWithList[ind].remark;
  527 + orderStagesList.push(item);
  528 + } else {
  529 + item.id = orderStagesWithList[ind].id;
  530 + item.contract = orderStagesWithList[ind].contract;
  531 + item.vendor = orderStagesWithList[ind].vendor;
  532 + item.dateRange = orderStagesWithList[ind].dateRange;
  533 + item.terminal = orderStagesWithList[ind].terminal;
  534 + item.dId =
  535 + orderStagesWithList[ind].orderStagesDeviceVoList[index].dId;
  536 + item.deviceName =
  537 + orderStagesWithList[ind].orderStagesDeviceVoList[
  538 + index
  539 + ].deviceName;
  540 + item.deviceModel =
  541 + orderStagesWithList[ind].orderStagesDeviceVoList[
  542 + index
  543 + ].deviceModel;
  544 + item.count =
  545 + orderStagesWithList[ind].orderStagesDeviceVoList[
  546 + index
  547 + ].count;
  548 + item.unitPrice =
  549 + orderStagesWithList[ind].orderStagesDeviceVoList[
  550 + index
  551 + ].unitPrice;
  552 + item.price =
  553 + orderStagesWithList[ind].orderStagesDeviceVoList[
  554 + index
  555 + ].price;
  556 + item.totalPrice = orderStagesWithList[ind].totalPrice;
  557 + item.payWay = orderStagesWithList[ind].payWay;
  558 + item.annex = orderStagesWithList[ind].annex;
  559 + item.remark = orderStagesWithList[ind].remark;
  560 + orderStagesList.push(item);
  561 + }
  562 + }
  563 + }
  564 + return {
  565 + data: orderStagesList || [],
  566 + };
  567 + }
  568 + }
  569 + }}
  570 + editable={{
  571 + type: 'multiple',
  572 + }}
  573 + columnsState={{
  574 + persistenceKey: 'pro-table-singe-demos',
  575 + persistenceType: 'localStorage',
  576 + defaultValue: {
  577 + option: { fixed: 'right', disable: true },
  578 + },
  579 + // onChange(value) {
  580 + // console.log('value: ', value);
  581 + // },
  582 + }}
  583 + rowKey="dId"
  584 + search={{
  585 + labelWidth: 'auto',
  586 + }}
  587 + options={{
  588 + setting: {
  589 + listsHeight: 800,
  590 + },
  591 + }}
  592 + form={{
  593 + syncToUrl: (values, type) => {
  594 + if (type === 'get') {
  595 + return {
  596 + ...values,
  597 + created_at: [values.startTime, values.endTime],
  598 + };
  599 + }
  600 + return values;
  601 + },
  602 + }}
  603 + pagination={{
  604 + pageSize: 10,
  605 + // onChange: (page) => console.log(page),
  606 + }}
  607 + dateFormatter="string"
  608 + headerTitle={[]}
  609 + toolBarRender={() => [
  610 + <>
  611 + <AddModel toReload={reload}></AddModel>
  612 + <UploadModel toReload={reload}></UploadModel>
  613 + <Button
  614 + type="primary"
  615 + onClick={() => {
  616 + toExport();
  617 + }}
  618 + >
  619 + <VerticalAlignTopOutlined />
  620 + 导出
  621 + </Button>
  622 + </>,
  623 + ]}
  624 + />
  625 + );
  626 +};
src/pages/Instalment/components/upload/uploadApp.tsx 0 → 100644
  1 +import { InboxOutlined } from '@ant-design/icons';
  2 +import { Upload } from 'antd';
  3 +import React from 'react';
  4 +
  5 +const App: React.FC = ({ uploadFile }) => {
  6 + const { Dragger } = Upload;
  7 +
  8 + const props = {
  9 + name: 'file',
  10 + multiple: true,
  11 + maxCount: 1,
  12 + onChange: (info) => {
  13 + uploadFile(info.file.originFileObj);
  14 + },
  15 + };
  16 +
  17 + return (
  18 + <Dragger {...props}>
  19 + <p className="ant-upload-drag-icon">
  20 + <InboxOutlined />
  21 + </p>
  22 + <p className="ant-upload-text">
  23 + Click or drag file to this area to upload
  24 + </p>
  25 + <p className="ant-upload-hint">
  26 + Support for a single or bulk upload. Strictly prohibited from uploading
  27 + company data or other banned files.
  28 + </p>
  29 + </Dragger>
  30 + );
  31 +};
  32 +
  33 +export default App;
src/pages/Instalment/components/upload/uploadModel.tsx 0 → 100644
  1 +import { postOrderErpOrderStagesImport } from '@/services/request';
  2 +import { VerticalAlignBottomOutlined } from '@ant-design/icons';
  3 +import { ModalForm } from '@ant-design/pro-components';
  4 +import { Button, Form, message } from 'antd';
  5 +import { RcFile } from 'antd/es/upload';
  6 +import { useState } from 'react';
  7 +import App from './uploadApp';
  8 +
  9 +// const waitTime = (time: number = 100) => {
  10 +// return new Promise((resolve) => {
  11 +// setTimeout(() => {
  12 +// resolve(true);
  13 +// }, time);
  14 +// });
  15 +// };
  16 +
  17 +export default ({ toReload }) => {
  18 + const [form] = Form.useForm<{ name: string; company: string }>();
  19 + const [uploadFile, setUploadFile] = useState({});
  20 + // function setUploadFileWay(value) {
  21 + // setUploadFile(value)
  22 + // }
  23 + return (
  24 + <ModalForm<{
  25 + name: string;
  26 + company: string;
  27 + }>
  28 + title="新建表单"
  29 + trigger={
  30 + <Button type="primary">
  31 + <VerticalAlignBottomOutlined />
  32 + 导入
  33 + </Button>
  34 + }
  35 + form={form}
  36 + autoFocusFirstInput
  37 + modalProps={{
  38 + destroyOnClose: true,
  39 + }}
  40 + submitTimeout={2000}
  41 + onFinish={async () => {
  42 + const formData = new FormData();
  43 + formData.append('file', uploadFile as RcFile);
  44 + const res = await postOrderErpOrderStagesImport({
  45 + data: formData,
  46 + headers: {
  47 + 'Content-Type':
  48 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  49 + },
  50 + });
  51 + if (res) {
  52 + message.success('提交成功');
  53 + toReload();
  54 + return true;
  55 + }
  56 + }}
  57 + >
  58 + <App uploadFile={setUploadFile}></App>
  59 + </ModalForm>
  60 + );
  61 +};
src/pages/Instalment/index.tsx 0 → 100644
  1 +import Title from './components/title/title';
  2 +
  3 +const instalment_contect: React.FC = () => (
  4 + <>
  5 + <Title />
  6 + </>
  7 +);
  8 +
  9 +export default instalment_contect;
src/pages/Order/components/CheckModal.tsx
@@ -401,6 +401,9 @@ export default ({ @@ -401,6 +401,9 @@ export default ({
401 if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) { 401 if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) {
402 type = 'confirm_reissue'; 402 type = 'confirm_reissue';
403 } 403 }
  404 + if (checkType(CHECK_TYPE.CREDIT_AUDIT)) {
  405 + type = 'credit_audit';
  406 + }
404 return type; 407 return type;
405 } 408 }
406 409
@@ -648,11 +651,15 @@ export default ({ @@ -648,11 +651,15 @@ export default ({
648 ) : ( 651 ) : (
649 <div>请特别注意订单总金额与订单金额。</div> 652 <div>请特别注意订单总金额与订单金额。</div>
650 )} 653 )}
651 - <ProFormTextArea  
652 - width="lg"  
653 - name="name"  
654 - placeholder="若驳回,请填写驳回理由"  
655 - /> 654 + {!checkType(CHECK_TYPE.CONFIRM_DELIVER) ? (
  655 + <ProFormTextArea
  656 + width="lg"
  657 + name="name"
  658 + placeholder="若驳回,请填写驳回理由"
  659 + />
  660 + ) : (
  661 + <></>
  662 + )}
656 {checkType(CHECK_TYPE.FINALCIAL) ? ( 663 {checkType(CHECK_TYPE.FINALCIAL) ? (
657 <> 664 <>
658 <div className="pb-4 text-xs decoration-gray-50"> 665 <div className="pb-4 text-xs decoration-gray-50">
src/pages/Order/components/ImportExpressBillModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { postOrderImportImportWeightAndVolume } from '@/services';
  3 +import { ModalForm, ProFormUploadDragger } from '@ant-design/pro-components';
  4 +import { Button, Form, message } from 'antd';
  5 +
  6 +export default () => {
  7 + const [form] = Form.useForm();
  8 + const [messageApi, contextHolder] = message.useMessage();
  9 + return (
  10 + <>
  11 + <ModalForm
  12 + title="导入重量、体积"
  13 + trigger={<Button type="primary">导入重量、体积</Button>}
  14 + form={form}
  15 + autoFocusFirstInput
  16 + modalProps={{
  17 + destroyOnClose: true,
  18 + }}
  19 + submitTimeout={2000}
  20 + onFinish={async (values) => {
  21 + console.log(values);
  22 + const formData = new FormData();
  23 + formData.append('file', values.express[0].originFileObj);
  24 + messageApi.open({
  25 + type: 'loading',
  26 + content: '正在导入...',
  27 + duration: 0,
  28 + });
  29 + const res = await postOrderImportImportWeightAndVolume({
  30 + data: formData,
  31 + headers: {
  32 + 'Content-Type':
  33 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  34 + },
  35 + });
  36 + if (res.result === RESPONSE_CODE.SUCCESS) {
  37 + return true;
  38 + } else {
  39 + message.error('导入失败');
  40 + }
  41 + messageApi.destroy();
  42 + }}
  43 + >
  44 + <ProFormUploadDragger max={1} label="上传快递单" name="express" />
  45 + </ModalForm>
  46 + {contextHolder}
  47 + </>
  48 + );
  49 +};
src/pages/Order/components/ImportModal.tsx
@@ -26,7 +26,13 @@ export default ({ onClose }) =&gt; { @@ -26,7 +26,13 @@ export default ({ onClose }) =&gt; {
26 }; 26 };
27 const downloadTemplate = async () => { 27 const downloadTemplate = async () => {
28 exportLoading('正在下载模板...'); 28 exportLoading('正在下载模板...');
29 - orderExport('/api/service/order/exportTemplate', {}, exportLoadingDestory); 29 + orderExport(
  30 + '/api/service/order/exportTemplate',
  31 + '订单.xlsx',
  32 + 'post',
  33 + {},
  34 + exportLoadingDestory,
  35 + );
30 }; 36 };
31 37
32 const handleUpload = async () => { 38 const handleUpload = async () => {
@@ -59,6 +65,8 @@ export default ({ onClose }) =&gt; { @@ -59,6 +65,8 @@ export default ({ onClose }) =&gt; {
59 exportLoading('正在下载错误信息...'); 65 exportLoading('正在下载错误信息...');
60 orderExport( 66 orderExport(
61 '/api/service/order/errorExcelInformation', 67 '/api/service/order/errorExcelInformation',
  68 + '订单.xlsx',
  69 + 'post',
62 formData, 70 formData,
63 exportLoadingDestory, 71 exportLoadingDestory,
64 ); 72 );
src/pages/Order/components/ModifiedDiffModal.tsx
1 import { postServiceOrderModifiedDiff } from '@/services'; 1 import { postServiceOrderModifiedDiff } from '@/services';
2 -import {  
3 - enumValueToLabel,  
4 - getAliYunOSSFileNameFromUrl,  
5 - getUserInfo,  
6 -} from '@/utils'; 2 +import { enumValueToLabel, getAliYunOSSFileNameFromUrl } from '@/utils';
7 import { getReceivingCompanyOptions, isSupplier } from '@/utils/order'; 3 import { getReceivingCompanyOptions, isSupplier } from '@/utils/order';
8 import { Button, Divider, Modal, Space, Table, TableProps } from 'antd'; 4 import { Button, Divider, Modal, Space, Table, TableProps } from 'antd';
9 -import Base64 from 'base-64';  
10 import { useEffect, useState } from 'react'; 5 import { useEffect, useState } from 'react';
11 import { 6 import {
12 PAYEE_OPTIONS, 7 PAYEE_OPTIONS,
  8 + PAYMENT_CHANNEL_OPTIONS,
  9 + PAYMENT_METHOD_OPTIONS,
13 PRODUCT_BELONG_DEPARTMENT_OPTIONS, 10 PRODUCT_BELONG_DEPARTMENT_OPTIONS,
14 SHIPPING_WAREHOUSE_OPTIONS, 11 SHIPPING_WAREHOUSE_OPTIONS,
15 } from '../constant'; 12 } from '../constant';
16 import '../table.less'; 13 import '../table.less';
17 14
18 export default ({ setVisible, subOrders, mainOrder, onClose }) => { 15 export default ({ setVisible, subOrders, mainOrder, onClose }) => {
19 - const userInfo = getUserInfo();  
20 let subIds = subOrders?.map((item: any) => { 16 let subIds = subOrders?.map((item: any) => {
21 return item.id; 17 return item.id;
22 }); 18 });
@@ -77,6 +73,12 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; { @@ -77,6 +73,12 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
77 if (key === '发货仓库') { 73 if (key === '发货仓库') {
78 newText = enumValueToLabel(text, SHIPPING_WAREHOUSE_OPTIONS); 74 newText = enumValueToLabel(text, SHIPPING_WAREHOUSE_OPTIONS);
79 } 75 }
  76 + if (key === '支付渠道') {
  77 + newText = enumValueToLabel(text, PAYMENT_CHANNEL_OPTIONS);
  78 + }
  79 + if (key === '支付方式') {
  80 + newText = enumValueToLabel(text, PAYMENT_METHOD_OPTIONS);
  81 + }
80 if (key === '单价' || key === '合计') { 82 if (key === '单价' || key === '合计') {
81 newText = '¥' + newText; 83 newText = '¥' + newText;
82 } 84 }
@@ -186,6 +188,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; { @@ -186,6 +188,8 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
186 ['productBelongBusiness', '所属事业部'], 188 ['productBelongBusiness', '所属事业部'],
187 ['shippingWarehouse', '发货仓库'], 189 ['shippingWarehouse', '发货仓库'],
188 ['notes', '备注'], 190 ['notes', '备注'],
  191 + ['paymentChannel', '支付渠道'],
  192 + ['paymentMethod', '支付方式'],
189 ['listAnnex', '附件'], 193 ['listAnnex', '附件'],
190 ]; 194 ];
191 for (let field of visibleFields) { 195 for (let field of visibleFields) {
@@ -234,7 +238,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; { @@ -234,7 +238,6 @@ export default ({ setVisible, subOrders, mainOrder, onClose }) =&gt; {
234 ['institutionContactName', '单位联系人'], 238 ['institutionContactName', '单位联系人'],
235 ['institution', '单位'], 239 ['institution', '单位'],
236 ['totalPayment', '支付总金额'], 240 ['totalPayment', '支付总金额'],
237 - ['paymentChannel', '支付渠道'],  
238 ['notes', '备注'], 241 ['notes', '备注'],
239 ['bank', '开户银行'], 242 ['bank', '开户银行'],
240 ['bankAccountNumber', '银行账号'], 243 ['bankAccountNumber', '银行账号'],
src/pages/Order/components/OrderDrawer.tsx
1 import { RESPONSE_CODE } from '@/constants/enum'; 1 import { RESPONSE_CODE } from '@/constants/enum';
2 import { 2 import {
3 postCanrdApiUserAddressList, 3 postCanrdApiUserAddressList,
4 - postCanrdApiUserList, 4 + postCanrdApiUserDetail,
  5 + postCanrdApiUserNowMoneyCheck,
5 postKingdeeRepCustomerDetail, 6 postKingdeeRepCustomerDetail,
6 postKingdeeRepMaterial, 7 postKingdeeRepMaterial,
7 postKingdeeRepMaterialUnit, 8 postKingdeeRepMaterialUnit,
8 postKingdeeRepMeasureUnit, 9 postKingdeeRepMeasureUnit,
  10 + postPrepaidPhoneAvailableList,
9 postServiceOrderAddOrder, 11 postServiceOrderAddOrder,
10 postServiceOrderAfterSalesQuerySnapshotOrder, 12 postServiceOrderAfterSalesQuerySnapshotOrder,
11 postServiceOrderApplyAfterSales, 13 postServiceOrderApplyAfterSales,
12 postServiceOrderApplyModify, 14 postServiceOrderApplyModify,
13 - postServiceOrderQuerySalesCode,  
14 postServiceOrderUpdateOrder, 15 postServiceOrderUpdateOrder,
15 } from '@/services'; 16 } from '@/services';
16 import { 17 import {
@@ -22,6 +23,7 @@ import { @@ -22,6 +23,7 @@ import {
22 } from '@/utils'; 23 } from '@/utils';
23 import { getDefaultString } from '@/utils/StringUtil'; 24 import { getDefaultString } from '@/utils/StringUtil';
24 import { getTeacherCustomFieldNumber } from '@/utils/kingdee'; 25 import { getTeacherCustomFieldNumber } from '@/utils/kingdee';
  26 +import { getSalesCodeOptions } from '@/utils/order';
25 import { 27 import {
26 DrawerForm, 28 DrawerForm,
27 FormListActionType, 29 FormListActionType,
@@ -106,6 +108,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -106,6 +108,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
106 }, 108 },
107 ]; 109 ];
108 }>(); 110 }>();
  111 + const [accountOptions, setAccountOptions] = useState<any>([]);
109 112
110 let copyData = cloneDeep(data); 113 let copyData = cloneDeep(data);
111 114
@@ -122,15 +125,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -122,15 +125,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
122 /** 125 /**
123 * 获取销售代码枚举,在复制和编辑的时候判断是否为旧的代码 126 * 获取销售代码枚举,在复制和编辑的时候判断是否为旧的代码
124 */ 127 */
125 - const getSalesCodeOptions = async () => {  
126 - const res = await postServiceOrderQuerySalesCode();  
127 - let options = res.data?.map((item) => {  
128 - return {  
129 - label: item.userName,  
130 - value: item.userName,  
131 - number: item.number,  
132 - };  
133 - }); 128 + const loadSalesCodeOptions = async () => {
  129 + let options = await getSalesCodeOptions();
134 setSalesCodeOptions(options); 130 setSalesCodeOptions(options);
135 131
136 if (optType('copy') || optType('edit')) { 132 if (optType('copy') || optType('edit')) {
@@ -236,6 +232,38 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -236,6 +232,38 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
236 // } 232 // }
237 233
238 /** 234 /**
  235 + * 加载预存账号的options
  236 + */
  237 + async function loadAccountOptions(phone: any) {
  238 + let newAccountOptions = [];
  239 + //预存账号id
  240 + let uid = copyData.prepaidUid;
  241 + let res = await postCanrdApiUserDetail({ data: { uid: uid } });
  242 + if (res && res.result === RESPONSE_CODE.SUCCESS && res.data !== null) {
  243 + let uidDetail = res.data;
  244 + uidDetail.value = uid;
  245 + uidDetail.label = uidDetail.realName;
  246 + newAccountOptions.push(uidDetail);
  247 + }
  248 +
  249 + //查询当前手机号允许使用的预存账号
  250 + if (phone) {
  251 + let res = await postPrepaidPhoneAvailableList({ data: { phone: phone } });
  252 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  253 + let uidDetails = res.data;
  254 + for (let detail of uidDetails) {
  255 + detail.value = detail.uid;
  256 + detail.label = detail.realName;
  257 + newAccountOptions.push(detail);
  258 + }
  259 + }
  260 + }
  261 +
  262 + console.log(newAccountOptions);
  263 + setAccountOptions(newAccountOptions);
  264 + }
  265 +
  266 + /**
239 * 构建回显数据 267 * 构建回显数据
240 */ 268 */
241 function buildOrderData() { 269 function buildOrderData() {
@@ -303,6 +331,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -303,6 +331,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
303 if (!optType('after-sales-check')) { 331 if (!optType('after-sales-check')) {
304 // showKindeeInfo(); 332 // showKindeeInfo();
305 } 333 }
  334 +
  335 + loadAccountOptions(form.getFieldValue('customerContactNumber'));
306 } 336 }
307 } 337 }
308 338
@@ -524,6 +554,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -524,6 +554,8 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
524 getDefaultString(option.detail), 554 getDefaultString(option.detail),
525 ); 555 );
526 form.setFieldValue('customerNameString', option.realName); 556 form.setFieldValue('customerNameString', option.realName);
  557 +
  558 + loadAccountOptions(option.phone);
527 } 559 }
528 560
529 //erp收货地址:需要与客户联系人中的地址一样:姓名,手机号,地址 561 //erp收货地址:需要与客户联系人中的地址一样:姓名,手机号,地址
@@ -586,6 +618,56 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -586,6 +618,56 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
586 } 618 }
587 619
588 /** 620 /**
  621 + * 检查用户额度
  622 + * @param option
  623 + */
  624 + const checkAccountMoney = async (uid: any, subPrice: any) => {
  625 + let res = await postCanrdApiUserNowMoneyCheck({
  626 + data: { uid: uid, subPrice: subPrice },
  627 + });
  628 + if (res && res.result === RESPONSE_CODE.SUCCESS && res.data) {
  629 + let data = res.data;
  630 + let isCredit = data.isCredit;
  631 + if (isCredit) {
  632 + return true;
  633 + }
  634 +
  635 + message.error(
  636 + '用户余额不足,当前预减的金额为:' +
  637 + data.subPrice +
  638 + ',当前账号余额为:' +
  639 + data.nowMoney +
  640 + ',当前账号可赊账额度为:' +
  641 + data.creditLimit,
  642 + );
  643 + return false;
  644 + }
  645 +
  646 + return false;
  647 + };
  648 +
  649 + /**
  650 + * 总金额改变触发事件
  651 + * 如果是预存单,需要检查余额
  652 + * @param value
  653 + */
  654 + const totalPaymentChange = (value: any) => {
  655 + let paymentMethod = form.getFieldValue('paymentMethod');
  656 + let prepaidUid = form.getFieldValue('prepaidUid');
  657 + if (
  658 + value &&
  659 + paymentMethod &&
  660 + paymentMethod === 'WITHHOLDING_ADVANCE_DEPOSIT' &&
  661 + prepaidUid
  662 + ) {
  663 + let valid = checkAccountMoney(prepaidUid, value);
  664 + if (!valid) {
  665 + form.setFieldValue('prepaidUid', undefined);
  666 + }
  667 + }
  668 + };
  669 +
  670 + /**
589 * 检查客户是否可以编辑 671 * 检查客户是否可以编辑
590 * @returns 672 * @returns
591 */ 673 */
@@ -658,6 +740,18 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -658,6 +740,18 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
658 } 740 }
659 } 741 }
660 742
  743 + const validateContactNumber = (_: any, value: any) => {
  744 + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  745 + const phoneRegex = /^\d{1,11}(-\d{1,11})?$/;
  746 +
  747 + if (emailRegex.test(value) || phoneRegex.test(value)) {
  748 + return Promise.resolve();
  749 + }
  750 + return Promise.reject(
  751 + new Error('联系方式必须是邮箱或手机号格式(不能包含空格等特殊符号)'),
  752 + );
  753 + };
  754 +
661 /** 755 /**
662 * 刪除草稿数据 756 * 刪除草稿数据
663 */ 757 */
@@ -667,7 +761,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -667,7 +761,7 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
667 761
668 useEffect(() => { 762 useEffect(() => {
669 checkHasLocalData(); 763 checkHasLocalData();
670 - getSalesCodeOptions(); 764 + loadSalesCodeOptions();
671 if (optType('after-sales-check')) { 765 if (optType('after-sales-check')) {
672 getOldOrderData(data.id); 766 getOldOrderData(data.id);
673 } else { 767 } else {
@@ -949,7 +1043,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -949,7 +1043,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
949 } 1043 }
950 1044
951 let title = ''; 1045 let title = '';
952 - let spanText = '';  
953 let realName = item.realName; 1046 let realName = item.realName;
954 let phone = item.phone; 1047 let phone = item.phone;
955 let province = item.province; 1048 let province = item.province;
@@ -959,31 +1052,41 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -959,31 +1052,41 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
959 let institution = item.institution; 1052 let institution = item.institution;
960 let institutionContactName = item.institutionContactName; 1053 let institutionContactName = item.institutionContactName;
961 1054
962 - title =  
963 - getDefaultString(realName) +  
964 - '|' +  
965 - getDefaultString(phone) +  
966 - '|' +  
967 - getDefaultString(institution) +  
968 - '|' +  
969 - getDefaultString(institutionContactName) +  
970 - '|' + 1055 + let address =
971 getDefaultString(province) + 1056 getDefaultString(province) +
972 getDefaultString(city) + 1057 getDefaultString(city) +
973 getDefaultString(district) + 1058 getDefaultString(district) +
974 getDefaultString(detail); 1059 getDefaultString(detail);
975 1060
976 - spanText = 1061 + title =
977 getDefaultString(realName) + 1062 getDefaultString(realName) +
978 '|' + 1063 '|' +
979 getDefaultString(phone) + 1064 getDefaultString(phone) +
980 '|' + 1065 '|' +
981 getDefaultString(institution) + 1066 getDefaultString(institution) +
982 '|' + 1067 '|' +
983 - getDefaultString(institutionContactName); 1068 + getDefaultString(institutionContactName) +
  1069 + '|' +
  1070 + address;
  1071 +
984 return ( 1072 return (
985 - <div title={title}>  
986 - <span style={{ color: '#333333' }}>{spanText}</span> 1073 + <div title={title} className="whitespace-normal">
  1074 + <span style={{ color: '#333333' }}>
  1075 + {getDefaultString(realName)}
  1076 + </span>
  1077 + |
  1078 + <span className="text-sky-600">
  1079 + {getDefaultString(phone)}
  1080 + </span>
  1081 + |
  1082 + <span style={{ color: '#333333' }}>
  1083 + {getDefaultString(institution)}
  1084 + </span>
  1085 + |
  1086 + <span style={{ color: '#333333' }}>
  1087 + {getDefaultString(institutionContactName)}
  1088 + </span>
  1089 + |<span className="text-orange-400">{address}</span>
987 </div> 1090 </div>
988 ); 1091 );
989 }, 1092 },
@@ -991,6 +1094,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -991,6 +1094,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
991 debounceTime={1000} 1094 debounceTime={1000}
992 request={async (value, {}) => { 1095 request={async (value, {}) => {
993 const keywords = value.keyWords; 1096 const keywords = value.keyWords;
  1097 + if (keywords === '') {
  1098 + return [];
  1099 + }
994 const res = await postCanrdApiUserAddressList({ 1100 const res = await postCanrdApiUserAddressList({
995 data: { keywords: keywords }, 1101 data: { keywords: keywords },
996 }); 1102 });
@@ -1044,7 +1150,15 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1044,7 +1150,15 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1044 name="customerContactNumber" 1150 name="customerContactNumber"
1045 label="联系方式" 1151 label="联系方式"
1046 placeholder="请输入联系方式" 1152 placeholder="请输入联系方式"
1047 - rules={[{ required: true, message: '联系方式必填' }]} 1153 + fieldProps={{
  1154 + onBlur: (v) => {
  1155 + loadAccountOptions(v.target.value);
  1156 + },
  1157 + }}
  1158 + rules={[
  1159 + { required: true, message: '联系方式必填' },
  1160 + { validator: validateContactNumber },
  1161 + ]}
1048 /> 1162 />
1049 <ProFormText 1163 <ProFormText
1050 width="lg" 1164 width="lg"
@@ -1080,7 +1194,12 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1080,7 +1194,12 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1080 { required: true, message: '支付总额必填' }, 1194 { required: true, message: '支付总额必填' },
1081 { 1195 {
1082 validator: (_, value) => { 1196 validator: (_, value) => {
1083 - if (value <= 0) { 1197 + let paymentMethod = form.getFieldValue('paymentMethod');
  1198 + if (
  1199 + value <= 0 &&
  1200 + paymentMethod &&
  1201 + paymentMethod === 'WITHHOLDING_ADVANCE_DEPOSIT'
  1202 + ) {
1084 return Promise.reject( 1203 return Promise.reject(
1085 new Error( 1204 new Error(
1086 '支付总额必须大于0 (扣预存的订单现在也必须填写实际金额)', 1205 '支付总额必须大于0 (扣预存的订单现在也必须填写实际金额)',
@@ -1103,6 +1222,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1103,6 +1222,9 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1103 计算 1222 计算
1104 </Button> 1223 </Button>
1105 ), 1224 ),
  1225 + onChange: (value: any) => {
  1226 + totalPaymentChange(value);
  1227 + },
1106 }} 1228 }}
1107 disabled={optType('after-sales-check')} 1229 disabled={optType('after-sales-check')}
1108 /> 1230 />
@@ -1138,8 +1260,15 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1138,8 +1260,15 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1138 hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'} 1260 hidden={paymentMethod !== 'WITHHOLDING_ADVANCE_DEPOSIT'}
1139 showSearch 1261 showSearch
1140 label="预存账号" 1262 label="预存账号"
1141 - onChange={(option: any) => {  
1142 - form.setFieldValue('prepaidAmount', option.nowMoney); 1263 + onChange={(value: any) => {
  1264 + //检查用户额度
  1265 + let valid = checkAccountMoney(
  1266 + value,
  1267 + form.getFieldValue('totalPayment'),
  1268 + );
  1269 + if (!valid) {
  1270 + form.setFieldValue('prepaidUid', undefined);
  1271 + }
1143 }} 1272 }}
1144 placeholder="请选择预存账号" 1273 placeholder="请选择预存账号"
1145 rules={[ 1274 rules={[
@@ -1170,21 +1299,22 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1170,21 +1299,22 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1170 }, 1299 },
1171 }} 1300 }}
1172 debounceTime={1000} 1301 debounceTime={1000}
1173 - request={async (value, {}) => {  
1174 - const keywords = value.keyWords;  
1175 - const res = await postCanrdApiUserList({  
1176 - data: { keywords: keywords, pageSize: 1000000 },  
1177 - });  
1178 - let options = res?.data?.data?.map((c: any) => {  
1179 - return {  
1180 - ...c,  
1181 - label: c.realName,  
1182 - value: c.uid,  
1183 - key: c.uid,  
1184 - };  
1185 - });  
1186 - return options;  
1187 - }} 1302 + // request={async (value, {}) => {
  1303 + // const keywords = value.keyWords;
  1304 + // const res = await postCanrdApiUserList({
  1305 + // data: { keywords: keywords, pageSize: 50 },
  1306 + // });
  1307 + // let options = res?.data?.data?.map((c: any) => {
  1308 + // return {
  1309 + // ...c,
  1310 + // label: c.realName,
  1311 + // value: c.uid,
  1312 + // key: c.uid,
  1313 + // };
  1314 + // });
  1315 + // return options;
  1316 + // }}
  1317 + options={accountOptions}
1188 /> 1318 />
1189 <ProFormSelect 1319 <ProFormSelect
1190 placeholder="选择是否需要开票" 1320 placeholder="选择是否需要开票"
@@ -1305,8 +1435,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1305,8 +1435,6 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1305 (sum, item) => FloatAdd(sum, item.subOrderPayment), 1435 (sum, item) => FloatAdd(sum, item.subOrderPayment),
1306 0, 1436 0,
1307 ); 1437 );
1308 - console.log(reduce);  
1309 - console.log(totalPayment);  
1310 if (reduce === totalPayment || value) { 1438 if (reduce === totalPayment || value) {
1311 return Promise.resolve(); 1439 return Promise.resolve();
1312 } 1440 }
@@ -1516,8 +1644,20 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; { @@ -1516,8 +1644,20 @@ export default ({ onClose, data, subOrders, orderOptType }) =&gt; {
1516 label="商品数量" 1644 label="商品数量"
1517 fieldProps={{ 1645 fieldProps={{
1518 onChange: (value) => { 1646 onChange: (value) => {
1519 - listMeta.record.quantity = value;  
1520 - computeSubOrderPayment(listMeta); 1647 + // 确保变更后的值为整数
  1648 + const intValue = parseInt(value, 10);
  1649 + if (!isNaN(intValue)) {
  1650 + listMeta.record.quantity = intValue;
  1651 + computeSubOrderPayment(listMeta);
  1652 + }
  1653 + },
  1654 + parser: (value) => {
  1655 + // 将输入的值转换为整数,如果不是合法数字则返回空字符串触发校验错误
  1656 + return value ? parseInt(value, 10) : '';
  1657 + },
  1658 + formatter: (value) => {
  1659 + // 在显示时始终将其格式化为不带小数部分的整数字符串
  1660 + return value ? value.toString() : '';
1521 }, 1661 },
1522 }} 1662 }}
1523 placeholder="请输入商品数量" 1663 placeholder="请输入商品数量"
src/pages/Order/constant.ts
1 import { postServiceOrderQueryCustomerInformation } from '@/services'; 1 import { postServiceOrderQueryCustomerInformation } from '@/services';
2 import { enumToProTableEnumValue } from '@/utils'; 2 import { enumToProTableEnumValue } from '@/utils';
3 import { getReceivingCompanyOptions, isSupplier } from '@/utils/order'; 3 import { getReceivingCompanyOptions, isSupplier } from '@/utils/order';
4 -  
5 export const COMFIR_RECEIPT_IMAGES_NUMBER = 3; 4 export const COMFIR_RECEIPT_IMAGES_NUMBER = 3;
6 5
7 export const PAYMENT_CHANNEL_OPTIONS = { 6 export const PAYMENT_CHANNEL_OPTIONS = {
@@ -29,6 +28,7 @@ export const PAYMENT_METHOD_OPTIONS = { @@ -29,6 +28,7 @@ export const PAYMENT_METHOD_OPTIONS = {
29 CASH_ON_DELIVERY: '货到付款', 28 CASH_ON_DELIVERY: '货到付款',
30 HIRE_PURCHASE: '分期付款', 29 HIRE_PURCHASE: '分期付款',
31 PAYMENT_RECEIPT: '已回款', 30 PAYMENT_RECEIPT: '已回款',
  31 + PREPAID_NO_NEED_SEND: '预存款无需发货',
32 }; 32 };
33 33
34 export const PRODUCT_BELONG_DEPARTMENT_OPTIONS = { 34 export const PRODUCT_BELONG_DEPARTMENT_OPTIONS = {
@@ -108,6 +108,7 @@ export const CHECK_TYPE = { @@ -108,6 +108,7 @@ export const CHECK_TYPE = {
108 PAYMENT_RECEIPTS_AUDIT: 'PAYMENT_RECEIPTS_AUDIT', 108 PAYMENT_RECEIPTS_AUDIT: 'PAYMENT_RECEIPTS_AUDIT',
109 CONFIRM_REISSUE: 'CONFIRM_REISSUE', 109 CONFIRM_REISSUE: 'CONFIRM_REISSUE',
110 PREPAID_AUDIT: 'PREPAID_AUDIT', 110 PREPAID_AUDIT: 'PREPAID_AUDIT',
  111 + CREDIT_AUDIT: 'CREDIT_AUDIT',
111 }; 112 };
112 113
113 /** 114 /**
@@ -170,6 +171,7 @@ export const PAYMENT_RECEIPTS_STATUS_OPTIONS = { @@ -170,6 +171,7 @@ export const PAYMENT_RECEIPTS_STATUS_OPTIONS = {
170 171
171 export const ORDER_STATUS_OPTIONS = { 172 export const ORDER_STATUS_OPTIONS = {
172 WAIT_CONFIRM_DELIVER_AFTER_INVOICE: '待开票后确认发货', 173 WAIT_CONFIRM_DELIVER_AFTER_INVOICE: '待开票后确认发货',
  174 + SALES_CONFIRM: '销售待确认',
173 UNAUDITED: '未审核', 175 UNAUDITED: '未审核',
174 LEADER_PROCESS: '领导待审核', 176 LEADER_PROCESS: '领导待审核',
175 MODIFY_APPLY_WAIT_FOR_AUDIT: '修改待审核', 177 MODIFY_APPLY_WAIT_FOR_AUDIT: '修改待审核',
@@ -190,6 +192,7 @@ export const ORDER_STATUS_OPTIONS = { @@ -190,6 +192,7 @@ export const ORDER_STATUS_OPTIONS = {
190 AFTER_SALES_FAILURE: '售后失败', 192 AFTER_SALES_FAILURE: '售后失败',
191 NO_NEED_SEND: '无需发货', 193 NO_NEED_SEND: '无需发货',
192 PROCURE_CONVERT_WAREHOUSE_KEEPER: '采购转仓库', 194 PROCURE_CONVERT_WAREHOUSE_KEEPER: '采购转仓库',
  195 + CREDIT_CONFIRM: '赊账待审核',
193 }; 196 };
194 197
195 export const MODIFIED_AUDIT_STATUS_OPTIONS = { 198 export const MODIFIED_AUDIT_STATUS_OPTIONS = {
@@ -221,17 +224,11 @@ export const FINANCIAL_STATUS_OPTIONS = { @@ -221,17 +224,11 @@ export const FINANCIAL_STATUS_OPTIONS = {
221 UN_INVOICING: '取消开票', 224 UN_INVOICING: '取消开票',
222 }; 225 };
223 226
224 -/*export const getAfterInvoicingStatus = async () => {  
225 - let res = await postServiceConstAfterInvoicingStatus();  
226 - if (res.result === RESPONSE_CODE.SUCCESS) {  
227 - return res.data;  
228 - }  
229 - return {};  
230 -};*/  
231 -export let AFTER_INVOICING_STATUS = { 227 +export const AFTER_INVOICING_STATUS = {
232 NOT_YET_INVOICED: '尚未开票', 228 NOT_YET_INVOICED: '尚未开票',
233 APPLY_FOR_INVOICING: '申请开票', 229 APPLY_FOR_INVOICING: '申请开票',
234 URGENT_INVOICE_AUDITING: '加急待审核', 230 URGENT_INVOICE_AUDITING: '加急待审核',
  231 + URGENT_INVOICE_AUDIT_NOTPASS: '加急审核失败',
235 PARTIAL_INVOICING: '部分开票', 232 PARTIAL_INVOICING: '部分开票',
236 COMPLETE_INVOICING: '完全开票', 233 COMPLETE_INVOICING: '完全开票',
237 INVOICING: '开票中', 234 INVOICING: '开票中',
@@ -281,6 +278,10 @@ export const TAGS_COLOR = new Map&lt;string, string&gt;([ @@ -281,6 +278,10 @@ export const TAGS_COLOR = new Map&lt;string, string&gt;([
281 ['AUDIT_NOTPASS', 'error'], 278 ['AUDIT_NOTPASS', 'error'],
282 ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'], 279 ['WAIT_CONFIRM_DELIVER_AFTER_INVOICE', 'processing'],
283 ['INVOICING', 'processing'], 280 ['INVOICING', 'processing'],
  281 + ['SALES_CONFIRM', 'warning'],
  282 + ['URGENT_INVOICE_AUDIT_NOTPASS', 'red'],
  283 + ['REISSUE', 'processing'],
  284 + ['CREDIT_CONFIRM', 'warning'],
284 ]); 285 ]);
285 export const SALES_CODE_OPTIONS = [ 286 export const SALES_CODE_OPTIONS = [
286 { label: 'D-Linda', value: 'D-Linda' }, 287 { label: 'D-Linda', value: 'D-Linda' },
@@ -408,6 +409,8 @@ export const HISTORY_OPT_TYPE = new Map&lt;string, string&gt;([ @@ -408,6 +409,8 @@ export const HISTORY_OPT_TYPE = new Map&lt;string, string&gt;([
408 ['applyModify', '申请修改订单信息'], 409 ['applyModify', '申请修改订单信息'],
409 ['OUTSIDE_SYSTEM_PUSH', '外部系统推送了本订单'], 410 ['OUTSIDE_SYSTEM_PUSH', '外部系统推送了本订单'],
410 ['cancelSendOrder', '取消发货'], 411 ['cancelSendOrder', '取消发货'],
  412 + ['salesConfirm', '商城订单销售确认'],
  413 + ['credit_audit', '赊账审核'],
411 ]); 414 ]);
412 415
413 export const MAIN_ORDER_COLUMNS = [ 416 export const MAIN_ORDER_COLUMNS = [
@@ -621,10 +624,6 @@ export const MAIN_ORDER_COLUMNS = [ @@ -621,10 +624,6 @@ export const MAIN_ORDER_COLUMNS = [
621 dataIndex: 'afterInvoicingStatus', 624 dataIndex: 'afterInvoicingStatus',
622 valueType: 'select', 625 valueType: 'select',
623 hideInTable: true, 626 hideInTable: true,
624 - /*request: async () => {  
625 - let status = await getAfterInvoicingStatus();  
626 - return enumToSelect(status);  
627 - },*/  
628 valueEnum: enumToProTableEnumValue(AFTER_INVOICING_STATUS), 627 valueEnum: enumToProTableEnumValue(AFTER_INVOICING_STATUS),
629 }, 628 },
630 { 629 {
src/pages/Order/index.tsx
1 import ButtonConfirm from '@/components/ButtomConfirm'; 1 import ButtonConfirm from '@/components/ButtomConfirm';
2 import { RESPONSE_CODE } from '@/constants/enum'; 2 import { RESPONSE_CODE } from '@/constants/enum';
  3 +import ImportExpressBillModal from '@/pages/Order/components/ImportExpressBillModal';
3 import InvoicingDrawerForm from '@/pages/Order/components/InvoicingDrawerForm'; 4 import InvoicingDrawerForm from '@/pages/Order/components/InvoicingDrawerForm';
4 import ReissueModal from '@/pages/Order/components/ReissueModal'; 5 import ReissueModal from '@/pages/Order/components/ReissueModal';
5 import { 6 import {
@@ -15,6 +16,7 @@ import { @@ -15,6 +16,7 @@ import {
15 postServiceOrderProvideProcurementRoles, 16 postServiceOrderProvideProcurementRoles,
16 postServiceOrderQueryServiceOrder, 17 postServiceOrderQueryServiceOrder,
17 postServiceOrderSaleCancelInvoicing, 18 postServiceOrderSaleCancelInvoicing,
  19 + postServiceOrderSalesConfirm,
18 } from '@/services'; 20 } from '@/services';
19 import { orderExport } from '@/services/order'; 21 import { orderExport } from '@/services/order';
20 import { 22 import {
@@ -798,7 +800,7 @@ const OrderPage = () =&gt; { @@ -798,7 +800,7 @@ const OrderPage = () =&gt; {
798 key={index} 800 key={index}
799 onConfirm={() => { 801 onConfirm={() => {
800 window.open( 802 window.open(
801 - '/previewApi/onlinePreview?url=' + 803 + '/onlinePreview?url=' +
802 encodeURIComponent(Base64.encode(item.url)), 804 encodeURIComponent(Base64.encode(item.url)),
803 ); 805 );
804 }} 806 }}
@@ -1261,6 +1263,25 @@ const OrderPage = () =&gt; { @@ -1261,6 +1263,25 @@ const OrderPage = () =&gt; {
1261 </div> 1263 </div>
1262 </Flex> 1264 </Flex>
1263 <Flex className="w-[18%]" wrap="wrap" gap="small"> 1265 <Flex className="w-[18%]" wrap="wrap" gap="small">
  1266 + {optRecord.subPath?.includes('salesConfirm') && (
  1267 + <ButtonConfirm
  1268 + className="p-0"
  1269 + title="是否确认此商城订单信息无误?确认无误之后订单将进入审核流程。"
  1270 + text="订单确认"
  1271 + onConfirm={async () => {
  1272 + let res = await postServiceOrderSalesConfirm({
  1273 + data: {
  1274 + subOrderIds: [optRecord.id],
  1275 + },
  1276 + });
  1277 +
  1278 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  1279 + message.success(res.message);
  1280 + refreshTable();
  1281 + }
  1282 + }}
  1283 + />
  1284 + )}
1264 {optRecord.subPath?.includes('uploadPaymentReceiptBill') ? ( 1285 {optRecord.subPath?.includes('uploadPaymentReceiptBill') ? (
1265 <Button 1286 <Button
1266 className="p-0" 1287 className="p-0"
@@ -1327,6 +1348,23 @@ const OrderPage = () =&gt; { @@ -1327,6 +1348,23 @@ const OrderPage = () =&gt; {
1327 '' 1348 ''
1328 )} 1349 )}
1329 1350
  1351 + {optRecord.subPath?.includes('creditAudit') ? (
  1352 + <Button
  1353 + className="p-0"
  1354 + type="link"
  1355 + onClick={() => {
  1356 + setCurrentMainId(record.id);
  1357 + setCurretnOptSubId(optRecord.id);
  1358 + setCheckVisible(true);
  1359 + setOrderCheckType(CHECK_TYPE.CREDIT_AUDIT);
  1360 + }}
  1361 + >
  1362 + 赊账审核
  1363 + </Button>
  1364 + ) : (
  1365 + ''
  1366 + )}
  1367 +
1330 {optRecord.subPath?.includes('auditPaymentReceipt') ? ( 1368 {optRecord.subPath?.includes('auditPaymentReceipt') ? (
1331 <Button 1369 <Button
1332 className="p-0" 1370 className="p-0"
@@ -1975,7 +2013,7 @@ const OrderPage = () =&gt; { @@ -1975,7 +2013,7 @@ const OrderPage = () =&gt; {
1975 2013
1976 <Flex title={optRecord.notes}> 2014 <Flex title={optRecord.notes}>
1977 <div 2015 <div
1978 - className="overflow-hidden whitespace-normal overflow-ellipsis hover:cursor-pointer" 2016 + className="max-w-[1100px] overflow-hidden whitespace-normal overflow-ellipsis hover:cursor-pointer"
1979 onClick={() => { 2017 onClick={() => {
1980 copyToClipboard(optRecord.notes); 2018 copyToClipboard(optRecord.notes);
1981 message.info('备注复制成功:' + optRecord.notes); 2019 message.info('备注复制成功:' + optRecord.notes);
@@ -2427,7 +2465,7 @@ const OrderPage = () =&gt; { @@ -2427,7 +2465,7 @@ const OrderPage = () =&gt; {
2427 )} 2465 )}
2428 className="whitespace-no-wrap overflow-hidden overflow-ellipsis max-w-[400px]" 2466 className="whitespace-no-wrap overflow-hidden overflow-ellipsis max-w-[400px]"
2429 > 2467 >
2430 - <span className="text-[#8C8C8C]">开票款单位:</span> 2468 + <span className="text-[#8C8C8C]">开票款单位:</span>
2431 <span className="text-slate-700"> 2469 <span className="text-slate-700">
2432 {record.receivingCompany !== null 2470 {record.receivingCompany !== null
2433 ? enumValueToLabel( 2471 ? enumValueToLabel(
@@ -2571,6 +2609,37 @@ const OrderPage = () =&gt; { @@ -2571,6 +2609,37 @@ const OrderPage = () =&gt; {
2571 <Flex justify="flex-end"> 2609 <Flex justify="flex-end">
2572 <Space.Compact direction="vertical" align="end"> 2610 <Space.Compact direction="vertical" align="end">
2573 <Space wrap> 2611 <Space wrap>
  2612 + {record.mainPath?.includes('salesConfirm') && (
  2613 + <ButtonConfirm
  2614 + className="p-0"
  2615 + title="是否确认此商城订单信息无误?确认无误之后订单将进入审核流程。"
  2616 + text="订单确认"
  2617 + onConfirm={async () => {
  2618 + let subIds = subOrderSelectedMap
  2619 + .get(record.id)
  2620 + ?.map((item) => {
  2621 + return item.id;
  2622 + });
  2623 + if (subIds === null || subIds === undefined) {
  2624 + subIds = record.subOrderInformationLists.map(
  2625 + (item) => {
  2626 + return item.id;
  2627 + },
  2628 + );
  2629 + }
  2630 + let res = await postServiceOrderSalesConfirm({
  2631 + data: {
  2632 + subOrderIds: subIds,
  2633 + },
  2634 + });
  2635 +
  2636 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  2637 + message.success(res.message);
  2638 + refreshTable();
  2639 + }
  2640 + }}
  2641 + />
  2642 + )}
2574 {record.mainPath?.includes('uploadPaymentReceiptBill') ? ( 2643 {record.mainPath?.includes('uploadPaymentReceiptBill') ? (
2575 <Button 2644 <Button
2576 className="p-0" 2645 className="p-0"
@@ -2862,6 +2931,38 @@ const OrderPage = () =&gt; { @@ -2862,6 +2931,38 @@ const OrderPage = () =&gt; {
2862 '' 2931 ''
2863 )} 2932 )}
2864 2933
  2934 + {record.mainPath?.includes('creditAudit') ? (
  2935 + <Button
  2936 + className="p-0"
  2937 + type="link"
  2938 + onClick={() => {
  2939 + let selectedSubOrders = subOrderSelectedMap.get(
  2940 + record.id,
  2941 + );
  2942 + setSelectedRows(selectedSubOrders);
  2943 + if (selectedSubOrders === undefined) {
  2944 + selectedSubOrders = record.subOrderInformationLists;
  2945 + }
  2946 + for (let i = 0; i < selectedSubOrders.length; i++) {
  2947 + if (
  2948 + selectedSubOrders[i].orderStatus !==
  2949 + 'CREDIT_CONFIRM'
  2950 + ) {
  2951 + message.error('请选择[赊账待审核]的子订单进行审核');
  2952 + return;
  2953 + }
  2954 + }
  2955 + createOptObject(null, record.id);
  2956 + setCheckVisible(true);
  2957 + setOrderCheckType(CHECK_TYPE.CREDIT_AUDIT);
  2958 + }}
  2959 + >
  2960 + 赊账审核
  2961 + </Button>
  2962 + ) : (
  2963 + ''
  2964 + )}
  2965 +
2865 {record.mainPath?.includes('editProductionTime') ? ( 2966 {record.mainPath?.includes('editProductionTime') ? (
2866 <Button 2967 <Button
2867 className="p-0" 2968 className="p-0"
@@ -3203,10 +3304,11 @@ const OrderPage = () =&gt; { @@ -3203,10 +3304,11 @@ const OrderPage = () =&gt; {
3203 if ( 3304 if (
3204 orderStatus !== 'UNAUDITED' && 3305 orderStatus !== 'UNAUDITED' &&
3205 orderStatus !== 'AUDIT_FAILED' && 3306 orderStatus !== 'AUDIT_FAILED' &&
3206 - orderStatus !== 'LEADER_PROCESS' 3307 + orderStatus !== 'LEADER_PROCESS' &&
  3308 + orderStatus !== 'SALES_CONFIRM'
3207 ) { 3309 ) {
3208 message.error( 3310 message.error(
3209 - '请选择未审核或者审核失败的订单进行编辑', 3311 + '请选择【未审核、审核失败、销售待确认】的订单进行编辑',
3210 ); 3312 );
3211 return; 3313 return;
3212 } 3314 }
@@ -3712,6 +3814,7 @@ const OrderPage = () =&gt; { @@ -3712,6 +3814,7 @@ const OrderPage = () =&gt; {
3712 'subNotes', 3814 'subNotes',
3713 'orderStatus', 3815 'orderStatus',
3714 'createTime', 3816 'createTime',
  3817 + 'modifiedAuditStatus',
3715 ]; 3818 ];
3716 if (isSupplier() && !canSearchIndex.includes(item.dataIndex)) { 3819 if (isSupplier() && !canSearchIndex.includes(item.dataIndex)) {
3717 item.search = false; 3820 item.search = false;
@@ -3893,6 +3996,8 @@ const OrderPage = () =&gt; { @@ -3893,6 +3996,8 @@ const OrderPage = () =&gt; {
3893 3996
3894 toolBtns.push(radioGroup); 3997 toolBtns.push(radioGroup);
3895 3998
  3999 + toolBtns.push(<ImportExpressBillModal></ImportExpressBillModal>);
  4000 +
3896 //导出按钮配置 4001 //导出按钮配置
3897 const exportItems: MenuProps['items'] = [ 4002 const exportItems: MenuProps['items'] = [
3898 { 4003 {
@@ -3901,20 +4006,32 @@ const OrderPage = () =&gt; { @@ -3901,20 +4006,32 @@ const OrderPage = () =&gt; {
3901 onClick: async () => { 4006 onClick: async () => {
3902 let body = { flag: 50, ...searchParams }; 4007 let body = { flag: 50, ...searchParams };
3903 exportLoading(); 4008 exportLoading();
3904 - orderExport('/api/service/order/export', body, exportLoadingDestory); 4009 + orderExport(
  4010 + '/api/service/order/export',
  4011 + '订单导出结果.xls',
  4012 + 'POST',
  4013 + body,
  4014 + exportLoadingDestory,
  4015 + );
3905 }, 4016 },
3906 }, 4017 },
3907 { 4018 {
3908 label: '导出已选中订单', 4019 label: '导出已选中订单',
3909 key: '1', 4020 key: '1',
3910 onClick: async () => { 4021 onClick: async () => {
3911 - if (selectedMainOrderKeys.length === 0) { 4022 + if (mainOrderSelectedMap.size === 0) {
3912 message.error('请选择订单'); 4023 message.error('请选择订单');
3913 return; 4024 return;
3914 } 4025 }
3915 - let body = { flag: 30, id: selectedMainOrderKeys }; 4026 + let body = { flag: 30, id: Array.from(mainOrderSelectedMap.keys()) };
3916 exportLoading(); 4027 exportLoading();
3917 - orderExport('/api/service/order/export', body, exportLoadingDestory); 4028 + orderExport(
  4029 + '/api/service/order/export',
  4030 + '订单导出结果.xls',
  4031 + 'POST',
  4032 + body,
  4033 + exportLoadingDestory,
  4034 + );
3918 }, 4035 },
3919 }, 4036 },
3920 { 4037 {
@@ -3923,7 +4040,13 @@ const OrderPage = () =&gt; { @@ -3923,7 +4040,13 @@ const OrderPage = () =&gt; {
3923 onClick: async () => { 4040 onClick: async () => {
3924 let body = { flag: 40, ids: [] }; 4041 let body = { flag: 40, ids: [] };
3925 exportLoading(); 4042 exportLoading();
3926 - orderExport('/api/service/order/export', body, exportLoadingDestory); 4043 + orderExport(
  4044 + '/api/service/order/export',
  4045 + '订单导出结果.xls',
  4046 + 'POST',
  4047 + body,
  4048 + exportLoadingDestory,
  4049 + );
3927 }, 4050 },
3928 }, 4051 },
3929 { 4052 {
@@ -3932,7 +4055,13 @@ const OrderPage = () =&gt; { @@ -3932,7 +4055,13 @@ const OrderPage = () =&gt; {
3932 onClick: async () => { 4055 onClick: async () => {
3933 let body = { flag: 10, ids: [] }; 4056 let body = { flag: 10, ids: [] };
3934 exportLoading(); 4057 exportLoading();
3935 - orderExport('/api/service/order/export', body, exportLoadingDestory); 4058 + orderExport(
  4059 + '/api/service/order/export',
  4060 + '订单导出结果.xls',
  4061 + 'POST',
  4062 + body,
  4063 + exportLoadingDestory,
  4064 + );
3936 }, 4065 },
3937 }, 4066 },
3938 ]; 4067 ];
src/pages/OrderPrint/index.css 0 → 100644
  1 +.font0 {
  2 + color: windowtext;
  3 + font-size: 12pt;
  4 + font-weight: 400;
  5 + font-style: normal;
  6 + text-decoration: none;
  7 + font-family: '宋体';
  8 +}
  9 +
  10 +.font1 {
  11 + color: windowtext;
  12 + font-size: 16pt;
  13 + font-weight: 400;
  14 + font-style: normal;
  15 + text-decoration: none;
  16 + font-family: '宋体';
  17 +}
  18 +
  19 +.font2 {
  20 + color: windowtext;
  21 + font-size: 10pt;
  22 + font-weight: 400;
  23 + font-style: normal;
  24 + text-decoration: none;
  25 + font-family: '宋体';
  26 +}
  27 +
  28 +.font3 {
  29 + color: windowtext;
  30 + font-size: 14pt;
  31 + font-weight: 400;
  32 + font-style: normal;
  33 + text-decoration: none;
  34 + font-family: '宋体';
  35 +}
  36 +
  37 +.font4 {
  38 + color: windowtext;
  39 + font-size: 8pt;
  40 + font-weight: 400;
  41 + font-style: normal;
  42 + text-decoration: none;
  43 + font-family: '宋体';
  44 +}
  45 +
  46 +.font5 {
  47 + color: #00f;
  48 + font-size: 11pt;
  49 + font-weight: 400;
  50 + font-style: normal;
  51 + text-decoration: underline;
  52 + font-family: '宋体';
  53 +}
  54 +
  55 +.font6 {
  56 + color: #800080;
  57 + font-size: 11pt;
  58 + font-weight: 400;
  59 + font-style: normal;
  60 + text-decoration: underline;
  61 + font-family: '宋体';
  62 +}
  63 +
  64 +.font7 {
  65 + color: #000;
  66 + font-size: 11pt;
  67 + font-weight: 400;
  68 + font-style: normal;
  69 + text-decoration: none;
  70 + font-family: '宋体';
  71 +}
  72 +
  73 +.font8 {
  74 + color: #f00;
  75 + font-size: 11pt;
  76 + font-weight: 400;
  77 + font-style: normal;
  78 + text-decoration: none;
  79 + font-family: '宋体';
  80 +}
  81 +
  82 +.font9 {
  83 + color: #44546a;
  84 + font-size: 18pt;
  85 + font-weight: 700;
  86 + font-style: normal;
  87 + text-decoration: none;
  88 + font-family: '宋体';
  89 +}
  90 +
  91 +.font10 {
  92 + color: #7f7f7f;
  93 + font-size: 11pt;
  94 + font-weight: 400;
  95 + font-style: italic;
  96 + text-decoration: none;
  97 + font-family: '宋体';
  98 +}
  99 +
  100 +.font11 {
  101 + color: #44546a;
  102 + font-size: 15pt;
  103 + font-weight: 700;
  104 + font-style: normal;
  105 + text-decoration: none;
  106 + font-family: '宋体';
  107 +}
  108 +
  109 +.font12 {
  110 + color: #44546a;
  111 + font-size: 13pt;
  112 + font-weight: 700;
  113 + font-style: normal;
  114 + text-decoration: none;
  115 + font-family: '宋体';
  116 +}
  117 +
  118 +.font13 {
  119 + color: #44546a;
  120 + font-size: 11pt;
  121 + font-weight: 700;
  122 + font-style: normal;
  123 + text-decoration: none;
  124 + font-family: '宋体';
  125 +}
  126 +
  127 +.font14 {
  128 + color: #3f3f76;
  129 + font-size: 11pt;
  130 + font-weight: 400;
  131 + font-style: normal;
  132 + text-decoration: none;
  133 + font-family: '宋体';
  134 +}
  135 +
  136 +.font15 {
  137 + color: #3f3f3f;
  138 + font-size: 11pt;
  139 + font-weight: 700;
  140 + font-style: normal;
  141 + text-decoration: none;
  142 + font-family: '宋体';
  143 +}
  144 +
  145 +.font16 {
  146 + color: #fa7d00;
  147 + font-size: 11pt;
  148 + font-weight: 700;
  149 + font-style: normal;
  150 + text-decoration: none;
  151 + font-family: '宋体';
  152 +}
  153 +
  154 +.font17 {
  155 + color: #fff;
  156 + font-size: 11pt;
  157 + font-weight: 700;
  158 + font-style: normal;
  159 + text-decoration: none;
  160 + font-family: '宋体';
  161 +}
  162 +
  163 +.font18 {
  164 + color: #fa7d00;
  165 + font-size: 11pt;
  166 + font-weight: 400;
  167 + font-style: normal;
  168 + text-decoration: none;
  169 + font-family: '宋体';
  170 +}
  171 +
  172 +.font19 {
  173 + color: #000;
  174 + font-size: 11pt;
  175 + font-weight: 700;
  176 + font-style: normal;
  177 + text-decoration: none;
  178 + font-family: '宋体';
  179 +}
  180 +
  181 +.font20 {
  182 + color: #006100;
  183 + font-size: 11pt;
  184 + font-weight: 400;
  185 + font-style: normal;
  186 + text-decoration: none;
  187 + font-family: '宋体';
  188 +}
  189 +
  190 +.font21 {
  191 + color: #9c0006;
  192 + font-size: 11pt;
  193 + font-weight: 400;
  194 + font-style: normal;
  195 + text-decoration: none;
  196 + font-family: '宋体';
  197 +}
  198 +
  199 +.font22 {
  200 + color: #9c6500;
  201 + font-size: 11pt;
  202 + font-weight: 400;
  203 + font-style: normal;
  204 + text-decoration: none;
  205 + font-family: '宋体';
  206 +}
  207 +
  208 +.font23 {
  209 + color: #fff;
  210 + font-size: 11pt;
  211 + font-weight: 400;
  212 + font-style: normal;
  213 + text-decoration: none;
  214 + font-family: '宋体';
  215 +}
  216 +
  217 +.font24 {
  218 + color: #000;
  219 + font-size: 11pt;
  220 + font-weight: 400;
  221 + font-style: normal;
  222 + text-decoration: none;
  223 + font-family: '宋体';
  224 +}
  225 +
  226 +.style0 {
  227 + text-align: general;
  228 + vertical-align: middle;
  229 + white-space: nowrap;
  230 + color: windowtext;
  231 + font-size: 12pt;
  232 + font-weight: 400;
  233 + font-style: normal;
  234 + text-decoration: none;
  235 + font-family: '宋体';
  236 + border: none;
  237 +}
  238 +
  239 +.style21 {
  240 + color: #00f;
  241 + font-size: 11pt;
  242 + font-weight: 400;
  243 + font-style: normal;
  244 + text-decoration: underline;
  245 + font-family: '宋体';
  246 +}
  247 +
  248 +.style22 {
  249 + color: #800080;
  250 + font-size: 11pt;
  251 + font-weight: 400;
  252 + font-style: normal;
  253 + text-decoration: underline;
  254 + font-family: '宋体';
  255 +}
  256 +
  257 +.style23 {
  258 + background: #ffc;
  259 + border: 0.5pt solid #b2b2b2;
  260 +}
  261 +
  262 +.style24 {
  263 + color: #f00;
  264 + font-size: 11pt;
  265 + font-weight: 400;
  266 + font-style: normal;
  267 + text-decoration: none;
  268 + font-family: '宋体';
  269 +}
  270 +
  271 +.style25 {
  272 + color: #44546a;
  273 + font-size: 18pt;
  274 + font-weight: 700;
  275 + font-style: normal;
  276 + text-decoration: none;
  277 + font-family: '宋体';
  278 +}
  279 +
  280 +.style26 {
  281 + color: #7f7f7f;
  282 + font-size: 11pt;
  283 + font-weight: 400;
  284 + font-style: italic;
  285 + text-decoration: none;
  286 + font-family: '宋体';
  287 +}
  288 +
  289 +.style27 {
  290 + color: #44546a;
  291 + font-size: 15pt;
  292 + font-weight: 700;
  293 + font-style: normal;
  294 + text-decoration: none;
  295 + font-family: '宋体';
  296 + border-bottom: 1pt solid #5b9bd5;
  297 +}
  298 +
  299 +.style28 {
  300 + color: #44546a;
  301 + font-size: 13pt;
  302 + font-weight: 700;
  303 + font-style: normal;
  304 + text-decoration: none;
  305 + font-family: '宋体';
  306 + border-bottom: 1pt solid #5b9bd5;
  307 +}
  308 +
  309 +.style29 {
  310 + color: #44546a;
  311 + font-size: 11pt;
  312 + font-weight: 700;
  313 + font-style: normal;
  314 + text-decoration: none;
  315 + font-family: '宋体';
  316 + border-bottom: 1pt solid #acccea;
  317 +}
  318 +
  319 +.style30 {
  320 + color: #44546a;
  321 + font-size: 11pt;
  322 + font-weight: 700;
  323 + font-style: normal;
  324 + text-decoration: none;
  325 + font-family: '宋体';
  326 +}
  327 +
  328 +.style31 {
  329 + background: #fc9;
  330 + color: #3f3f76;
  331 + font-size: 11pt;
  332 + font-weight: 400;
  333 + font-style: normal;
  334 + text-decoration: none;
  335 + font-family: '宋体';
  336 + border: 0.5pt solid #7f7f7f;
  337 +}
  338 +
  339 +.style32 {
  340 + background: #f2f2f2;
  341 + color: #3f3f3f;
  342 + font-size: 11pt;
  343 + font-weight: 700;
  344 + font-style: normal;
  345 + text-decoration: none;
  346 + font-family: '宋体';
  347 + border: 0.5pt solid #3f3f3f;
  348 +}
  349 +
  350 +.style33 {
  351 + background: #f2f2f2;
  352 + color: #fa7d00;
  353 + font-size: 11pt;
  354 + font-weight: 700;
  355 + font-style: normal;
  356 + text-decoration: none;
  357 + font-family: '宋体';
  358 + border: 0.5pt solid #7f7f7f;
  359 +}
  360 +
  361 +.style34 {
  362 + background: #a5a5a5;
  363 + color: #fff;
  364 + font-size: 11pt;
  365 + font-weight: 700;
  366 + font-style: normal;
  367 + text-decoration: none;
  368 + font-family: '宋体';
  369 + border: 2pt double #3f3f3f;
  370 +}
  371 +
  372 +.style35 {
  373 + color: #fa7d00;
  374 + font-size: 11pt;
  375 + font-weight: 400;
  376 + font-style: normal;
  377 + text-decoration: none;
  378 + font-family: '宋体';
  379 + border-bottom: 2pt double #ff8001;
  380 +}
  381 +
  382 +.style36 {
  383 + color: #000;
  384 + font-size: 11pt;
  385 + font-weight: 700;
  386 + font-style: normal;
  387 + text-decoration: none;
  388 + font-family: '宋体';
  389 + border-top: 0.5pt solid #5b9bd5;
  390 + border-bottom: 2pt double #5b9bd5;
  391 +}
  392 +
  393 +.style37 {
  394 + background: #c6efce;
  395 + color: #006100;
  396 + font-size: 11pt;
  397 + font-weight: 400;
  398 + font-style: normal;
  399 + text-decoration: none;
  400 + font-family: '宋体';
  401 +}
  402 +
  403 +.style38 {
  404 + background: #ffc7ce;
  405 + color: #9c0006;
  406 + font-size: 11pt;
  407 + font-weight: 400;
  408 + font-style: normal;
  409 + text-decoration: none;
  410 + font-family: '宋体';
  411 +}
  412 +
  413 +.style39 {
  414 + background: #ffeb9c;
  415 + color: #9c6500;
  416 + font-size: 11pt;
  417 + font-weight: 400;
  418 + font-style: normal;
  419 + text-decoration: none;
  420 + font-family: '宋体';
  421 +}
  422 +
  423 +.style40 {
  424 + background: #5b9bd5;
  425 + color: #fff;
  426 + font-size: 11pt;
  427 + font-weight: 400;
  428 + font-style: normal;
  429 + text-decoration: none;
  430 + font-family: '宋体';
  431 +}
  432 +
  433 +.style41 {
  434 + background: #ddebf7;
  435 + color: #000;
  436 + font-size: 11pt;
  437 + font-weight: 400;
  438 + font-style: normal;
  439 + text-decoration: none;
  440 + font-family: '宋体';
  441 +}
  442 +
  443 +.style42 {
  444 + background: #bdd7ee;
  445 + color: #000;
  446 + font-size: 11pt;
  447 + font-weight: 400;
  448 + font-style: normal;
  449 + text-decoration: none;
  450 + font-family: '宋体';
  451 +}
  452 +
  453 +.style43 {
  454 + background: #9bc2e6;
  455 + color: #fff;
  456 + font-size: 11pt;
  457 + font-weight: 400;
  458 + font-style: normal;
  459 + text-decoration: none;
  460 + font-family: '宋体';
  461 +}
  462 +
  463 +.style44 {
  464 + background: #ed7d31;
  465 + color: #fff;
  466 + font-size: 11pt;
  467 + font-weight: 400;
  468 + font-style: normal;
  469 + text-decoration: none;
  470 + font-family: '宋体';
  471 +}
  472 +
  473 +.style45 {
  474 + background: #fce4d6;
  475 + color: #000;
  476 + font-size: 11pt;
  477 + font-weight: 400;
  478 + font-style: normal;
  479 + text-decoration: none;
  480 + font-family: '宋体';
  481 +}
  482 +
  483 +.style46 {
  484 + background: #f8cbad;
  485 + color: #000;
  486 + font-size: 11pt;
  487 + font-weight: 400;
  488 + font-style: normal;
  489 + text-decoration: none;
  490 + font-family: '宋体';
  491 +}
  492 +
  493 +.style47 {
  494 + background: #f4b084;
  495 + color: #fff;
  496 + font-size: 11pt;
  497 + font-weight: 400;
  498 + font-style: normal;
  499 + text-decoration: none;
  500 + font-family: '宋体';
  501 +}
  502 +
  503 +.style48 {
  504 + background: #a5a5a5;
  505 + color: #fff;
  506 + font-size: 11pt;
  507 + font-weight: 400;
  508 + font-style: normal;
  509 + text-decoration: none;
  510 + font-family: '宋体';
  511 +}
  512 +
  513 +.style49 {
  514 + background: #ededed;
  515 + color: #000;
  516 + font-size: 11pt;
  517 + font-weight: 400;
  518 + font-style: normal;
  519 + text-decoration: none;
  520 + font-family: '宋体';
  521 +}
  522 +
  523 +.style50 {
  524 + background: #dbdbdb;
  525 + color: #000;
  526 + font-size: 11pt;
  527 + font-weight: 400;
  528 + font-style: normal;
  529 + text-decoration: none;
  530 + font-family: '宋体';
  531 +}
  532 +
  533 +.style51 {
  534 + background: #c9c9c9;
  535 + color: #fff;
  536 + font-size: 11pt;
  537 + font-weight: 400;
  538 + font-style: normal;
  539 + text-decoration: none;
  540 + font-family: '宋体';
  541 +}
  542 +
  543 +.style52 {
  544 + background: #ffc000;
  545 + color: #fff;
  546 + font-size: 11pt;
  547 + font-weight: 400;
  548 + font-style: normal;
  549 + text-decoration: none;
  550 + font-family: '宋体';
  551 +}
  552 +
  553 +.style53 {
  554 + background: #fff2cc;
  555 + color: #000;
  556 + font-size: 11pt;
  557 + font-weight: 400;
  558 + font-style: normal;
  559 + text-decoration: none;
  560 + font-family: '宋体';
  561 +}
  562 +
  563 +.style54 {
  564 + background: #ffe699;
  565 + color: #000;
  566 + font-size: 11pt;
  567 + font-weight: 400;
  568 + font-style: normal;
  569 + text-decoration: none;
  570 + font-family: '宋体';
  571 +}
  572 +
  573 +.style55 {
  574 + background: #ffd966;
  575 + color: #fff;
  576 + font-size: 11pt;
  577 + font-weight: 400;
  578 + font-style: normal;
  579 + text-decoration: none;
  580 + font-family: '宋体';
  581 +}
  582 +
  583 +.style56 {
  584 + background: #4472c4;
  585 + color: #fff;
  586 + font-size: 11pt;
  587 + font-weight: 400;
  588 + font-style: normal;
  589 + text-decoration: none;
  590 + font-family: '宋体';
  591 +}
  592 +
  593 +.style57 {
  594 + background: #d9e1f2;
  595 + color: #000;
  596 + font-size: 11pt;
  597 + font-weight: 400;
  598 + font-style: normal;
  599 + text-decoration: none;
  600 + font-family: '宋体';
  601 +}
  602 +
  603 +.style58 {
  604 + background: #b4c6e7;
  605 + color: #000;
  606 + font-size: 11pt;
  607 + font-weight: 400;
  608 + font-style: normal;
  609 + text-decoration: none;
  610 + font-family: '宋体';
  611 +}
  612 +
  613 +.style59 {
  614 + background: #8ea9db;
  615 + color: #fff;
  616 + font-size: 11pt;
  617 + font-weight: 400;
  618 + font-style: normal;
  619 + text-decoration: none;
  620 + font-family: '宋体';
  621 +}
  622 +
  623 +.style60 {
  624 + background: #70ad47;
  625 + color: #fff;
  626 + font-size: 11pt;
  627 + font-weight: 400;
  628 + font-style: normal;
  629 + text-decoration: none;
  630 + font-family: '宋体';
  631 +}
  632 +
  633 +.style61 {
  634 + background: #e2efda;
  635 + color: #000;
  636 + font-size: 11pt;
  637 + font-weight: 400;
  638 + font-style: normal;
  639 + text-decoration: none;
  640 + font-family: '宋体';
  641 +}
  642 +
  643 +.style62 {
  644 + background: #c6e0b4;
  645 + color: #000;
  646 + font-size: 11pt;
  647 + font-weight: 400;
  648 + font-style: normal;
  649 + text-decoration: none;
  650 + font-family: '宋体';
  651 +}
  652 +
  653 +.style63 {
  654 + background: #a9d08e;
  655 + color: #fff;
  656 + font-size: 11pt;
  657 + font-weight: 400;
  658 + font-style: normal;
  659 + text-decoration: none;
  660 + font-family: '宋体';
  661 +}
  662 +
  663 +td {
  664 + padding-top: 1px;
  665 + padding-right: 1px;
  666 + padding-left: 1px;
  667 + text-align: general;
  668 + vertical-align: middle;
  669 + white-space: nowrap;
  670 + color: windowtext;
  671 + font-size: 12pt;
  672 + font-weight: 400;
  673 + font-style: normal;
  674 + text-decoration: none;
  675 + font-family: '宋体';
  676 + border: none;
  677 +}
  678 +
  679 +.xl65 {
  680 + text-align: center;
  681 + font-size: 16pt;
  682 +}
  683 +
  684 +.xl66 {
  685 + text-align: center;
  686 + font-size: 10pt;
  687 +}
  688 +
  689 +.xl67 {
  690 + text-align: center;
  691 + font-size: 14pt;
  692 +}
  693 +
  694 +.xl68 {
  695 + text-align: center;
  696 + font-size: 14pt;
  697 +}
  698 +
  699 +.xl69 {
  700 + text-align: left;
  701 + font-size: 8pt;
  702 +}
  703 +
  704 +.xl70 {
  705 + text-align: left;
  706 + font-size: 8pt;
  707 +}
  708 +
  709 +.xl71 {
  710 + text-align: center;
  711 + font-size: 8pt;
  712 + border: 0.5pt solid windowtext;
  713 +}
  714 +
  715 +.xl72 {
  716 + text-align: center;
  717 + font-size: 8pt;
  718 + border: 0.5pt solid windowtext;
  719 + white-space: normal;
  720 +}
  721 +
  722 +.xl73 {
  723 + white-space: normal;
  724 + font-size: 8pt;
  725 + border: 0.5pt solid windowtext;
  726 +}
  727 +
  728 +.xl74 {
  729 + text-align: center;
  730 + white-space: normal;
  731 + font-size: 8pt;
  732 + border: 0.5pt solid windowtext;
  733 +}
  734 +
  735 +.xl75 {
  736 + text-align: center;
  737 + white-space: normal;
  738 + font-size: 8pt;
  739 + border: 0.5pt solid windowtext;
  740 +}
  741 +
  742 +.xl76 {
  743 + font-size: 8pt;
  744 +}
  745 +
  746 +.xl77 {
  747 + font-size: 8pt;
  748 +}
  749 +
  750 +.xl78 {
  751 + text-align: center;
  752 + font-size: 8pt;
  753 +}
src/pages/Prepaid/constant.tsx
@@ -226,6 +226,13 @@ export const BALANCE_CHANGE_COLUMNS = [ @@ -226,6 +226,13 @@ export const BALANCE_CHANGE_COLUMNS = [
226 width: 140, 226 width: 140,
227 }, 227 },
228 { 228 {
  229 + title: '变动人',
  230 + dataIndex: 'updateBy',
  231 + key: 'updateBy',
  232 + dataType: 'text',
  233 + width: 200,
  234 + },
  235 + {
229 title: '类型', 236 title: '类型',
230 dataIndex: 'title', 237 dataIndex: 'title',
231 key: 'title', 238 key: 'title',
src/pages/ResearchGroup/components/AuditModal.tsx 0 → 100644
  1 +import { RESPONSE_CODE } from '@/constants/enum';
  2 +import { postCommonAudit } from '@/services';
  3 +import { ModalForm, ProFormTextArea } from '@ant-design/pro-components';
  4 +import { Button, Form, message } from 'antd';
  5 +import { cloneDeep } from 'lodash';
  6 +
  7 +// import { cloneDeep } from 'lodash';
  8 +export default ({ setVisible, ids, onClose }) => {
  9 + const [form] = Form.useForm();
  10 + let auditIds = cloneDeep(ids);
  11 +
  12 + const parseValues = (values: any) => {
  13 + values.ids = auditIds;
  14 + values.notes = form.getFieldValue('auditNotes');
  15 + };
  16 +
  17 + const doAudit = async (values: any) => {
  18 + values.type = 'research_group_member_request_audit';
  19 + let res = await postCommonAudit({ data: values });
  20 + if (res && res.result === RESPONSE_CODE.SUCCESS) {
  21 + message.success(res.message);
  22 + onClose();
  23 + }
  24 + };
  25 +
  26 + const loadbtns = (props: any, defaultDoms: any) => {
  27 + let btns = [];
  28 + //取消
  29 + btns.push(defaultDoms[0]);
  30 +
  31 + //驳回
  32 + btns.push(
  33 + <Button
  34 + type="primary"
  35 + onClick={() => {
  36 + let values = form.getFieldsValue();
  37 + values.pass = false;
  38 + parseValues(values);
  39 + doAudit(values);
  40 + }}
  41 + >
  42 + 驳回
  43 + </Button>,
  44 + );
  45 +
  46 + //确认
  47 + btns.push(defaultDoms[1]);
  48 +
  49 + return btns;
  50 + };
  51 +
  52 + return (
  53 + <>
  54 + <ModalForm
  55 + width={500}
  56 + open
  57 + title="审核"
  58 + form={form}
  59 + autoFocusFirstInput
  60 + modalProps={{
  61 + okText: '通过',
  62 + cancelText: '取消',
  63 + destroyOnClose: true,
  64 + onCancel: () => {
  65 + setVisible(false);
  66 + },
  67 + }}
  68 + onFinish={async (values) => {
  69 + values.pass = true;
  70 + parseValues(values);
  71 + doAudit(values);
  72 + onClose();
  73 + }}
  74 + onOpenChange={setVisible}
  75 + submitter={{
  76 + render: (props, defaultDoms) => {
  77 + return loadbtns(props, defaultDoms);
  78 + },
  79 + }}
  80 + >
  81 + <ProFormTextArea
  82 + name="auditNotes"
  83 + key="auditNotes"
  84 + placeholder="备注"
  85 + label="若驳回,请填写备注"
  86 + />
  87 + </ModalForm>
  88 + </>
  89 + );
  90 +};