|
|
@@ -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>
|
|
|
)
|
|
|
}
|
|
|
|