Browse Source

feat: 客户来源统计

outaozhen 4 năm trước cách đây
mục cha
commit
c786eb395d

+ 5 - 0
config/routes.js

@@ -226,6 +226,11 @@ export default [
             name: 'additions',
             component: './Statistic/Customer/CustomerAdditions',
             access: 'authRouteFilter'
+          },
+          {
+            path: '/statistic/customer/source',
+            name: 'source',
+            component: './Statistic/Customer/Source'
           }
         ]
       }

+ 2 - 1
src/locales/zh-CN/menu.js

@@ -49,5 +49,6 @@ export default {
   'menu.statistic.product.trends': '发票收款入账趋势',
   'menu.statistic.product.receivables': '应收款统计',
   'menu.statistic.customer': '客户数据',
-  'menu.statistic.customer.additions': '客户新增'
+  'menu.statistic.customer.additions': '客户新增',
+  'menu.statistic.customer.source': '客户来源'
 }

+ 124 - 0
src/pages/Statistic/Customer/Source/index.tsx

@@ -0,0 +1,124 @@
+import BasicTable from '@/components/Table'
+import { PageContainer } from '@ant-design/pro-layout'
+import React, { useRef, useState } from 'react'
+import dayjs from 'dayjs'
+import consts from '@/consts'
+import { disabledDate } from '@/utils/utils'
+import OptionSelect from '../../components/OptionSelect'
+import { DatePicker, Select, Table } from 'antd'
+import { Pie } from '@ant-design/charts'
+import { querySourceList } from '@/services/statistic'
+
+const columnGroupMap = [
+  { label: '客户', value: 'client' },
+  { label: '单位', value: 'company' }
+]
+
+const Source = () => {
+  const [state, setState] = useState({
+    params: {
+      optionType: 'singleStaff',
+      dataIds: [],
+      priceType: 'client',
+      startMonth: [dayjs(new Date()), dayjs(new Date())]
+    },
+    list: []
+  })
+
+  const tRef = useRef(null)
+
+  const handleOptionChange = (type, ids) =>
+    setState({ ...state, params: { ...state.params, optionType: type, dataIds: ids } })
+
+  const columnConfig = {
+    data: state.list.map(item => ({ type: item.sourceName, value: item.count })),
+    appendPadding: 10,
+    angleField: 'value',
+    colorField: 'type',
+    radius: 0.9,
+    interactions: [{ type: 'element-active' }],
+    color: ['#40B7E6', '#79CE67', '#FBD743', '#ED9978', '#B8E641', '#E641B8', '#E67041', '#41E6C3']
+  }
+
+  const columns = [
+    {
+      dataIndex: 'sourceName',
+      title: '服务方式',
+      align: 'center'
+    },
+    {
+      dataIndex: 'count',
+      title: '数量',
+      align: 'center',
+      render: text => <div className="text-right">{text}</div>
+    }
+  ]
+  return (
+    <PageContainer title={false} breadcrumb={false} waterMarkProps={{ offsetTop: 111 }}>
+      <div className="flex flex-col">
+        <div className="flex flex-row justify-between mb-4">
+          <div className="card-transition bg-white w-full h-250px">
+            {/* 扇形图 */}
+            {state.list?.length ? <Pie {...columnConfig} /> : null}
+          </div>
+        </div>
+        <BasicTable
+          search={false}
+          columns={columns}
+          actionRef={tRef}
+          rowkey="sourceId"
+          params={state.params}
+          pagination={false}
+          bordered
+          toolbar={{
+            title: [
+              <OptionSelect onChange={handleOptionChange} type="Source" key="sourceId" multiple={false} />,
+              <div className="ml-2" key="id">
+                <Select
+                  defaultValue="client"
+                  options={columnGroupMap}
+                  placeholder="请选择类型"
+                  onChange={e => setState({ ...state, params: { ...state.params, priceType: e } })}
+                />
+              </div>
+            ],
+            actions: [
+              <DatePicker.RangePicker
+                picker="month"
+                key="DatePicker"
+                allowClear={false}
+                disabledDate={current => disabledDate(current, 'month')}
+                value={state.params.startMonth}
+                onChange={val => setState({ ...state, params: { ...state.params, startMonth: val } })}
+              />
+            ]
+          }}
+          request={async params => {
+            const {
+              code = -1,
+              data: { list, sum }
+            } = await querySourceList({ ...params })
+            setState({ ...state, sum, list })
+            return {
+              data: list,
+              success: code === consts.RET_CODE.SUCCESS,
+              total: list?.length || 0
+            }
+          }}
+          summary={data =>
+            data?.length ? (
+              <>
+                <Table.Summary.Row>
+                  <Table.Summary.Cell className="text-center">小计</Table.Summary.Cell>
+                  <Table.Summary.Cell className="text-right">{state.sum}</Table.Summary.Cell>
+                </Table.Summary.Row>
+              </>
+            ) : null
+          }
+        />
+      </div>
+    </PageContainer>
+  )
+}
+
+export default Source

+ 16 - 0
src/services/statistic.ts

@@ -44,3 +44,19 @@ export async function queryInvoiceReceivablesList(params) {
     data: params
   })
 }
+
+/** 来源统计 */
+export async function querySourceList(params) {
+  return request('/statistic/source/statistics', {
+    method: 'POST',
+    data: params
+  })
+}
+
+/** 单位性质统计 */
+export async function queryNatureList(params) {
+  return request('/statistic/unit/nature', {
+    method: 'POST',
+    data: params
+  })
+}