Selaa lähdekoodia

feat: 统计-软件锁用量-图表

lanjianrong 4 vuotta sitten
vanhempi
commit
e1402dc7bc
2 muutettua tiedostoa jossa 165 lisäystä ja 93 poistoa
  1. 18 0
      src/global.less
  2. 147 93
      src/pages/Statistic/Software/Usage/index.jsx

+ 18 - 0
src/global.less

@@ -217,3 +217,21 @@ input:-webkit-autofill:active {
 //   height: 100%;
 //   cursor: col-resize;
 // }
+.card-transition {
+  display: flex;
+  justify-content: center;
+  height: calc(11.11111vw - 20px);
+  min-height: 130px;
+  max-height: 280px;
+  -o-object-fit: cover;
+  object-fit: cover;
+  overflow: hidden;
+  border: 1px solid #f0f0f0;
+  border-radius: 6px;
+  transition: all 0.3s;
+}
+.card-transition:hover {
+  border-color: transparent;
+  box-shadow: 0 6px 16px rgb(107 147 224 / 14%);
+  transform: translateY(-4px);
+}

+ 147 - 93
src/pages/Statistic/Software/Usage/index.jsx

@@ -5,6 +5,7 @@ import { querySoftwareUsageList, queryUsageSelectOptions } from '@/services/stat
 import consts from '@/consts'
 import { useDebounceFn } from 'ahooks'
 import dayjs from 'dayjs'
+import { Pie } from '@ant-design/charts'
 
 const { Text } = Typography
 const opMap = {
@@ -12,6 +13,12 @@ const opMap = {
   DEPARTMENT: 'department'
 }
 
+const colLabelValToZH = {
+  giftsCount: '赠送',
+  lendCount: '借出',
+  salesCount: '销售'
+}
+
 const Usage = () => {
   const tRef = useRef(null)
   const [state, setState] = useState({
@@ -51,6 +58,26 @@ const Usage = () => {
     }
     return state.department || []
   }, [state.optionType, state.staff, state.department])
+
+  const pieData = useMemo(() => {
+    if (!state.chart || !state.sum) return {}
+    const leftKeys = Object.keys(state.chart)
+    const pieLeft = []
+    leftKeys.forEach(item => {
+      const v = state.chart[item]
+      pieLeft.push({ label: item === 'unused' ? '未使用' : '已使用', value: v })
+    })
+    const rightKeys = Object.keys(state.sum)
+    const pieRight = []
+    rightKeys.forEach(item => {
+      const v = state.sum[item]
+      if (item !== 'receiveCount') {
+        pieRight.push({ label: colLabelValToZH[item], value: v })
+      }
+    })
+    return { pieLeft, pieRight }
+  }, [state.chart])
+
   useEffect(() => {
     queryStaffAndDepartment()
   }, [])
@@ -117,103 +144,130 @@ const Usage = () => {
     }
   ]
 
+  const leftConfig = {
+    appendPadding: 10,
+    data: pieData.pieLeft,
+    angleField: 'value',
+    colorField: 'label',
+    radius: 0.9,
+    interactions: [{ type: 'element-active' }]
+  }
+  const rightConfig = {
+    appendPadding: 10,
+    data: pieData.pieRight,
+    angleField: 'value',
+    colorField: 'label',
+    radius: 0.9,
+    interactions: [{ type: 'element-active' }]
+  }
+
   return (
-    <BasicTable
-      manualRequest
-      search={false}
-      columns={columns}
-      actionRef={tRef}
-      rowkey={record => record.name}
-      toolbar={{
-        title: [
-          <Select
-            key="Select"
-            defaultValue="staff"
-            options={[
-              { label: '部门', value: 'department' },
-              { label: '员工', value: 'staff' }
-            ]}
-            onChange={val => setState({ ...state, optionType: val })}
-          />,
-          state.optionType === opMap.STAFF ? (
+    <div className="flex flex-col">
+      <div className="flex flex-row justify-between mb-4">
+        <div className="card-transition  w-1/2 bg-white mr-2">
+          {pieData.pieLeft ? <Pie {...leftConfig} /> : null}
+        </div>
+        <div className="card-transition w-1/2 bg-white ml-2">
+          {pieData.pieRight ? <Pie {...rightConfig} /> : null}
+        </div>
+      </div>
+      <BasicTable
+        manualRequest
+        search={false}
+        columns={columns}
+        actionRef={tRef}
+        rowkey="name"
+        toolbar={{
+          title: [
             <Select
-              key="StaffSelect"
-              className="min-w-120px"
-              dropdownMatchSelectWidth
-              options={options}
-              mode="multiple"
-              onChange={value => trySetOpIds(value)}
+              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"
+                dropdownMatchSelectWidth
+                options={options}
+                mode="multiple"
+                onChange={value => trySetOpIds(value)}
+              />
+            ) : (
+              <TreeSelect
+                key="DepartmentSelect"
+                treeData={options}
+                className="min-w-120px"
+                dropdownMatchSelectWidth
+                multiple
+                onChange={value => trySetOpIds(value)}
+              />
+            )
+          ],
+          actions: [
+            <DatePicker.RangePicker
+              picker="month"
+              key="DatePicker"
+              disabled={[false, true]}
+              value={state.startMonth}
+              onChange={val => setState({ ...state, startMonth: val })}
             />
-          ) : (
-            <TreeSelect
-              key="DepartmentSelect"
-              treeData={options}
-              className="min-w-120px"
-              dropdownMatchSelectWidth
-              multiple
-              onChange={value => trySetOpIds(value)}
-            />
-          )
-        ],
-        actions: [
-          <DatePicker.RangePicker
-            picker="month"
-            key="DatePicker"
-            disabled={[false, true]}
-            value={state.startMonth}
-            onChange={val => setState({ ...state, startMonth: val })}
-          />
-        ]
-      }}
-      params={mainParams}
-      pagination={false}
-      bordered
-      request={async (params, sort, filter) => {
-        const {
-          code = -1,
-          data: { list, sum, chart, create }
-        } = await querySoftwareUsageList({ ...params, ...sort, ...filter })
-        setState({ ...state, sum, chart, create })
-        return {
-          data: list,
-          success: code === consts.RET_CODE.SUCCESS,
-          total: list?.length || 0
+          ]
+        }}
+        params={mainParams}
+        pagination={false}
+        bordered
+        request={async (params, sort, filter) => {
+          const {
+            code = -1,
+            data: { list, sum, chart, create }
+          } = await querySoftwareUsageList({ ...params, ...sort, ...filter })
+          setState({ ...state, sum, chart, create })
+          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-center">{state.create}</Table.Summary.Cell>
+                <Table.Summary.Cell className="text-center">
+                  {state.sum?.receiveCount}
+                </Table.Summary.Cell>
+                <Table.Summary.Cell className="text-center">
+                  {state.sum?.lendCount}
+                </Table.Summary.Cell>
+                <Table.Summary.Cell className="text-center">
+                  {state.sum?.salesCount}
+                </Table.Summary.Cell>
+                <Table.Summary.Cell className="text-center">
+                  {state.sum?.giftsCount}
+                </Table.Summary.Cell>
+              </Table.Summary.Row>
+              <Table.Summary.Row>
+                <Table.Summary.Cell className="text-center">总计</Table.Summary.Cell>
+                <Table.Summary.Cell colSpan={2} className="text-center">
+                  <Text type="danger">{state.create + state.sum?.receiveCount}</Text>
+                </Table.Summary.Cell>
+                <Table.Summary.Cell colSpan={3} className="text-center">
+                  <Text type="danger">
+                    {state.sum?.lendCount + state.sum?.salesCount + state.sum?.giftsCount}
+                  </Text>
+                </Table.Summary.Cell>
+              </Table.Summary.Row>
+            </>
+          ) : null
         }
-      }}
-      summary={data =>
-        data?.length ? (
-          <>
-            <Table.Summary.Row>
-              <Table.Summary.Cell className="text-center">小计</Table.Summary.Cell>
-              <Table.Summary.Cell className="text-center">{state.create}</Table.Summary.Cell>
-              <Table.Summary.Cell className="text-center">
-                {state.sum?.receiveCount}
-              </Table.Summary.Cell>
-              <Table.Summary.Cell className="text-center">
-                {state.sum?.lendCount}
-              </Table.Summary.Cell>
-              <Table.Summary.Cell className="text-center">
-                {state.sum?.salesCount}
-              </Table.Summary.Cell>
-              <Table.Summary.Cell className="text-center">
-                {state.sum?.giftsCount}
-              </Table.Summary.Cell>
-            </Table.Summary.Row>
-            <Table.Summary.Row>
-              <Table.Summary.Cell className="text-center">总计</Table.Summary.Cell>
-              <Table.Summary.Cell colSpan={2} className="text-center">
-                <Text type="danger">{state.create + state.sum?.receiveCount}</Text>
-              </Table.Summary.Cell>
-              <Table.Summary.Cell colSpan={3} className="text-center">
-                <Text type="danger">
-                  {state.sum?.lendCount + state.sum?.salesCount + state.sum?.giftsCount}
-                </Text>
-              </Table.Summary.Cell>
-            </Table.Summary.Row>
-          </>
-        ) : null
-      }
-    />
+      />
+    </div>
   )
 }