Commit 1a5687dee0e22e582ce050b0b1c8889ddbef5c05

Authored by zhongnanhuang
2 parents 3d302513 d5cb3ed2

Merge branch 'refs/heads/develop'

# Conflicts:
#	.umirc.ts
#	src/access.ts
#	src/services/definition.ts
#	src/services/request.ts
.umirc.ts
@@ -73,6 +73,13 @@ export default defineConfig({ @@ -73,6 +73,13 @@ export default defineConfig({
73 access: 'canReadAdminAndSales', 73 access: 'canReadAdminAndSales',
74 }, 74 },
75 { 75 {
  76 + name: '分期账单',
  77 + path: '/instalment',
  78 + component: './Instalment',
  79 + icon: 'BookOutlined',
  80 + access: 'canReadLinda',
  81 + },
  82 + {
76 name: '打印', 83 name: '打印',
77 path: '/print', 84 path: '/print',
78 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';
8 const canReadSales = 8 const canReadSales =
9 roleSmallVO?.code === 'salesManager' || 9 roleSmallVO?.code === 'salesManager' ||
10 roleSmallVO?.code === 'salesRepresentative'; 10 roleSmallVO?.code === 'salesRepresentative';
  11 +
11 return { 12 return {
12 canReadAdmin: canReadAdmin, 13 canReadAdmin: canReadAdmin,
13 canReadProcure: canReadProcure, 14 canReadProcure: canReadProcure,
  15 + canReadLinda: username === 'Linda' || '吴量',
14 canReadAdminAndFinance: canReadFinance || canReadAdmin, 16 canReadAdminAndFinance: canReadFinance || canReadAdmin,
15 canReadSales: canReadSales, 17 canReadSales: canReadSales,
16 canReadAdminAndFinanceAndSales: 18 canReadAdminAndFinanceAndSales:
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 + setContextBody({
  155 + id: undefined,
  156 + contract: undefined,
  157 + dateRange: undefined,
  158 + terminal: undefined,
  159 + orderStagesDeviceVoList: [],
  160 + totalPrice: undefined,
  161 + payWay: '30/30/30/10',
  162 + annex: undefined,
  163 + remark: undefined,
  164 + });
  165 + handleInputChange('30/30/30/10', 0, 0);
  166 + }
  167 +
  168 + return (
  169 + <ModalForm<OrderStagesWithListItem>
  170 + title="新建"
  171 + trigger={
  172 + <Button
  173 + key="button"
  174 + icon={<PlusOutlined />}
  175 + type="primary"
  176 + onClick={() => refresh()}
  177 + >
  178 + 新增
  179 + </Button>
  180 + }
  181 + form={form}
  182 + autoFocusFirstInput
  183 + modalProps={{
  184 + destroyOnClose: true,
  185 + }}
  186 + submitTimeout={2000}
  187 + onFinish={async (values) => {
  188 + if (editProductBody.length === 0) {
  189 + message.error('请填写产品数据');
  190 + return false;
  191 + }
  192 + let remakeValue = [];
  193 +
  194 + const formData = new FormData();
  195 + let toSendEdit = {
  196 + id: values.id || contextBody.id,
  197 + contract: values.contract || contextBody.contract,
  198 + vendor: values.vendor || contextBody.vendor,
  199 + dateRange: values.dateRange || contextBody.dateRange,
  200 + terminal: values.terminal || contextBody.terminal,
  201 + orderStagesDeviceDoList:
  202 + values.orderStagesDeviceVoList ||
  203 + contextBody.orderStagesDeviceVoList,
  204 + totalPrice: values.totalPrice || contextBody.totalPrice,
  205 + payWay: values.payWay || contextBody.payWay,
  206 + annex: contextBody.annex,
  207 + remark: values.remark || contextBody.remark,
  208 + };
  209 + if (values.annex) {
  210 + formData.append('file', values.annex[0].originFileObj as RcFile);
  211 + const res = await postOrderErpOrderStagesUpload({
  212 + data: formData,
  213 + headers: {
  214 + 'Content-Type':
  215 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  216 + },
  217 + });
  218 + if (res.data) {
  219 + toSendEdit.annex = res.data;
  220 + }
  221 + }
  222 + const isSaveOrUpdate = await postOrderErpOrderStagesAdd({
  223 + data: { ...toSendEdit },
  224 + });
  225 +
  226 + if (isSaveOrUpdate) {
  227 + const promises = [];
  228 +
  229 + otherBody.forEach((item) => {
  230 + let remakeItem = {
  231 + ossId: item.ossId,
  232 + number: item.id,
  233 + dataRange: item.payDate,
  234 + fileName: item.fileName,
  235 + };
  236 + if (
  237 + typeof item.fileUrl === 'object' &&
  238 + item.fileUrl instanceof File
  239 + ) {
  240 + const formData = new FormData();
  241 + formData.append('file', item.fileUrl as RcFile);
  242 + const uploadPromise = async () => {
  243 + const res = await postOrderErpOrderStagesUpload({
  244 + data: formData,
  245 + headers: {
  246 + 'Content-Type':
  247 + 'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
  248 + },
  249 + });
  250 + if (res.data) {
  251 + remakeItem.fileUrl = res.data;
  252 + }
  253 + };
  254 + promises.push(uploadPromise());
  255 + }
  256 + remakeValue.push(remakeItem);
  257 + });
  258 +
  259 + let makeEnd = [];
  260 + const getRetrunIDPromise = async () => {
  261 + let returnOssID = await postOrderErpOrderStagesSearch({
  262 + data: { contract: values.contract || contextBody.contract },
  263 + });
  264 + console.log(returnOssID.data);
  265 +
  266 + if (returnOssID) {
  267 + makeEnd = remakeValue.map((item) => {
  268 + return { ...item, ossId: returnOssID.data[0].id };
  269 + });
  270 + }
  271 + };
  272 +
  273 + promises.push(getRetrunIDPromise());
  274 + Promise.all(promises).then(async () => {
  275 + await postOrderErpOrderStagesPayWaySaveOrUpdate({
  276 + data: makeEnd,
  277 + });
  278 + });
  279 + toReload();
  280 + }
  281 + await waitTime(2000);
  282 + message.success('提交成功');
  283 + return true;
  284 + }}
  285 + >
  286 + <ProCard title="基本信息" headerBordered bordered>
  287 + <ProForm.Group>
  288 + <ProFormText
  289 + width="md"
  290 + name="vendor"
  291 + rules={[{ required: true, message: '此项为必填项' }]}
  292 + label="供应商名称"
  293 + placeholder="请输入"
  294 + initialValue={contextBody.vendor}
  295 + />
  296 +
  297 + <ProFormText
  298 + width="md"
  299 + name="terminal"
  300 + rules={[{ required: true, message: '此项为必填项' }]}
  301 + label="终端名称"
  302 + placeholder="请输入"
  303 + initialValue={contextBody.terminal}
  304 + />
  305 +
  306 + <ProFormDatePicker
  307 + name="dateRange"
  308 + width="md"
  309 + label="签合同日期"
  310 + placeholder="请选择日期"
  311 + fieldProps={{
  312 + format: (value) => value.format('YYYY-MM-DD'),
  313 + }}
  314 + initialValue={contextBody.dateRange}
  315 + />
  316 +
  317 + <ProFormText
  318 + width="md"
  319 + name="payWay"
  320 + rules={[{ required: true, message: '此项为必填项' }]}
  321 + label="付款比例"
  322 + placeholder="请输入"
  323 + initialValue={contextBody.payWay}
  324 + disabled={!isDis}
  325 + onBlur={(e) => {
  326 + setContextBody({ ...contextBody, payWay: e.target.value });
  327 + handleInputChange(e.target.value, 1);
  328 + }}
  329 + />
  330 +
  331 + <ProFormText
  332 + width="md"
  333 + name="contract"
  334 + rules={[{ required: true, message: '此项为必填项' }]}
  335 + label="合同编号"
  336 + placeholder="请输入"
  337 + initialValue={contextBody.contract}
  338 + />
  339 +
  340 + <ProFormUploadButton
  341 + width="md"
  342 + name="annex"
  343 + max={1}
  344 + label="合同附件"
  345 + />
  346 +
  347 + <ProFormText
  348 + width="md"
  349 + name="totalPrice"
  350 + label="合同金额"
  351 + placeholder="请输入"
  352 + disabled={isDis}
  353 + initialValue={'0'}
  354 + />
  355 + </ProForm.Group>
  356 + </ProCard>
  357 + <ProCard
  358 + title={
  359 + <>
  360 + <span style={{ color: 'red' }}>*</span>产品明细
  361 + </>
  362 + }
  363 + style={{ marginTop: 10 }}
  364 + headerBordered
  365 + bordered
  366 + >
  367 + <ProductDetail
  368 + productBody={[]}
  369 + EditProductBody={getEditProductBody}
  370 + ></ProductDetail>
  371 + </ProCard>
  372 +
  373 + <ProCard
  374 + title="付款信息"
  375 + style={{ marginTop: 10 }}
  376 + headerBordered
  377 + bordered
  378 + >
  379 + <PayWayDetail
  380 + payBody={payWayBody}
  381 + thisId={null}
  382 + currtSave={setSave}
  383 + ></PayWayDetail>
  384 + </ProCard>
  385 +
  386 + <ProCard style={{ marginTop: 10 }} headerBordered bordered>
  387 + <ProFormTextArea
  388 + label="备注"
  389 + name="remark"
  390 + initialValue={contextBody.remark}
  391 + />
  392 + </ProCard>
  393 + </ModalForm>
  394 + );
  395 +};
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/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/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/services/order.ts
@@ -2,12 +2,14 @@ import axios from &#39;axios&#39;; @@ -2,12 +2,14 @@ import axios from &#39;axios&#39;;
2 2
3 export const orderExport = async ( 3 export const orderExport = async (
4 url: any = '', 4 url: any = '',
  5 + fileName: any = '',
  6 + method: any = '',
5 data: any = {}, 7 data: any = {},
6 exportLoadingDestory: any, 8 exportLoadingDestory: any,
7 ) => { 9 ) => {
8 axios({ 10 axios({
9 url: url, 11 url: url,
10 - method: 'post', 12 + method: method,
11 responseType: 'blob', 13 responseType: 'blob',
12 headers: { Authorization: localStorage.getItem('token') }, 14 headers: { Authorization: localStorage.getItem('token') },
13 data, 15 data,
@@ -18,7 +20,7 @@ export const orderExport = async ( @@ -18,7 +20,7 @@ export const orderExport = async (
18 const downloadUrl = window.URL.createObjectURL(blob); 20 const downloadUrl = window.URL.createObjectURL(blob);
19 const a = document.createElement('a'); 21 const a = document.createElement('a');
20 a.href = downloadUrl; 22 a.href = downloadUrl;
21 - a.download = '订单.xlsx'; // 你可以为文件命名 23 + a.download = fileName; // 你可以为文件命名
22 document.body.appendChild(a); 24 document.body.appendChild(a);
23 a.click(); // 模拟点击操作来下载文件 25 a.click(); // 模拟点击操作来下载文件
24 URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存 26 URL.revokeObjectURL(downloadUrl); // 释放掉 blob 对象所占用的内存