前置条件

在开发table页面之前,要确保已经在本地创建了基础前端项目。详见 新建项目

  • 页面编写
  • 配置路由
  • 页面访问

页面编写

在项目的react/src/app/demo/containers/organization(project, user, global)目录下新建一个新的功能文件夹table及其相关的JS文件。

1.编写index.js文件

  1. $ cd choerodon-todo-service
  2. $ mkdir -p react/src/app/demo/containers/organization/table
  3. $ touch react/src/app/demo/containers/organization/table/index.js
  1. // table/index.js
  2. import React, { Component } from 'react';
  3. import { observer } from 'mobx-react';
  4. import { Button, Table } from 'choerodon-ui';
  5. import { Action, Content, Header, Page } from '@choerodon/boot';
  6. import Store from './stores';
  7. @observer
  8. class TableDemo extends Component {
  9. componentDidMount() {
  10. this.loadData();
  11. }
  12. loadData = () => {
  13. Store.loadData();
  14. }
  15. renderLevel(text) {
  16. const LEVEL_MAP = {
  17. organization: '组织',
  18. project: '项目',
  19. };
  20. return LEVEL_MAP[text] || '全局';
  21. }
  22. renderTable = () => {
  23. const { isLoading, pagination } = Store;
  24. const columns = [
  25. {
  26. title: '名字',
  27. dataIndex: 'name',
  28. key: 'name',
  29. width: '25%',
  30. },
  31. {
  32. title: '编码',
  33. dataIndex: 'code',
  34. key: 'code',
  35. width: '25%',
  36. },
  37. {
  38. title: '层级',
  39. dataIndex: 'level',
  40. key: 'level'
  41. },
  42. {
  43. title: '状态',
  44. dataIndex: 'enabled',
  45. key: 'enabled',
  46. },
  47. {
  48. title: '',
  49. key: 'action',
  50. align: 'right',
  51. render: (text, record) => {
  52. const actionDatas = [{
  53. icon: '',
  54. type: 'site',
  55. text: '修改',
  56. }];
  57. if (record.enabled) {
  58. actionDatas.push({
  59. icon: '',
  60. type: 'site',
  61. text: '停用',
  62. });
  63. } else {
  64. actionDatas.push({
  65. icon: '',
  66. type: 'site',
  67. text: '启用',
  68. });
  69. }
  70. return <Action data={actionDatas} getPopupContainer={() => document.getElementsByClassName('page-content')[0]} />;
  71. },
  72. },
  73. ];
  74. return (
  75. <Table
  76. columns={columns}
  77. dataSource={Store.data.slice()}
  78. pagination={pagination}
  79. rowKey={record => record.id}
  80. onChange={this.handlePageChange}
  81. loading={isLoading}
  82. filterBarPlaceholder="过滤表"
  83. />
  84. );
  85. }
  86. render() {
  87. return (
  88. <Page className="choerodon-role">
  89. <Header title="表格演示">
  90. <Button
  91. onClick={this.handleRefresh}
  92. icon="refresh"
  93. >
  94. 刷新
  95. </Button>
  96. </Header>
  97. <Content
  98. title="标题"
  99. description="描述"
  100. link="#"
  101. >
  102. {this.renderTable()}
  103. </Content>
  104. </Page>
  105. );
  106. }
  107. }
  108. export default TableDemo;

2.编写store代码

  1. $ cd choerodon-todo-service
  2. $ mkdir -p react/src/app/demo/containers/organization/table/stores
  3. $ touch react/src/app/demo/containers/organization/table/stores/index.js
  4. $ touch react/src/app/demo/containers/organization/table/stores/Store.js
  1. // stores/index.js
  2. import Store from './Store';
  3. export default Store;
  1. // stores/Store.js
  2. import { action, computed, observable } from 'mobx';
  3. import { axios } from '@choerodon/boot';
  4. class Store {
  5. @observable data = [];
  6. @observable isLoading = true;
  7. @observable pagination = {
  8. current: 1,
  9. pageSize: 10,
  10. total: '',
  11. };
  12. @action
  13. setData(data) {
  14. this.data = data;
  15. }
  16. @action
  17. setIsLoading(data) {
  18. this.isLoading = data;
  19. }
  20. @computed
  21. get getData() {
  22. return this.data.slice();
  23. }
  24. @action
  25. loadData(page = this.pagination.current, size = this.pagination.pageSize) {
  26. const body = {};
  27. const sorter = [];
  28. this.isLoading = true;
  29. axios.post(
  30. `/iam/v1/roles/search?page=${page}&size=${size}&sort=${sorter.join(',')}`,
  31. JSON.stringify(body),
  32. )
  33. .then((res) => {
  34. this.isLoading = false;
  35. this.data = res.list;
  36. this.pagination = {
  37. current: res.pageNum,
  38. pageSize: res.pageSize,
  39. total: res.total,
  40. };
  41. });
  42. }
  43. }
  44. const store = new Store();
  45. export default store;

配置异步路由

修改react/src/app/demo/containers/DEMOIndex.js文件中配置新建文件的访问路径:

  1. // DEMOIndex.js
  2. import React from 'react';
  3. import { Route, Switch } from 'react-router-dom';
  4. import { inject } from 'mobx-react';
  5. import { asyncRouter, nomatch } from '@choerodon/boot';
  6. const HelloIndex = asyncRouter(() => import('./organization/hello'));
  7. const TableIndex = asyncRouter(() => import('./organization/table'));
  8. @inject('AppState')
  9. class DEMOIndex extends React.Component {
  10. render() {
  11. const { match, AppState } = this.props;
  12. return (
  13. <Switch>
  14. <Route path={`${match.url}/hello`} component={HelloIndex} />
  15. <Route path={`${match.url}/table`} component={TableIndex} />
  16. <Route path="*" component={nomatch} />
  17. </Switch>
  18. );
  19. }
  20. }
  21. export default DEMOIndex;

页面访问

本次demo的访问路径应该为: http://localhost:9090/#/demo/table

因为在编译自动收集路由配置时,本模块的路由被映射为/demo,也就是在package.json中设置的routeName字段。