1
0
فهرست منبع

fix(compiler): 新增报备管理页面,对接口,封装上传图片组件

shylock 1 سال پیش
والد
کامیت
092d820d01

+ 7 - 0
config/routes.ts

@@ -78,6 +78,13 @@
     icon: 'Appstore',
     component: './RoleManagement',
   },
+  // 报备管理
+  {
+    path: '/ReportingManagement',
+    name: '报备管理',
+    icon: 'Appstore',
+    component: './ReportingManagement',
+  },
   {
     path: '/ParameterConfiguration',
     name: '参数配置',

+ 67 - 0
src/components/UploadCommon/index.tsx

@@ -0,0 +1,67 @@
+import { Upload, Modal } from 'antd';
+import { PlusOutlined } from '@ant-design/icons';
+import React, { useState } from 'react';
+import type { RcFile, UploadProps } from 'antd/es/upload';
+import type { UploadFile } from 'antd/es/upload/interface';
+
+interface uploadProps {
+  onChange: (value: any) => void;
+  value: any;
+}
+
+const getBase64 = (file: RcFile): Promise<string> =>
+  new Promise((resolve, reject) => {
+    const reader = new FileReader();
+    reader.readAsDataURL(file);
+    reader.onload = () => resolve(reader.result as string);
+    reader.onerror = (error) => reject(error);
+  });
+
+/**
+ * 上传图片组件
+ * @param props
+ * @constructor
+ */
+const UploadCommon: React.FC<uploadProps> = (props) => {
+  const { value, onChange } = props;
+  const [fileList, setFileList] = useState(value || []);
+  const [previewOpen, setPreviewOpen] = useState(false);
+  const [previewImage, setPreviewImage] = useState('');
+  const [previewTitle, setPreviewTitle] = useState('');
+
+  // 查看弹框关闭
+  const handleCancel = () => setPreviewOpen(false);
+
+  // 查看
+  const handlePreview = async (file: UploadFile) => {
+    if (!file.url && !file.preview) {
+      file.preview = await getBase64(file.originFileObj as RcFile);
+    }
+    setPreviewImage(file.url || (file.preview as string));
+    setPreviewOpen(true);
+    setPreviewTitle(file.name || file.url!.substring(file.url!.lastIndexOf('/') + 1));
+  };
+
+  const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
+    setFileList(newFileList);
+    onChange(newFileList);
+  };
+
+  return (
+    <div>
+      <Upload
+        action="/web/v1/files"
+        listType="picture-card"
+        fileList={fileList}
+        onPreview={handlePreview}
+        onChange={handleChange}
+      >
+        {<PlusOutlined />}
+      </Upload>
+      <Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handleCancel}>
+        <img alt="图片" style={{ width: '100%' }} src={previewImage} />
+      </Modal>
+    </div>
+  );
+};
+export default UploadCommon;

+ 126 - 0
src/pages/ReportingManagement/check.tsx

@@ -0,0 +1,126 @@
+import { Descriptions, Modal } from 'antd';
+import React from 'react';
+import moment from 'moment';
+
+interface checkProps {
+  visible: boolean;
+  data: any;
+  checkCallback: () => void;
+}
+
+/**
+ * 报备查看弹框
+ * @param props
+ * @constructor
+ */
+const Check: React.FC<checkProps> = (props) => {
+  const { visible, data, checkCallback } = props;
+
+  const onOk = () => {
+    checkCallback();
+  };
+
+  const onCancel = () => {
+    checkCallback();
+  };
+
+  // 城市拼接
+  const handleCity = () => {
+    return `${data.province} ${data.city} ${data.district}`;
+  };
+
+  const handleImg = () => {
+    if (data?.files && data?.files.length) {
+      return data?.files.map((res: any) => (
+        <img
+          style={{ width: '100px', height: '100px', margin: '5px 10px' }}
+          src={res.url}
+          key={res.record_id}
+          alt="图片"
+        />
+      ));
+    } else {
+      return '暂无图片';
+    }
+  };
+
+  return (
+    <Modal title="查看" open={visible} onOk={onOk} onCancel={onCancel} width={1000}>
+      <Descriptions bordered>
+        <Descriptions.Item label="工程名称">{data?.project_name}</Descriptions.Item>
+        <Descriptions.Item label="城市">{handleCity()}</Descriptions.Item>
+        <Descriptions.Item label="街道">{data?.street}</Descriptions.Item>
+        <Descriptions.Item label="路">{data?.rode}</Descriptions.Item>
+        <Descriptions.Item label="小区">{data?.residence}</Descriptions.Item>
+        <Descriptions.Item label="门牌">{data?.doorplate}</Descriptions.Item>
+        <Descriptions.Item label="详细地址" span={2}>
+          {data?.address}
+        </Descriptions.Item>
+        <Descriptions.Item label="建筑面积">{data?.area}</Descriptions.Item>
+        <Descriptions.Item label="招标形式">
+          {{ 1: '内部仪标', 2: '公开招标', 3: '提供方案书' }[data?.bidding_form]}
+        </Descriptions.Item>
+        <Descriptions.Item label="项目用途">
+          {
+            {
+              1: '酒店餐饮',
+              2: '商务办公',
+              3: '政府项目',
+              4: '工矿企业',
+              5: '文教卫生',
+              6: '商业建筑',
+              7: '房产配套',
+              8: '其他',
+            }[data?.project_effect]
+          }
+        </Descriptions.Item>
+        <Descriptions.Item label="工程进展">
+          {
+            {
+              1: '了解信息',
+              2: '确认经销商',
+              3: '方案报价',
+              4: '邀请招标',
+              5: '投标询价',
+              6: '价格竞争',
+              7: '商务谈判',
+              8: '合同准备',
+              9: '收到定金',
+            }[data?.project_progress]
+          }
+        </Descriptions.Item>
+        <Descriptions.Item label="空调类型">
+          {
+            {
+              1: '组合式方案',
+              2: '供暖机组',
+              3: '雅居多联机',
+              4: '多联机系列',
+              5: '螺杆机系列',
+              6: '热水机系列',
+              7: '离心机系列',
+              8: '地源热泵',
+              9: '模块机系列',
+            }[data?.air_conditioner_type]
+          }
+        </Descriptions.Item>
+        <Descriptions.Item label="甲方联系人">{data?.contact_person}</Descriptions.Item>
+        <Descriptions.Item label="联系方式">{data?.phone}</Descriptions.Item>
+        <Descriptions.Item label="计划成交日期">
+          {data?.planned_fixture_date
+            ? moment(data?.planned_fixture_date).format('YYYY-MM-DD')
+            : ''}
+        </Descriptions.Item>
+        <Descriptions.Item label="跟进人">{data?.follow_people}</Descriptions.Item>
+        <Descriptions.Item label="成功几率">{data?.success_probability}</Descriptions.Item>
+        <Descriptions.Item label="成功几率分析" span={3}>
+          {data?.success_probability_analysis}
+        </Descriptions.Item>
+        <Descriptions.Item label="图片" span={3}>
+          {handleImg()}
+        </Descriptions.Item>
+      </Descriptions>
+    </Modal>
+  );
+};
+export default Check;

+ 521 - 0
src/pages/ReportingManagement/edit.tsx

@@ -0,0 +1,521 @@
+import React, { useEffect, useState } from 'react';
+import {
+  Cascader,
+  Col,
+  DatePicker,
+  Form,
+  Input,
+  InputNumber,
+  Modal,
+  Row,
+  Select,
+  message,
+} from 'antd';
+import { cityQuery, createReporting, editReporting } from '@/services/ReportingManagement';
+import moment from 'moment';
+import UploadCommon from '@/components/UploadCommon';
+
+interface userEditPros {
+  visible: boolean;
+  editCallback: () => void;
+  detailData: any;
+}
+
+const { TextArea } = Input;
+
+/**
+ * 报备编辑页面
+ * @param props
+ * @constructor
+ */
+const Edit: React.FC<userEditPros> = (props) => {
+  const { visible, editCallback, detailData } = props;
+  const [form] = Form.useForm();
+  const [cityList, setCityList] = useState([]);
+  const [filesList, setFilesList] = useState([]);
+
+  // 获取城市列表
+  const getCityList = () => {
+    cityQuery({ q: 'tree' }).then((res) => {
+      if (res?.code === 0) {
+        const arr = res?.data?.list;
+        setCityList(arr);
+      }
+    });
+  };
+
+  useEffect(() => {
+    getCityList();
+  }, []);
+
+  const onOk = () => {
+    form.validateFields().then((values) => {
+      if (values) {
+        const data = { ...values };
+        if (values.success_probability) {
+          data.success_probability = values.success_probability.toString();
+        }
+        if (values.success_probability_analysis) {
+          data.success_probability_analysis = values.success_probability_analysis;
+        }
+        if (values.planned_fixture_date) {
+          data.planned_fixture_date = moment(values.planned_fixture_date).format('YYYY-MM-DD');
+        }
+        if (values.files && values.files.length) {
+          data.files = filesList;
+        }
+        if (detailData) {
+          data.record_id = detailData.record_id;
+          const cityInfo = values.city
+            .split('')
+            .filter((x: { charCodeAt: () => number }) => x.charCodeAt() != 32)
+            .join('')
+            .split('/');
+          data.province = cityInfo[0];
+          data.city = cityInfo[1];
+          data.district = cityInfo[2];
+          editReporting(data)
+            .then((res) => {
+              if (res && res.code === 0) {
+                message.success('编辑成功');
+                editCallback();
+              } else {
+                message.error('编辑失败');
+              }
+            })
+            .catch((e) => {
+              message.error(e?.message);
+            });
+        } else {
+          data.province = values.city[0];
+          data.city = values.city[1];
+          data.district = values.city[2];
+          createReporting(data)
+            .then((res) => {
+              if (res && res.code === 0) {
+                message.success('新增成功');
+                editCallback();
+              } else {
+                message.error('新增失败');
+              }
+            })
+            .catch((e) => {
+              message.error(e?.message);
+            });
+        }
+      }
+    });
+  };
+
+  // 上传图片回调
+  const onUploadChange = (files: any) => {
+    if (files && files.length) {
+      const arr: any = [];
+      files.forEach((el: any) => {
+        arr.push({ url: el?.response?.data?.url || '' });
+      });
+      setFilesList(arr);
+    }
+  };
+
+  const onCancel = () => {
+    editCallback();
+  };
+
+  const formItemLayout = {
+    labelCol: {
+      span: 7,
+    },
+    wrapperCol: {
+      span: 15,
+    },
+  };
+
+  const formItemLayoutTwo = {
+    labelCol: {
+      span: 4,
+    },
+    wrapperCol: {
+      span: 19,
+    },
+  };
+
+  return (
+    <Modal
+      title={`${detailData ? '编辑' : '新增'}`}
+      open={visible}
+      onOk={onOk}
+      onCancel={onCancel}
+      width={800}
+    >
+      <Form form={form}>
+        <Row>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="project_name"
+              label="工程名称"
+              rules={[{ required: true, message: '请输入工程名称' }]}
+              initialValue={detailData?.project_name || ''}
+            >
+              <Input placeholder="请输入工程名称" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="city"
+              label="城市"
+              rules={[{ required: true, message: '请选择城市' }]}
+              initialValue={
+                detailData && JSON.stringify(detailData) !== '{}'
+                  ? `${detailData?.province}` +
+                    ' / ' +
+                    `${detailData?.city}` +
+                    ' / ' +
+                    `${detailData?.district}`
+                  : ''
+              }
+            >
+              <Cascader
+                options={cityList}
+                fieldNames={{ label: 'name', value: 'name', children: 'children' }}
+                placeholder="请选择城市"
+              />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="street"
+              label="街道"
+              rules={[{ required: true, message: '请输入街道' }]}
+              initialValue={detailData?.street || ''}
+            >
+              <Input placeholder="请输入街道" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="rode"
+              label="路"
+              rules={[{ required: true, message: '请输入路' }]}
+              initialValue={detailData?.rode || ''}
+            >
+              <Input placeholder="请输入路" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="residence"
+              label="小区"
+              rules={[{ required: true, message: '请输入小区' }]}
+              initialValue={detailData?.residence || ''}
+            >
+              <Input placeholder="请输入小区" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="doorplate"
+              label="门牌"
+              rules={[{ required: true, message: '请输入门牌' }]}
+              initialValue={detailData?.doorplate || ''}
+            >
+              <Input placeholder="请输入门牌" />
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item
+              {...formItemLayoutTwo}
+              name="address"
+              label="详细地址"
+              rules={[{ required: true, message: '请输入详细地址' }]}
+              initialValue={detailData?.address || ''}
+            >
+              <TextArea rows={4} placeholder="请输入详细地址" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="area"
+              label="建筑面积"
+              rules={[{ required: true, message: '请输入建筑面积' }]}
+              initialValue={detailData?.area || ''}
+            >
+              <Input placeholder="请输入建筑面积" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="bidding_form"
+              label="招标形式"
+              rules={[{ required: true, message: '请选择招标形式' }]}
+              initialValue={detailData?.bidding_form || undefined}
+            >
+              <Select
+                placeholder="请选择招标形式"
+                options={[
+                  {
+                    value: '1',
+                    label: '内部仪标',
+                  },
+                  {
+                    value: '2',
+                    label: '公开招标',
+                  },
+                  {
+                    value: '3',
+                    label: '提供方案书',
+                  },
+                ]}
+              />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="project_effect"
+              label="项目用途"
+              rules={[{ required: true, message: '请选择项目用途' }]}
+              initialValue={detailData?.project_effect || undefined}
+            >
+              <Select
+                placeholder="请选择项目用途"
+                options={[
+                  {
+                    value: '1',
+                    label: '酒店餐饮',
+                  },
+                  {
+                    value: '2',
+                    label: '商务办公',
+                  },
+                  {
+                    value: '3',
+                    label: '政府项目',
+                  },
+                  {
+                    value: '4',
+                    label: '工矿企业',
+                  },
+                  {
+                    value: '5',
+                    label: '文教卫生',
+                  },
+                  {
+                    value: '6',
+                    label: '商业建筑',
+                  },
+                  {
+                    value: '7',
+                    label: '房产配套',
+                  },
+                  {
+                    value: '8',
+                    label: '其他',
+                  },
+                ]}
+              />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="project_progress"
+              label="工程进展"
+              rules={[{ required: true, message: '请选择工程进展' }]}
+              initialValue={detailData?.project_progress || undefined}
+            >
+              <Select
+                placeholder="请选择工程进展"
+                options={[
+                  {
+                    value: '1',
+                    label: '了解信息',
+                  },
+                  {
+                    value: '2',
+                    label: '确认经销商',
+                  },
+                  {
+                    value: '3',
+                    label: '方案报价',
+                  },
+                  {
+                    value: '4',
+                    label: '邀请招标',
+                  },
+                  {
+                    value: '5',
+                    label: '投标询价',
+                  },
+                  {
+                    value: '6',
+                    label: '价格竞争',
+                  },
+                  {
+                    value: '7',
+                    label: '商务谈判',
+                  },
+                  {
+                    value: '8',
+                    label: '合同准备',
+                  },
+                  {
+                    value: '9',
+                    label: '收到定金',
+                  },
+                ]}
+              />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="air_conditioner_type"
+              label="空调类型"
+              rules={[{ required: true, message: '请选择空调类型' }]}
+              initialValue={detailData?.air_conditioner_type || undefined}
+            >
+              <Select
+                placeholder="请选择空调类型"
+                options={[
+                  {
+                    value: '1',
+                    label: '组合式方案',
+                  },
+                  {
+                    value: '2',
+                    label: '供暖机组',
+                  },
+                  {
+                    value: '3',
+                    label: '雅居多联机',
+                  },
+                  {
+                    value: '4',
+                    label: '多联机系列',
+                  },
+                  {
+                    value: '5',
+                    label: '螺杆机系列',
+                  },
+                  {
+                    value: '6',
+                    label: '热水机系列',
+                  },
+                  {
+                    value: '7',
+                    label: '离心机系列',
+                  },
+                  {
+                    value: '8',
+                    label: '地源热泵',
+                  },
+                  {
+                    value: '9',
+                    label: '模块机系列',
+                  },
+                ]}
+              />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="contact_person"
+              label="甲方联系人"
+              rules={[{ required: true, message: '请输入甲方联系人' }]}
+              initialValue={detailData?.contact_person || ''}
+            >
+              <Input placeholder="请输入甲方联系人" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="phone"
+              label="联系方式"
+              rules={[{ required: true, message: '请输入联系方式' }]}
+              initialValue={detailData?.phone || ''}
+            >
+              <Input placeholder="请输入联系方式" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="planned_fixture_date"
+              label="计划成交日期"
+              rules={[{ required: true, message: '请输入计划成交日期' }]}
+              initialValue={
+                detailData?.planned_fixture_date ? moment(detailData?.planned_fixture_date) : ''
+              }
+            >
+              <DatePicker style={{ width: '235px' }} />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="follow_people"
+              label="跟进人"
+              rules={[{ required: true, message: '请输入跟进人' }]}
+              initialValue={detailData?.follow_people || ''}
+            >
+              <Input placeholder="请输入跟进人" />
+            </Form.Item>
+          </Col>
+          <Col span={12}>
+            <Form.Item
+              {...formItemLayout}
+              name="success_probability"
+              label="成功几率"
+              rules={[{ required: true, message: '请输入成功几率' }]}
+              initialValue={detailData?.success_probability || ''}
+            >
+              <InputNumber
+                min={0}
+                max={100}
+                placeholder="请输入成功几率"
+                addonAfter="%"
+                style={{ width: '235px' }}
+              />
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item
+              {...formItemLayoutTwo}
+              name="success_probability_analysis"
+              label="成功几率分析"
+              rules={[{ required: false, message: '请输入成功几率分析' }]}
+              initialValue={detailData?.success_probability_analysis || ''}
+            >
+              <TextArea rows={4} placeholder="请输入成功几率分析" />
+            </Form.Item>
+          </Col>
+          <Col span={24}>
+            <Form.Item
+              {...formItemLayoutTwo}
+              name="files"
+              label="上传图片"
+              initialValue={detailData?.files || []}
+            >
+              <UploadCommon
+                value={detailData?.files ? detailData?.files : []}
+                onChange={onUploadChange}
+              />
+            </Form.Item>
+          </Col>
+        </Row>
+      </Form>
+    </Modal>
+  );
+};
+export default Edit;

+ 382 - 0
src/pages/ReportingManagement/index.tsx

@@ -0,0 +1,382 @@
+import { PageContainer } from '@ant-design/pro-components';
+import { Button, Card, DatePicker, Form, Input, message, Modal, Select, Space, Table } from 'antd';
+import React, { useEffect, useState } from 'react';
+import { PlusCircleOutlined, ReloadOutlined, SearchOutlined } from '@ant-design/icons';
+import type { ColumnsType } from 'antd/es/table';
+import {
+  infoQuery,
+  reportingAbandon,
+  reportingDetailQuery,
+  reportingQuery,
+  reportingSuccess,
+  salesQuery,
+} from '@/services/ReportingManagement';
+import Edit from './edit';
+import Check from './check';
+import moment from 'moment';
+
+const { RangePicker } = DatePicker;
+
+interface DataType {
+  name: string;
+  record_id: string;
+  status: number;
+}
+
+/**
+ * 报备管理
+ * @constructor
+ */
+const ReportingManagement: React.FC = () => {
+  const [form] = Form.useForm();
+  const [pagination, setPagination] = useState({ total: 0, current: 1, pageSize: 10 });
+  const [detailData, setDetailData] = useState<object | null>({});
+  const [loading, setLoading] = useState(false);
+  const [dataList, setDataList] = useState([]);
+  const [searchData, setSearchData] = useState<object | null>({});
+  const [visible, setVisible] = useState(false);
+  const [salesmanList, setSalesmanList] = useState([]);
+  const [checkVisible, setCheckVisible] = useState(false);
+  const [checkData, setCheckData] = useState<object | null>({});
+
+  const getList = () => {
+    const params = {
+      q: 'page',
+      current: pagination.current,
+      pageSize: pagination.pageSize,
+      ...searchData,
+    };
+    reportingQuery(params).then((res) => {
+      if (res?.code === 0) {
+        setDataList(res?.data?.list || []);
+        setPagination(res.data.pagination);
+        setLoading(false);
+      }
+    });
+  };
+
+  const getSalesList = (id: string) => {
+    const params = {
+      q: 'list',
+      status: 1,
+      parent_id: id,
+    };
+    salesQuery(params).then((res) => {
+      if (res?.code === 0) {
+        setSalesmanList(res?.data || []);
+      }
+    });
+  };
+
+  const getUserInfo = () => {
+    infoQuery().then((res) => {
+      if (res?.code === 0) {
+        getSalesList(res.data.record_id);
+      }
+    });
+  };
+
+  useEffect(() => {
+    getList();
+    getUserInfo();
+  }, []);
+
+  // 搜索
+  const onFinish = () => {
+    form.validateFields().then((data) => {
+      const params: any = {};
+      if (data.project_name) {
+        params.project_name = data.project_name;
+      }
+      if (data.status) {
+        params.status = data.status;
+      }
+      if (data.user_id) {
+        params.user_id = data.user_id;
+      }
+      if (data.time) {
+        params.time_start = moment(data.time[0]).format('YYYY-MM-DD');
+        params.time_end = moment(data.time[1]).format('YYYY-MM-DD');
+      }
+      setLoading(true);
+      setSearchData(params);
+    });
+  };
+
+  const onReset = () => {
+    form.resetFields();
+    setLoading(true);
+    setSearchData(null);
+  };
+
+  useEffect(() => {
+    getList();
+  }, [searchData]);
+
+  // 分页切换
+  const tableChange = () => {
+    setLoading(true);
+    const params = {
+      q: 'page',
+      current: pagination.current,
+      pageSize: pagination.pageSize,
+      ...searchData,
+    };
+    reportingQuery(params).then((res) => {
+      if (res?.code === 0) {
+        setDataList(res?.data?.list || []);
+        setPagination(res.data.pagination);
+        setLoading(false);
+      }
+    });
+  };
+
+  // 新增
+  const onAdd = () => {
+    setVisible(true);
+    setDetailData(null);
+  };
+
+  // 编辑弹框
+  const toEdit = (record: any) => {
+    reportingDetailQuery(record.record_id).then((res) => {
+      if (res?.code === 0) {
+        setDetailData(record || null);
+        setVisible(true);
+      }
+    });
+  };
+
+  // 编辑弹框回调
+  const onEditCallback = () => {
+    setVisible(false);
+    getList();
+  };
+
+  // 查看弹框
+  const toCheck = (record: any) => {
+    reportingDetailQuery(record.record_id).then((res) => {
+      if (res?.code === 0) {
+        setCheckData(record);
+        setCheckVisible(true);
+      }
+    });
+  };
+
+  // 查看弹框回调
+  const checkCallback = () => {
+    setCheckVisible(false);
+  };
+
+  // 成交
+  const toDeal = (record: any) => {
+    Modal.confirm({
+      title: '成交',
+      content: '是否确认成交?',
+      onOk: () => {
+        reportingSuccess(record.record_id)
+          .then((res) => {
+            if (res.code === 0) {
+              message.success('成交成功');
+            } else {
+              message.error('成交失败');
+            }
+            getList();
+          })
+          .catch((e) => {
+            message.error(e?.message);
+          });
+      },
+    });
+  };
+
+  // 放弃
+  const toDisable = (record: any) => {
+    Modal.confirm({
+      title: '放弃',
+      content: '是否确认放弃?',
+      onOk: () => {
+        reportingAbandon(record.record_id)
+          .then((res) => {
+            if (res.code === 0) {
+              message.success('放弃成功');
+            } else {
+              message.error('放弃失败');
+            }
+            getList();
+          })
+          .catch((e) => {
+            message.error(e?.message);
+          });
+      },
+    });
+  };
+
+  const columns: ColumnsType<DataType> = [
+    {
+      title: '序号',
+      align: 'center',
+      key: 'index',
+      render: (_: any, row: any, index: number) => index + 1,
+    },
+    {
+      title: '工程名称',
+      dataIndex: 'project_name',
+      key: 'project_name',
+    },
+    {
+      title: '城市',
+      dataIndex: 'city',
+      key: 'city',
+      render: (_, data: any) => (
+        <span>{`${data.province}` + ' ' + `${data.city}` + ' ' + `${data.district}`}</span>
+      ),
+    },
+    {
+      title: '甲方联系人',
+      dataIndex: 'contact_person',
+      key: 'contact_person',
+    },
+    {
+      title: '联系方式',
+      dataIndex: 'phone',
+      key: 'phone',
+    },
+    {
+      title: '跟进人',
+      dataIndex: 'follow_people',
+      key: 'follow_people',
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      key: 'status',
+      render: (v) =>
+        v && <span>{{ 1: '审核未通过', 2: '审核通过', 3: '成交', 4: '放弃', 5: '丢单' }[v]}</span>,
+    },
+    {
+      title: '操作',
+      key: 'action',
+      render: (_, record) => (
+        <Space size="middle">
+          <a
+            onClick={() => {
+              toEdit(record);
+            }}
+          >
+            编辑
+          </a>
+          <a
+            onClick={() => {
+              toCheck(record);
+            }}
+          >
+            查看
+          </a>
+          {record?.status === 2 && (
+            <a
+              style={{ color: 'green' }}
+              onClick={() => {
+                toDeal(record);
+              }}
+            >
+              成交
+            </a>
+          )}
+          {record?.status === 2 && (
+            <a
+              style={{ color: 'red' }}
+              onClick={() => {
+                toDisable(record);
+              }}
+            >
+              放弃
+            </a>
+          )}
+        </Space>
+      ),
+    },
+  ];
+
+  const paginationProps = {
+    showSizeChanger: true,
+    showQuickJumper: true,
+    showTotal: (total: number) => {
+      return <span> 共 {total}条 </span>;
+    },
+    ...pagination,
+  };
+
+  return (
+    <PageContainer>
+      <Card>
+        <Form form={form} layout="inline" onFinish={onFinish}>
+          <Form.Item name="project_name" label="工程名称">
+            <Input placeholder="请输入工程名称" />
+          </Form.Item>
+          <Form.Item name="status" label="状态">
+            <Select style={{ width: '175px' }} placeholder="请选择状态">
+              <Select.Option key={2} value={2}>
+                审核通过
+              </Select.Option>
+              <Select.Option key={3} value={3}>
+                成交
+              </Select.Option>
+              <Select.Option key={4} value={4}>
+                放弃
+              </Select.Option>
+              <Select.Option key={5} value={5}>
+                丢单
+              </Select.Option>
+            </Select>
+          </Form.Item>
+          <Form.Item name="user_id" label="业务员">
+            <Select style={{ width: '175px' }} placeholder="请选择业务员">
+              {salesmanList && salesmanList.length
+                ? salesmanList.map((res: any) => {
+                    return (
+                      <Select.Option key={res?.record_id} value={res?.record_id}>
+                        {res?.user_name}
+                      </Select.Option>
+                    );
+                  })
+                : null}
+            </Select>
+          </Form.Item>
+          <Form.Item name="time" label="时间">
+            <RangePicker />
+          </Form.Item>
+          <Form.Item style={{ marginBottom: '10px' }}>
+            <Space>
+              <Button type="primary" htmlType="submit">
+                <SearchOutlined />
+                查询
+              </Button>
+              <Button htmlType="button" onClick={onReset}>
+                <ReloadOutlined />
+                重置
+              </Button>
+            </Space>
+          </Form.Item>
+        </Form>
+        <Button htmlType="button" type="primary" style={{ margin: '20px 0' }} onClick={onAdd}>
+          <PlusCircleOutlined />
+          新增报备
+        </Button>
+        <Table
+          columns={columns}
+          dataSource={dataList}
+          rowKey={(record) => record.record_id}
+          pagination={paginationProps}
+          loading={loading}
+          onChange={tableChange}
+        />
+      </Card>
+      {visible && <Edit detailData={detailData} editCallback={onEditCallback} visible={visible} />}
+      {checkVisible && (
+        <Check visible={checkVisible} data={checkData} checkCallback={checkCallback} />
+      )}
+    </PageContainer>
+  );
+};
+export default ReportingManagement;

+ 83 - 0
src/services/ReportingManagement.ts

@@ -0,0 +1,83 @@
+import { request } from '@@/plugin-request/request';
+import { stringify } from 'qs';
+
+/**
+ * 报备列表
+ * @param param
+ */
+export async function reportingQuery(param: object) {
+  return request(`/web/v1/customer_reports?${stringify(param)}`);
+}
+
+/**
+ * 报备详情
+ * @param id
+ */
+export async function reportingDetailQuery(id: string) {
+  return request(`/web/v1/customer_reports/${id}`);
+}
+
+/**
+ * 业务员列表
+ * @param param
+ */
+export async function salesQuery(param: object) {
+  return request(`/web/v1/users?${stringify(param)}`);
+}
+
+/**
+ * 当前账号信息
+ */
+export async function infoQuery() {
+  return request(`/web/v1/users/current`);
+}
+
+/**
+ * 城市列表
+ * @param params
+ */
+export async function cityQuery(params: any) {
+  return request(`/web/v1/cities?${stringify(params)}`);
+}
+
+/**
+ * 创建报备
+ * @param params
+ */
+export async function createReporting(params: object) {
+  return request(`/web/v1/customer_reports`, {
+    method: 'POST',
+    data: params,
+  });
+}
+
+/**
+ * 编辑报备
+ * @param params
+ */
+export async function editReporting(params: any) {
+  return request(`/web/v1/customer_reports/${params.record_id}`, {
+    method: 'PUT',
+    data: params,
+  });
+}
+
+/**
+ * 报备成交
+ * @param id
+ */
+export async function reportingSuccess(id: string) {
+  return request(`/web/v1/customer_reports/${id}/success`, {
+    method: 'PATCH',
+  });
+}
+
+/**
+ * 报备放弃
+ * @param id
+ */
+export async function reportingAbandon(id: string) {
+  return request(`/web/v1/customer_reports/${id}/abandon`, {
+    method: 'PATCH',
+  });
+}