Переглянути джерело

Merge branch 'dev' of http://192.168.1.41:3000/outaozhen/cldV2react into dev

outaozhen 4 роки тому
батько
коміт
b177a4b4e9

+ 14 - 7
src/components/RightContent/NoticeIcon/index.tsx

@@ -88,13 +88,14 @@ const NoticeIconView = () => {
   const noticeData = getNoticeData(notices)
   const unreadMsg = getUnreadData(noticeData || {})
 
-  const changeReadState = async (id: string) => {
-    const { code = -1 } = await updateNotice({ ids: [id] })
+  const changeReadState = async item => {
+    if (item.isRead) return
+    const { code = -1 } = await updateNotice({ ids: [item.id] })
     if (code === consts.RET_CODE.SUCCESS) {
       setNotices(
-        notices.map(item => {
-          const notice = { ...item }
-          if (notice.id === id) {
+        notices.map(i => {
+          const notice = { ...i }
+          if (notice.id === item.id) {
             notice.isRead = true
           }
           return notice
@@ -108,6 +109,8 @@ const NoticeIconView = () => {
   }
 
   const clearReadState = async (title: string, key: string) => {
+    if (initialState?.currentUser?.[`${title}HasClear`]) return
+
     const ids = []
     setNotices(
       notices.map(item => {
@@ -124,7 +127,11 @@ const NoticeIconView = () => {
       message.success(`${'清空了'} ${title}`)
       setInitialState({
         ...initialState,
-        currentUser: { ...currentUser, unreadCount: currentUser.unreadCount - notices.length }
+        currentUser: {
+          ...currentUser,
+          unreadCount: currentUser.unreadCount - ids.length,
+          [`${title}HasClear`]: true
+        }
       })
     }
   }
@@ -134,7 +141,7 @@ const NoticeIconView = () => {
       className={styles.action}
       count={currentUser && currentUser.unreadCount}
       onItemClick={item => {
-        changeReadState(item.id!)
+        changeReadState(item)
       }}
       onClear={(title: string, key: string) => clearReadState(title, key)}
       loading={false}

+ 3 - 2
src/components/Table/src/BasicTable.tsx

@@ -2,7 +2,7 @@
 /* eslint-disable no-param-reassign */
 import PermSelect from '@/pages/Customer/Company/components/PermSelect'
 import { TABLE_COLUMNS_MAP, ColumnStateEnum } from '@/utils/cache/cacheEnum'
-import { isNullOrUnDef } from '@/utils/is'
+import { isNullOrUnDef, isUnDef } from '@/utils/is'
 import type { ColumnsState } from '@ant-design/pro-table'
 import ProTable from '@ant-design/pro-table'
 import { useModel } from 'umi'
@@ -95,7 +95,8 @@ const BasicTable: {
     tableElRef,
     columnsRef,
     state.selectKeysRef,
-    state.sizeRef
+    state.sizeRef,
+    isUnDef(resetProps.pagination)
   )
 
   useLayoutEffect(() => {

+ 25 - 20
src/components/Table/src/hooks/useTableScroll.ts

@@ -11,7 +11,8 @@ export function useTableScroll(
   tableElRef: RefObject<HTMLElement>,
   columnsRef: ProColumns<any> = [],
   selectKeysRef: string[] = [],
-  sizeRef: DensitySize = 'middle'
+  sizeRef: DensitySize = 'middle',
+  paginationRef: boolean
 ) {
   // let bodyEl: HTMLElement | null
   const [tableHeight, setTableHeight] = useState(null)
@@ -30,19 +31,21 @@ export function useTableScroll(
 
     let paginationHeight = 0
     if (dataSource && dataSource?.length) {
-      paginationHeight += 32
-      if (sizeRef) {
-        switch (sizeRef) {
-          case 'large':
-            paginationHeight += 32
-            break
-          case 'small':
-            paginationHeight += 24
-            break
-
-          default:
-            paginationHeight += 24
-            break
+      if (paginationRef) {
+        paginationHeight += 32
+        if (sizeRef) {
+          switch (sizeRef) {
+            case 'large':
+              paginationHeight += 32
+              break
+            case 'small':
+              paginationHeight += 24
+              break
+
+            default:
+              paginationHeight += 24
+              break
+          }
         }
       }
     }
@@ -71,13 +74,15 @@ export function useTableScroll(
       const tbodyEl: HTMLElement = tableElRef.current
         ?.querySelector('.ant-table-container')
         ?.querySelector('.ant-table-tbody')
-      const hasScrollBar =
-        tableElRef.current?.querySelector('.ant-table-container')?.querySelector('table')?.style
-          .width !== '100%'
+      const el = tableElRef.current?.querySelector('.ant-table-container')?.querySelector('table')
+      let hasScrollBar = el?.style.width !== '100%'
+
+      if (el?.style.width !== '100%') {
+        hasScrollBar = el?.clientWidth > el?.style.width
+      }
+
+      const notDataHeight = `${height - (hasScrollBar ? 8 : 0)}px`
 
-      const notDataHeight = `calc(100vh - 48px - 48px - 64px - ${headerHeight}px - ${
-        hasScrollBar ? 8 : 0
-      }px)`
       tbodyEl && (tbodyEl!.style.height = notDataHeight)
       return
     }

+ 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);
+}

+ 1 - 1
src/pages/Customer/Business/index.jsx

@@ -185,7 +185,7 @@ const Business = ({ dispatch, groupList, shouldUpdate, loading, refreshGroupList
             ) : null}
           </div>
         </div>
-        <div className="p-4 bg-white " style={{ height: 'calc(100% - 1rem*2 - 20px)' }}>
+        <div className="p-4 bg-white " style={{ height: 'calc(100% - 1rem*2 - 25px)' }}>
           <div className="max-h-1/3">
             {funnelData?.length ? <Funnel data={funnelData} {...conifg} /> : null}
           </div>

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