Prechádzať zdrojové kódy

feat: 新增统计下OptionSelect组件

lanjianrong 4 rokov pred
rodič
commit
635a84eac0

+ 13 - 8
config/routes.js

@@ -151,21 +151,26 @@ export default [
     routes: [
       {
         path: '/statistic',
-        redirect: '/statistic/software'
+        redirect: '/statistic/product'
       },
       {
-        path: 'software',
-        name: 'software',
+        path: 'product',
+        name: 'product',
         icon: 'icon-chanpin',
         routes: [
           {
-            path: '/statistic/software',
-            redirect: '/statistic/software/usage'
+            path: '/statistic/product',
+            redirect: '/statistic/product/software-usage'
           },
           {
-            path: 'usage',
-            name: 'usage',
-            component: './Statistic/Software/Usage'
+            path: 'software-usage',
+            name: 'software-usage',
+            component: './Statistic/Product/SoftwareUsage'
+          },
+          {
+            path: 'invoice-aggregate',
+            name: 'invoice-aggregate',
+            component: './Statistic/Product/InvoiceAggregate'
           }
         ]
       }

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

@@ -35,6 +35,7 @@ export default {
   'menu.account.settings': '个人中心',
   'menu.settings': '个人中心',
   'menu.statistic': '统计',
-  'menu.statistic.software': '产品销售',
-  'menu.statistic.software.usage': '软件锁用量'
+  'menu.statistic.product': '产品销售',
+  'menu.statistic.product.software-usage': '软件锁用量',
+  'menu.statistic.product.invoice-aggregate': '发票收款入账汇总'
 }

+ 7 - 0
src/pages/Statistic/Product/InvoiceAggregate/index.jsx

@@ -0,0 +1,7 @@
+import React from 'react'
+
+const InvoiceAggregate = () => {
+  return <div />
+}
+
+export default InvoiceAggregate

+ 15 - 92
src/pages/Statistic/Software/Usage/index.jsx

@@ -1,18 +1,14 @@
-import { useState, useEffect, useRef, useMemo } from 'react'
+import { useState, useRef, useMemo } from 'react'
 import BasicTable from '@/components/Table'
-import { DatePicker, Select, TreeSelect, Table, Typography } from 'antd'
-import { querySoftwareUsageList, queryUsageSelectOptions } from '@/services/statistic'
+import { DatePicker, Table, Typography } from 'antd'
+import { querySoftwareUsageList } from '@/services/statistic'
 import consts from '@/consts'
-import { useDebounceFn } from 'ahooks'
 import dayjs from 'dayjs'
 import { Pie } from '@ant-design/charts'
 import { isMobile } from '@/utils/is'
+import OptionSelect from '../../components/OptionSelect'
 
 const { Text } = Typography
-const opMap = {
-  STAFF: 'staff',
-  DEPARTMENT: 'department'
-}
 
 const colLabelValToZH = {
   giftsCount: '赠送',
@@ -23,42 +19,12 @@ const colLabelValToZH = {
 const Usage = () => {
   const tRef = useRef(null)
   const [state, setState] = useState({
-    optionType: opMap.STAFF,
-    opIds: [],
-    department: null,
-    staff: null,
-    startMonth: [dayjs(new Date()), dayjs(new Date())]
-  })
-
-  const queryStaffAndDepartment = async () => {
-    const { code = -1, data: { department = [], staff = [] } = {} } =
-      await queryUsageSelectOptions()
-    if (code === consts.RET_CODE.SUCCESS) {
-      setState({
-        ...state,
-        department,
-        staff
-      })
-      tRef.current?.reload()
+    params: {
+      optionType: 'staff',
+      dataIds: [],
+      startMonth: [dayjs(new Date()), dayjs(new Date())]
     }
-  }
-
-  const mainParams = useMemo(() => {
-    const p = { optionType: state.optionType, startMonth: state.startMonth[0].format('YYYY-MM') }
-    if (state.optionType === opMap.STAFF) {
-      p.staffIds = state.opIds
-    } else {
-      p.departmentIds = state.opIds
-    }
-    return p
-  }, [state.optionType, state.opIds, state.startMonth])
-
-  const options = useMemo(() => {
-    if (state.optionType === opMap.STAFF) {
-      return state.staff?.map(item => ({ label: item.username, value: item.id })) || []
-    }
-    return state.department || []
-  }, [state.optionType, state.staff, state.department])
+  })
 
   const pieData = useMemo(() => {
     if (!state.chart || !state.sum) return {}
@@ -79,21 +45,6 @@ const Usage = () => {
     return { pieLeft, pieRight }
   }, [state.chart])
 
-  useEffect(() => {
-    queryStaffAndDepartment()
-  }, [])
-  const { run: trySetOpIds } = useDebounceFn(
-    ids => {
-      setState({ ...state, opIds: ids })
-    },
-    { wait: 500 }
-  )
-  useEffect(() => {
-    // 发起请求
-    if (state.opIds?.length) {
-      tRef.current?.reload()
-    }
-  }, [state.opIds])
   const columns = [
     {
       title: '名称',
@@ -164,6 +115,9 @@ const Usage = () => {
     interactions: [{ type: 'element-active' }]
   }
 
+  const optionChange = (type, ids) =>
+    setState({ ...state, params: { ...state.params, optionType: type, dataIds: ids } })
+
   return (
     <div className="flex flex-col">
       {!isMobile() && (
@@ -184,49 +138,18 @@ const Usage = () => {
         actionRef={tRef}
         rowkey="id"
         toolbar={{
-          title: [
-            <Select
-              key="Select"
-              defaultValue="staff"
-              options={[
-                { label: '部门', value: 'department' },
-                { label: '员工', value: 'staff' }
-              ]}
-              onChange={val => setState({ ...state, optionType: val })}
-            />,
-            state.optionType === opMap.STAFF ? (
-              <Select
-                key="StaffSelect"
-                className="min-w-120px"
-                defaultOpen
-                dropdownMatchSelectWidth
-                options={options}
-                mode="multiple"
-                onChange={value => trySetOpIds(value)}
-              />
-            ) : (
-              <TreeSelect
-                key="DepartmentSelect"
-                defaultOpen
-                treeData={options}
-                className="min-w-180px"
-                dropdownMatchSelectWidth
-                multiple
-                onChange={value => trySetOpIds(value)}
-              />
-            )
-          ],
+          title: <OptionSelect onChange={optionChange} />,
           actions: [
             <DatePicker.RangePicker
               picker="month"
               key="DatePicker"
               disabled={[false, true]}
               value={state.startMonth}
-              onChange={val => setState({ ...state, startMonth: val })}
+              onChange={val => setState({ ...state, params: { ...state.params, startMonth: val } })}
             />
           ]
         }}
-        params={mainParams}
+        params={state.params}
         pagination={false}
         bordered
         request={async (params, sort, filter) => {

+ 79 - 0
src/pages/Statistic/components/OptionSelect.tsx

@@ -0,0 +1,79 @@
+import consts from '@/consts'
+import { queryUsageSelectOptions } from '@/services/statistic'
+import { useDebounceFn } from 'ahooks'
+import { Select, TreeSelect } from 'antd'
+import React, { useState, useEffect } from 'react'
+
+enum opMap {
+  STAFF = 'staff',
+  DEPARTMENT = 'department'
+}
+
+type OptionSelectProps = {
+  onChange: (type: 'staff' | 'department', value) => void
+}
+const OptionSelect: React.FC<OptionSelectProps> = ({ onChange }) => {
+  const [state, setState] = useState({
+    optionType: opMap.STAFF,
+    opIds: null,
+    department: [],
+    staff: []
+  })
+
+  useEffect(() => {
+    const queryStaffAndDepartment = async () => {
+      const { code = -1, data: { department = [], staff = [] } = {} } =
+        await queryUsageSelectOptions()
+      if (code === consts.RET_CODE.SUCCESS) {
+        setState({
+          ...state,
+          department,
+          staff
+        })
+      }
+    }
+    queryStaffAndDepartment()
+  }, [])
+
+  const { run: trySetOpIds } = useDebounceFn(
+    ids => {
+      setState({ ...state, opIds: ids })
+      onChange(state.optionType, ids)
+    },
+    { wait: 500 }
+  )
+  return (
+    <div>
+      <Select
+        defaultValue="staff"
+        options={[
+          { label: '按部门', value: 'department' },
+          { label: '按员工', value: 'staff' }
+        ]}
+        onChange={val => setState({ ...state, optionType: val })}
+      />
+      {state.optionType === opMap.STAFF ? (
+        <TreeSelect
+          className="min-w-180px"
+          defaultOpen
+          treeCheckable
+          showCheckedStrategy="SHOW_PARENT"
+          dropdownMatchSelectWidth
+          treeData={state.staff}
+          onChange={value => trySetOpIds(value)}
+        />
+      ) : (
+        <TreeSelect
+          className="min-w-180px"
+          defaultOpen
+          treeData={state.department}
+          dropdownMatchSelectWidth
+          multiple
+          onChange={value => trySetOpIds(value)}
+        />
+      )}
+    </div>
+  )
+}
+
+export default OptionSelect