2.1.5-beta2 • Published 28 days ago

@gdjiami/rc-components v2.1.5-beta2

Weekly downloads
197
License
MIT
Repository
-
Last release
28 days ago

React Components

React 组件库, 收集了工作宝中后台应用的常用组件或套件. 致力于减少应用开发的代码重复,提高维护效率

DEMO


Installation

yarn add @gdjiami/rc-components

# 依赖
yarn add react react-dom tslib react-router react-router-dom

Usage

所有组件都在es目录下, es 使用 ES6 模块系统,另外每目录下面都有 Typescript 声明文件,所以支持类型检查,开发者可以按需导入需要的组件

rc-components 支持类似于antd的按需加载方式,如果你使用 typescript 可以使用ts-import-plugin 插件, 例如:

// webpack.config.js
const tsImportPluginFactory = require('ts-import-plugin')

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.(jsx|tsx|js|ts)$/,
        loader: 'ts-loader',
        options: {
          transpileOnly: true,
          getCustomTransformers: () => ({
            before: [
              tsImportPluginFactory([
                // 按需导入antd组件
                {
                  libraryName: 'antd',
                  libraryDirectory: 'es',
                  style: 'css',
                },
                // 按需导入rc-components组件
                {
                  libraryName: '@gdjiami/rc-components',
                  libraryDirectory: 'es',
                  style: 'css',
                },
              ]),
            ],
          }),
        },
        exclude: /node_modules/,
      },
    ],
  },
  // ...
}

对于babel可以使用babel-plugin-import 插件

使用示例

import React from 'react'
import { Login } from '@gdjiami/rc-components'
import { message } from 'antd'
import { delay } from './utils'

export default class LoginPage extends React.Component {
  public render() {
    return (
      <Login
        title="登录页面"
        onSubmit={this.handleSubmit}
        onSuccess={this.handleSuccess}
      />
    )
  }

  private handleSubmit = async () => {
    await delay(2000)
  }

  private handleSuccess = () => {
    message.success('登录成功')
  }
}

定位

rc-components 是基于 antd 组件库之上的高层组件库,旨在抽象重复的业务场景, 减少代码重复。其中耦合的东西有:

  • antd
  • react, react-dom
  • tslib
  • react-router v4
  • lodash

这些耦合的技术是 rc-components 的构建基础,而且在团队内的应用是比较稳定的、静态的,近期不会有大的变动。相对的,有些东西是我们 要避免耦合的:

  • 状态管理库,如 mobx,redux.
  • Ajax 请求库
  • 前端路由类型

Components

这里列举各组件的使用方法和注意事项

  • Title

    用于修改浏览器 title
import { Title } from '@gdjiami/rc-components'
import React, { FC } from 'react'

export const Page: FC = (props) => {
  return <Title>系统管理</Title>
}
  • AdminLayout

    后台应用布局组件 AdminLayout 为顶层父组件,其子组件分别有

    1. AdminLayout.Action 位于顶部的右边展示? (当前用户)
    2. AdminLayout.View 次顶层视图层,全局最外层用一次
    3. AdminLayout.HeaderBar
    4. AdminLayout.Footer 底部
    5. AdminLayout.Body 内容层,当业务页面用这个组件,其内容会按 AdminLayout 布局正确展示

    AdminLayout 常用参数(包括但不限于): | 参数 | 格式 | 用途| | ---- | ---- | ---- | | siteName | string | 应用名称 | logo | string | 应用图标 | menus | () => Promise<MenuConfig[]>) | MenuConfig[] | 菜单列表 | after | React.ReactNode | 头部右侧内容

    // layout.tsx
    
    <AdminLayout
      siteName="后台管理系统"
      title={<Title.Display breadcrumb inline />}
      menus={[]}
      after={
          <Dropdown
            overlay={
              <Menu>
                <Menu.Item key="resetPassword">修改密码</Menu.Item>
                <Menu.Item key="logout">安全退出</Menu.Item>
              </Menu>
            }
          >
            <AdminLayout.Action>用户名</AdminLayout.Action>
          </Dropdown>
      }
    >
      <AdminLayout.View>
        {props.children}
        <AdminLayout.Footer>Version</AdminLayout.Footer>
      </AdminLayout.View>
    </AdminLayout>

    AdminLayout.Body 一般用于业务子页面,里面直接添加页面内容

    <AdminLayout.Body>
      <title>应用管理</title>
      <FatTable
        enableSelect
        enablePersist="{false}"
        columns="{column}"
        header="{renderHeader}"
        headerExtra="{renderHeaderExtra}"
        onRemove="{handleRemove}"
        onFetch="{handleFetch}"
        onAction="{handleAction}"
      />
    </AdminLayout.Body>
  • FatTable

    后台应用表格组件,高频组件之一,集成了翻页,搜索,多选,上移下移等基础功能。 FatTable 子组件有

    1. FatTable.Actions 表格项功能按钮组,下为其子组件
    2. FatTable.Action 表格项功能按钮

FatTable 常用参数(仅列举了常用,更多请查看源码): | 参数 | 格式 | 用途| | ---- | ---- | ---- | | enableSelect | boolean | 是否开启可选 | enablePagination | boolean | 是否开启翻页 | onFetch | FetchHandler | 获取表格数据的方法(翻页搜索均调用此方法) | header | HeaderRenderer | 表格头部内容 (一般为搜索功能) | headerExtra | HeaderExtraRenderer | 表格头部额外内容 (一般表格功能按钮,导出、导出、删除、添加等) | columns | ColumnsType | 列表数据展示 | idKey | string | 列表项的 key (如没有唯一的值可手动构造) | className | string | 定义类名 | onShift | ShiftHandler | 顺序发生改变所调用的回调 | onRemove | RemoveHandler | 列表项删除所调用的回调 | onAction | ActionHandler | 操作表格的统一方法

// 直接用就好啦
<FatTable
  enableSelect
  columns="{column}"
  header="{renderHeader}"
  headerExtra="{renderHeaderExtra}"
  onRemove="{handleRemove}"
  onFetch="{handleFetch}"
  onAction="{handleAction}"
/>

onAction 使用方法 和表格交互的重要途径

// 示例内容
import { FatTable } from '@gdjiami/rc-components'
import { ColumnsType} from '@gdjiami/rc-components/es/fat-table'

const AppStore: FC = () => {
  const { getDownloadUrl } = useRootModel()
  const column: ColumnsType<T, P> = [
    {
      title: '示例内容', // 列的标题
      width: 80,
      render: r => ( // 自定义展示内容 没有则展示dataIndex字段
        <span>
          自定义的展示内容{r.logo}
        </span>
      )
    },
    {
      title: '示例内容2',
      dataIndex: 'downloadUrl',
    },
    {
      title: '操作',
      width: 180,
      render: (r, _, t) => {
        // t.triggerAction('toggleOpen', r) 来触发handleAction 可传入 action类型和数据
        // t.remove([r.id]) 来执行删除项的请求等方法
        return (
          <FatTable.Actions className="Container__TagGroup">
            <FatTable.Action onClick={() => t.remove([r.id])}>
              删除
            </FatTable.Action>
            <FatTable.Action onClick={() => t.triggerAction('actionType', r)}>
              启用
            </FatTable.Action>
          </FatTable.Actions>
        )
      }
    }
  ]

 const handleAction = (async (name, data, t) => {
    switch (name) {
      case 'actionType':
        // do something
        break
    }
  }

  return (
      <FatTable
        enableSelect
        enablePersist={false}
        columns={column}
        header={renderHeader}
        headerExtra={renderHeaderExtra}
        onRemove={handleRemove}
        onFetch={handleFetch}
        onAction={handleAction}
      />
  )
}
  • UserSelect

    员工选择的组件 首先在路由定义处使用 UserSelectProvider,为有需要使用的路由提供组件服务。
import { UserSelectProvider } from '@gdjiami/rc-components/es/user-select'

;<UserSelectProvider adaptor={adaptor}>
  <Route path="/static" exact component={Comp} />
</UserSelectProvider>

随后需定义 UserSelectAdaptor.tsx(一般和 Route.tsx 同层)

import {
  UserSelectAdaptor,
  DepartmentDesc,
  UserDesc,
  TenementDesc,
} from '@gdjiami/rc-components/es/user-select'
import { DepartmentSearchResult } from '@gdjiami/rc-components/es/user-select/Provider'
import rpc from '~/rpc'

interface DepartmentTreeItem {
  children?: DepartmentTreeItem[]
  departmentId: string
  departmentName: string
  tenementId: string
  fullPath: string
  parentIds: string[]
}

const Adaptor: UserSelectAdaptor = {
  /**
   * 获取部门树
   */
  async getDepartmentTree(tenementId: string): Promise<DepartmentDesc> {
    const res = await rpc.request<{ items: DepartmentTreeItem[] }>(
      'org.department.getTree',
      {
        tenementId,
        fetchFullPath: true,
      },
    )
    const items = res.items.map(
      ({ departmentId: id, departmentName: name, ...others }) =>
        ({ id, name, ...others } as DepartmentDesc),
    )
    return items[0]
  },

  async getDepartmentChildren(tenementId: string, departmentId: string) {
    const res = await rpc.request<{ items: DepartmentTreeItem[] }>(
      'org.department.getTree',
      {
        tenementId,
        parentId: departmentId,
        fetchFullPath: true,
      },
    )
    const items = res.items.map(
      ({ departmentId: id, departmentName: name, ...others }) =>
        ({ id, name, ...others } as DepartmentDesc),
    )
    return items
  },

  /**
   * 获取部门成员
   */
  async getDepartmentUsers(
    tenementId: string,
    departmentId: string,
    page: number,
    pageSize: number,
  ): Promise<{ items: UserDesc[]; total: number }> {
    return { items: [], total: 0 }
  },

  /**
   * 用户搜索
   * tenementId不为空时,表示企业内搜索
   */
  async searchUser(
    query: string,
    page: number,
    pageSize: number,
    tenementId?: string,
  ): Promise<{ items: UserDesc[]; total: number }> {
    const params = {
      key: query,
      startIndex: (page - 1) * pageSize,
      resultRows: pageSize,
      tenementId,
    }
    const res = await rpc.request<{
      items: Array<UserDesc & { userId: string }>
      totalItems: number
    }>('user.search', params)
    return {
      items: res.items.map((i) => ({ ...i, id: i.userId })),
      total: res.totalItems,
    }
  },

  /**
   * 企业搜索
   */
  async searchTenement(
    query: string,
    page: number,
    pageSize: number,
  ): Promise<{ items: TenementDesc[]; total: number }> {
    const params = {
      searchKey: query,
      startIndex: (page - 1) * pageSize,
      resultRows: pageSize,
    }
    const res = await rpc.request<{
      items: Array<{ tenementId: string; tenementName: string }>
      totalItems: number
    }>('tenement.lists', params)
    return {
      items: res.items.map((item) => {
        const { tenementId, tenementName } = item
        return { id: tenementId, name: tenementName, extra: item }
      }),
      total: res.totalItems,
    }
  },

  async searchDepartment(
    query: string,
    page: number,
    pageSize: number,
    tenementId?: string,
  ) {
    const res = await rpc.request<{
      items: Array<{
        userCount: string
        parentId: string
        parentIds: string[]
        leaf: boolean
        departmentId: string
        departmentName: string
      }>
      totalItems: number
    }>('org.department.search', {
      tenementId,
      key: query,
      startIndex: (page - 1) * pageSize,
      resultRows: pageSize,
      fetchFullPath: true,
    })

    return {
      items: res.items.map(
        (i) =>
          ({
            ...i,
            id: i.departmentId,
            name: i.departmentName,
          } as DepartmentSearchResult),
      ),
      total: res.totalItems,
    }
  },

  async normalizeDepartmentChecked(
    currentSelected: DepartmentDesc[],
    added: DepartmentDesc[],
    removed: DepartmentDesc[],
  ): Promise<DepartmentSearchResult[]> {
    const map = (i: DepartmentDesc) => ({
      tenementId: i.tenement!.id,
      departmentId: i.id,
    })
    const params = {
      currentItems: currentSelected.map(map),
      addItems: added.map(map),
      delItems: removed.map(map),
    }
    const res = await rpc.request<{
      currentItems: Array<{
        userCount: string
        parentId: string
        parentIds: string[]
        leaf: boolean
        departmentId: string
        departmentName: string
      }>
    }>('org.department.selectedChange', params)
    return res.currentItems.map(
      (i) =>
        ({
          ...i,
          id: i.departmentId,
          name: i.departmentName,
        } as DepartmentSearchResult),
    )
  },

  async getDepartmentDetail(
    ids: string[],
    tenementId?: string,
  ): Promise<DepartmentSearchResult[]> {
    const params = {
      items: ids.map((i) => ({ tenementId, departmentId: i })),
    }
    const res = await rpc.request<{
      items: Array<{
        userCount: string
        parentId: string
        parentIds: string[]
        leaf: boolean
        departmentId: string
        departmentName: string
      }>
    }>('org.department.getDepartmentInfo', params)
    return res.items.map(
      (i) =>
        ({
          ...i,
          id: i.departmentId,
          name: i.departmentName,
        } as DepartmentSearchResult),
    )
  },
}

export default Adaptor

Demo

run: yarn parcel -- ./components/AdminLayout/example/index.html

License

This project is licensed under the terms of the MIT license.

2.1.5-beta2

28 days ago

0.5.6

29 days ago

2.1.5-beta1

1 month ago

2.1.5

1 month ago

2.1.4-beta9

2 months ago

2.1.4-beta8

2 months ago

2.1.4-beta7

2 months ago

2.1.4-beta6

2 months ago

2.1.4-beta4

2 months ago

2.1.4-beta2

3 months ago

2.1.4-beta3

3 months ago

2.1.4-beta1

3 months ago

2.1.4

3 months ago

2.1.3-beta8

3 months ago

2.1.3-beta7

3 months ago

2.1.3-beta5

3 months ago

2.1.3-beta6

3 months ago

2.1.3-beta4

4 months ago

2.1.3-beta3

4 months ago

2.1.3-beta2

4 months ago

2.1.3-beta1

4 months ago

2.1.3

4 months ago

2.1.2-beta9

4 months ago

2.1.2-beta8

4 months ago

2.1.2-beta7

4 months ago

2.1.2-beta5

4 months ago

2.1.2-beta4

4 months ago

2.1.2-beta6

4 months ago

2.1.2-beta1

5 months ago

2.1.2-beta3

4 months ago

2.1.2-beta2

4 months ago

2.1.2

5 months ago

2.1.1-beta4

5 months ago

2.1.1-beta3

5 months ago

2.1.1-beta2

5 months ago

2.1.1-beta1

5 months ago

2.1.1-beta6

5 months ago

2.1.1-beta5

5 months ago

2.1.1

5 months ago

2.1.0-beta5

5 months ago

2.1.0-beta4

5 months ago

2.1.0-beta6

5 months ago

2.1.0-beta3

5 months ago

2.1.0-beta2

5 months ago

2.1.0-beta1

5 months ago

2.1.0

5 months ago

2.0.9-beta9

5 months ago

2.0.9-beta8

5 months ago

2.0.9-beta7

5 months ago

2.0.9-beta6

5 months ago

2.0.9-beta5

5 months ago

2.0.9-beta4

5 months ago

2.0.9-beta3

5 months ago

2.0.9-beta2

5 months ago

2.0.9-beta1

5 months ago

0.4.29

10 months ago

2.0.6-beta1

7 months ago

2.0.6-beta2

6 months ago

2.0.6-beta3

6 months ago

2.0.6-beta4

6 months ago

2.0.6-beta5

6 months ago

2.0.6-beta6

6 months ago

2.0.6-beta7

6 months ago

2.0.0-beta3

10 months ago

2.0.0-beta4

10 months ago

2.0.0-beta1

10 months ago

2.0.0-beta2

10 months ago

0.5.4

7 months ago

0.5.3

7 months ago

0.5.5

7 months ago

0.5.0

10 months ago

0.5.2

9 months ago

0.5.1

10 months ago

2.0.7-beta10

6 months ago

2.0.5-beta1

7 months ago

2.0.5-beta14

7 months ago

2.0.5-beta13

7 months ago

2.0.7-beta11

6 months ago

2.0.5-beta10

7 months ago

2.0.5-beta12

7 months ago

2.0.5-beta11

7 months ago

2.0.5-beta8

7 months ago

2.0.5-beta9

7 months ago

2.0.5-beta6

7 months ago

2.0.5-beta7

7 months ago

2.0.5-beta4

7 months ago

2.0.5-beta5

7 months ago

2.0.5-beta2

7 months ago

2.0.5-beta3

7 months ago

2.0.3

9 months ago

2.0.2

9 months ago

2.0.5

7 months ago

2.0.4

8 months ago

2.0.7

6 months ago

2.0.6

7 months ago

2.0.9

5 months ago

2.0.8-beta10

5 months ago

2.0.8

6 months ago

2.0.1

9 months ago

2.0.3-beta7

8 months ago

2.0.3-beta6

8 months ago

2.0.3-beta5

8 months ago

2.0.3-beta3

8 months ago

2.0.3-beta2

9 months ago

2.0.3-beta1

9 months ago

2.0.4-beta7

8 months ago

2.0.4-beta4

8 months ago

2.0.4-beta3

8 months ago

2.0.4-beta6

8 months ago

2.0.4-beta2

8 months ago

2.0.4-beta1

8 months ago

2.0.7-beta2

6 months ago

2.0.7-beta3

6 months ago

2.0.7-beta1

6 months ago

2.0.7-beta6

6 months ago

2.0.7-beta7

6 months ago

2.0.7-beta4

6 months ago

2.0.7-beta5

6 months ago

2.0.7-beta8

6 months ago

2.0.7-beta9

6 months ago

0.4.13-beta2

6 months ago

0.4.13-beta1

6 months ago

2.0.8-beta7

6 months ago

2.0.8-beta8

6 months ago

2.0.8-beta9

6 months ago

2.0.8-beta3

6 months ago

2.0.8-beta4

6 months ago

2.0.8-beta5

6 months ago

2.0.8-beta6

6 months ago

2.0.8-beta1

6 months ago

2.0.8-beta2

6 months ago

0.4.27-beta1

2 years ago

0.4.27-beta3

2 years ago

0.4.27-beta2

2 years ago

0.4.27-beta4

2 years ago

0.4.28

2 years ago

0.4.27

2 years ago

0.4.26

2 years ago

0.4.24

2 years ago

0.4.25

2 years ago

0.4.23

2 years ago

0.4.22-beta11

2 years ago

0.4.22-beta10

2 years ago

0.4.22-beta9

3 years ago

0.4.22-beta8

3 years ago

0.4.22-beta7

3 years ago

0.4.22-beta6

3 years ago

0.4.22-beta5

3 years ago

0.4.22-beta4

3 years ago

0.4.22-beta2

3 years ago

0.4.22-beta3

3 years ago

0.4.22-beta

3 years ago

0.4.21

3 years ago

0.4.21-beta4

3 years ago

0.4.21-beta3

3 years ago

0.4.21-beta2

3 years ago

0.4.20

3 years ago

0.4.21-beta

3 years ago

0.4.19

3 years ago

0.4.18

3 years ago

0.4.17

3 years ago

0.4.16

3 years ago

0.4.15

3 years ago

0.4.14

3 years ago

0.4.13

4 years ago

0.4.12

4 years ago

0.4.11

4 years ago

0.4.10

4 years ago

0.4.9

4 years ago

0.4.8

4 years ago

0.4.7

4 years ago

0.4.6

4 years ago

0.4.5

4 years ago

0.4.4

4 years ago

0.4.3

4 years ago

0.4.2

4 years ago

0.4.1

4 years ago

0.4.0

4 years ago

0.3.5

4 years ago

0.3.4

4 years ago

0.3.2

4 years ago

0.3.3

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.34

4 years ago

0.2.33

4 years ago

0.2.32

4 years ago

0.2.31

4 years ago

0.2.30

4 years ago

0.2.29

4 years ago

0.2.28

4 years ago

0.2.27

4 years ago

0.2.26

4 years ago

0.2.24

4 years ago

0.2.23

4 years ago

0.2.22

4 years ago

0.2.21

4 years ago

0.2.20

5 years ago

0.2.19

5 years ago

0.2.18

5 years ago

0.2.17

5 years ago

0.2.16

5 years ago

0.2.15

5 years ago

0.2.14

5 years ago

0.2.13

5 years ago

0.2.12

5 years ago

0.2.11

5 years ago

0.2.10

5 years ago

0.2.9

5 years ago

0.2.8

5 years ago

0.2.7

5 years ago

0.2.6

5 years ago

0.2.5

5 years ago

0.2.4

5 years ago

0.2.3

5 years ago

0.2.2

5 years ago

0.2.1

5 years ago

0.2.0

5 years ago

0.1.54

5 years ago

0.1.53

5 years ago

0.1.52

5 years ago

0.1.51

5 years ago

0.1.50

5 years ago

0.1.48

5 years ago

0.1.47

5 years ago

0.1.46

5 years ago

0.1.45

5 years ago

0.1.44

5 years ago

0.1.43

5 years ago

0.1.42

5 years ago

0.1.41

5 years ago

0.1.40

5 years ago

0.1.39

5 years ago

0.1.38

5 years ago

0.1.37

5 years ago

0.1.36

5 years ago

0.1.35

5 years ago

0.1.34

5 years ago

0.1.33

5 years ago

0.1.32

5 years ago

0.1.31

5 years ago

0.1.30

5 years ago

0.1.29

5 years ago

0.1.28

5 years ago

0.1.27

5 years ago

0.1.26

5 years ago

0.1.25

5 years ago

0.1.24

5 years ago

0.1.22

6 years ago

0.1.21

6 years ago

0.1.20

6 years ago

0.1.19

6 years ago

0.1.17

6 years ago

0.1.16

6 years ago

0.1.15

6 years ago

0.1.14

6 years ago

0.1.13

6 years ago

0.1.12

6 years ago

0.1.11

6 years ago

0.1.10

6 years ago

0.1.9

6 years ago

0.1.8

6 years ago

0.1.7

6 years ago

0.1.6

6 years ago

0.1.5

6 years ago

0.1.4

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago