Просмотр исходного кода

feat(组件): 新增ProTableCard组件

xieyonghong 3 лет назад
Родитель
Сommit
7397e6af65

+ 24 - 0
src/components/ProTableCard/CardItems/device.tsx

@@ -0,0 +1,24 @@
+import { Card } from 'antd';
+import { EditOutlined, EllipsisOutlined, SettingOutlined } from '@ant-design/icons';
+
+export interface DeviceCardProps {
+  id: string;
+  name: string;
+  photoUrl?: string;
+}
+
+export default (props: DeviceCardProps) => {
+  return (
+    <Card
+      style={{ width: 280 }}
+      cover={null}
+      actions={[
+        <SettingOutlined key="setting" />,
+        <EditOutlined key="edit" />,
+        <EllipsisOutlined key="ellipsis" />,
+      ]}
+    >
+      <div>{props.name}</div>
+    </Card>
+  );
+};

+ 40 - 0
src/components/ProTableCard/index.less

@@ -0,0 +1,40 @@
+@import '../../../node_modules/antd/lib/style/themes/variable';
+
+.pro-table-card {
+  position: relative;
+
+  .pro-table-card-setting-item {
+    color: rgba(0, 0, 0, 0.75);
+    font-size: 16px;
+    cursor: pointer;
+
+    &:hover {
+      color: @primary-color-hover;
+    }
+
+    &.active {
+      color: @primary-color-active;
+    }
+  }
+
+  .pro-table-card-items {
+    display: flex;
+    flex-wrap: wrap;
+    padding-bottom: 32px;
+
+    > div {
+      margin-right: 14px;
+      margin-bottom: 14px;
+    }
+  }
+
+  .pro-table-card-pagination {
+    position: absolute;
+    right: 24px;
+    bottom: 24px;
+
+    > .ant-pagination-item {
+      display: none;
+    }
+  }
+}

+ 154 - 0
src/components/ProTableCard/index.tsx

@@ -0,0 +1,154 @@
+import ProTable from '@jetlinks/pro-table';
+import type { ProTableProps } from '@jetlinks/pro-table';
+import type { ParamsType } from '@ant-design/pro-provider';
+import React, { useState } from 'react';
+import { isFunction } from 'lodash';
+import { Space, Pagination } from 'antd';
+import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons';
+import classNames from 'classnames';
+import './index.less';
+
+enum ModelEnum {
+  TABLE = 'TABLE',
+  CARD = 'CARD',
+}
+
+type ModelType = keyof typeof ModelEnum;
+
+interface ProTableCardProps<T> {
+  cardRender?: (data: T) => JSX.Element | React.ReactNode;
+}
+
+const ProTableCard = <
+  T extends Record<string, any>,
+  U extends ParamsType = ParamsType,
+  ValueType = 'text',
+>(
+  props: ProTableCardProps<T> & ProTableProps<T, U, ValueType>,
+) => {
+  const { cardRender, toolBarRender, request, ...extraProps } = props;
+  const [model, setModel] = useState<ModelType>(ModelEnum.CARD);
+  const [total, setTotal] = useState<number | undefined>(0);
+  const [current, setCurrent] = useState(1); // 当前页
+  const [pageIndex, setPageIndex] = useState(0);
+  const [pageSize, setPageSize] = useState(10); // 每页条数
+
+  /**
+   * 处理 Card
+   * @param dataSource
+   */
+  const handleCard = (dataSource: readonly T[] | undefined): JSX.Element => {
+    return (
+      <div className={'pro-table-card-items'}>
+        {dataSource
+          ? dataSource.map((item) =>
+              cardRender && isFunction(cardRender) ? cardRender(item) : null,
+            )
+          : null}
+      </div>
+    );
+  };
+
+  return (
+    <div className={'pro-table-card'}>
+      <ProTable<T, U, ValueType>
+        {...extraProps}
+        params={
+          {
+            ...props.params,
+            current: current,
+            pageIndex: pageIndex,
+            pageSize,
+          } as any
+        }
+        request={async (param, sort, filter) => {
+          if (request) {
+            const resp = await request(param, sort, filter);
+            setTotal(resp.result ? resp.result.total : 0);
+            return {
+              code: resp.message,
+              result: {
+                data: resp.result ? resp.result.data : [],
+                pageIndex: resp.result ? resp.result.pageIndex : 0,
+                pageSize: resp.result ? resp.result.pageSize : 0,
+                total: resp.result ? resp.result.total : 0,
+              },
+              status: resp.status,
+            };
+          }
+          return {};
+        }}
+        pagination={{
+          onChange: (page, size) => {
+            setCurrent(page);
+            setPageIndex(page - 1);
+            setPageSize(size);
+          },
+          pageSize: pageSize,
+          current: current,
+        }}
+        toolBarRender={(action, row) => {
+          const oldBar = toolBarRender ? toolBarRender(action, row) : [];
+          return [
+            ...oldBar,
+            <Space
+              align="center"
+              key={ModelEnum.TABLE}
+              size={12}
+              className={classNames(`pro-table-card-setting-item`, {
+                active: model === ModelEnum.TABLE,
+              })}
+              onClick={() => {
+                setModel(ModelEnum.TABLE);
+              }}
+            >
+              <BarsOutlined />
+            </Space>,
+            <Space
+              align="center"
+              size={12}
+              key={ModelEnum.CARD}
+              className={classNames(`pro-table-card-setting-item`, {
+                active: model === ModelEnum.CARD,
+              })}
+              onClick={() => {
+                setModel(ModelEnum.CARD);
+              }}
+            >
+              <AppstoreOutlined />
+            </Space>,
+          ];
+        }}
+        tableViewRender={
+          model === ModelEnum.CARD
+            ? (tableProps) => {
+                return handleCard(tableProps.dataSource);
+              }
+            : undefined
+        }
+      />
+      {model === ModelEnum.CARD && (
+        <Pagination
+          showSizeChanger
+          size="small"
+          className={'pro-table-card-pagination'}
+          total={total}
+          current={current}
+          onChange={(page, size) => {
+            setCurrent(page);
+            setPageIndex(page - 1);
+            setPageSize(size);
+          }}
+          pageSize={pageSize}
+          showTotal={(num) => {
+            const minSize = pageIndex * pageSize + 1;
+            const MaxSize = (pageIndex + 1) * pageSize;
+            return `第 ${minSize} - ${MaxSize > num ? num : MaxSize} 条/总共 ${num} 条`;
+          }}
+        />
+      )}
+    </div>
+  );
+};
+
+export default ProTableCard;

+ 2 - 2
src/components/Upload/Image/index.less

@@ -29,8 +29,8 @@
 
     .upload-image-content {
       .flex-center();
-      position: relative;
 
+      position: relative;
       display: flex;
       flex-direction: column;
       width: @with;
@@ -40,10 +40,10 @@
 
       .upload-image-mask {
         .flex-center();
+
         position: absolute;
         top: 0;
         left: 0;
-
         display: none;
         width: 100%;
         height: 100%;

+ 1 - 0
src/components/index.ts

@@ -1,2 +1,3 @@
 export { default as RadioCard } from './RadioCard';
 export { default as UploadImage } from './Upload/Image';
+export { default as ProTableCard } from './ProTableCard';

+ 4 - 2
src/pages/device/Instance/index.tsx

@@ -1,6 +1,5 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import type { ActionType, ProColumns } from '@jetlinks/pro-table';
-import ProTable from '@jetlinks/pro-table';
 import type { DeviceInstance } from '@/pages/device/Instance/typings';
 import moment from 'moment';
 import { Badge, Button, Dropdown, Menu, message, Popconfirm, Tooltip } from 'antd';
@@ -25,8 +24,10 @@ import Export from './Export';
 import Import from './Import';
 import Process from './Process';
 import SearchComponent from '@/components/SearchComponent';
+import { ProTableCard } from '@/components';
 import SystemConst from '@/utils/const';
 import Token from '@/utils/token';
+import DeviceCard from '@/components/ProTableCard/CardItems/device';
 
 export const statusMap = new Map();
 statusMap.set('在线', 'success');
@@ -343,7 +344,7 @@ const Instance = () => {
           setSearchParams({});
         }}
       />
-      <ProTable<DeviceInstance>
+      <ProTableCard<DeviceInstance>
         columns={columns}
         actionRef={actionRef}
         params={searchParams}
@@ -387,6 +388,7 @@ const Instance = () => {
             <Button>批量操作</Button>
           </Dropdown>,
         ]}
+        cardRender={(item) => <DeviceCard {...item} />}
       />
       <Save
         data={current}