diff --git a/SearchListApplications/src/_mock.js b/SearchListApplications/src/_mock.ts
similarity index 100%
rename from SearchListApplications/src/_mock.js
rename to SearchListApplications/src/_mock.ts
diff --git a/SearchListApplications/src/components/PageHeaderWrapper/index.js b/SearchListApplications/src/components/PageHeaderWrapper/index.js
deleted file mode 100644
index 1a40e25dfdc97a4e69407cbf1516e15ad65bd00b..0000000000000000000000000000000000000000
--- a/SearchListApplications/src/components/PageHeaderWrapper/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import { FormattedMessage } from 'umi-plugin-react/locale';
-import Link from 'umi/link';
-import { PageHeader } from 'ant-design-pro';
-import styles from './index.less';
-
-const PageHeaderWrapper = ({ children, wrapperClassName, ...restProps }) => (
-
- }
- key="pageheader"
- {...restProps}
- linkElement={Link}
- itemRender={item => {
- if (item.locale) {
- return
;
- }
- return item.title;
- }}
- />
- {children ?
{children}
: null}
-
-);
-
-export default PageHeaderWrapper;
diff --git a/SearchListApplications/src/components/PageHeaderWrapper/index.less b/SearchListApplications/src/components/PageHeaderWrapper/index.less
index 39a449657a98b039c29e6654fd117267cbb5283a..908db575ae9f0a0cd75d04952ba4f37b3002da42 100644
--- a/SearchListApplications/src/components/PageHeaderWrapper/index.less
+++ b/SearchListApplications/src/components/PageHeaderWrapper/index.less
@@ -1,11 +1,86 @@
@import '~antd/lib/style/themes/default.less';
-.content {
+.children-content {
margin: 24px 24px 0;
}
-@media screen and (max-width: @screen-sm) {
+.main {
+ .detail {
+ display: flex;
+ }
+
+ .row {
+ display: flex;
+ width: 100%;
+ }
+
+ .title-content {
+ margin-bottom: 16px;
+ }
+
+ @media screen and (max-width: @screen-sm) {
+ .content {
+ margin: 24px 0 0;
+ }
+ }
+
+ .title,
.content {
- margin: 24px 0 0;
+ flex: auto;
+ }
+
+ .extraContent,
+ .main {
+ flex: 0 1 auto;
+ }
+
+ .main {
+ width: 100%;
+ }
+
+ .title {
+ margin-bottom: 16px;
+ }
+
+ .logo,
+ .content,
+ .extraContent {
+ margin-bottom: 16px;
+ }
+
+ .extraContent {
+ min-width: 242px;
+ margin-left: 88px;
+ text-align: right;
+ }
+}
+
+@media screen and (max-width: @screen-xl) {
+ .extraContent {
+ margin-left: 44px;
+ }
+}
+
+@media screen and (max-width: @screen-lg) {
+ .extraContent {
+ margin-left: 20px;
+ }
+}
+
+@media screen and (max-width: @screen-md) {
+ .row {
+ display: block;
+ }
+
+ .action,
+ .extraContent {
+ margin-left: 0;
+ text-align: left;
+ }
+}
+
+@media screen and (max-width: @screen-sm) {
+ .detail {
+ display: block;
}
}
diff --git a/SearchListApplications/src/components/PageHeaderWrapper/index.tsx b/SearchListApplications/src/components/PageHeaderWrapper/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..fe1a33b8a4fa0759d759c01304484d9eee5e7986
--- /dev/null
+++ b/SearchListApplications/src/components/PageHeaderWrapper/index.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import { RouteContext } from '@ant-design/pro-layout';
+import { PageHeader, Typography } from 'antd';
+import styles from './index.less';
+import { GridContent } from '@ant-design/pro-layout';
+
+interface IPageHeaderWrapperProps {
+ content?: React.ReactNode;
+ title: React.ReactNode;
+ extraContent?: React.ReactNode;
+}
+
+const PageHeaderWrapper: React.SFC = ({
+ children,
+ title,
+ content,
+ extraContent,
+ ...restProps
+}) => (
+
+ {value => (
+
+
+ {title}
+
+ }
+ {...restProps}
+ {...value}
+ >
+
+
+
+ {content &&
{content}
}
+ {extraContent &&
{extraContent}
}
+
+
+
+
+ {children ? (
+
+ {children}
+
+ ) : null}
+
+ )}
+
+);
+
+export default PageHeaderWrapper;
diff --git a/SearchListApplications/src/components/StandardFormRow/index.js b/SearchListApplications/src/components/StandardFormRow/index.tsx
similarity index 67%
rename from SearchListApplications/src/components/StandardFormRow/index.js
rename to SearchListApplications/src/components/StandardFormRow/index.tsx
index 8cb0e444e6d488ae4cdfeceb8eb94ee4adbb9248..01a8bb5dabd9f232d14b6186c74909de407dfcb0 100644
--- a/SearchListApplications/src/components/StandardFormRow/index.js
+++ b/SearchListApplications/src/components/StandardFormRow/index.tsx
@@ -2,7 +2,22 @@ import React from 'react';
import classNames from 'classnames';
import styles from './index.less';
-const StandardFormRow = ({ title, children, last, block, grid, ...rest }) => {
+interface StandardFormRowProps {
+ title?: string;
+ last?: boolean;
+ block?: boolean;
+ grid?: boolean;
+ style?: React.CSSProperties;
+}
+
+const StandardFormRow: React.SFC = ({
+ title,
+ children,
+ last,
+ block,
+ grid,
+ ...rest
+}) => {
const cls = classNames(styles.standardFormRow, {
[styles.standardFormRowBlock]: block,
[styles.standardFormRowLast]: last,
diff --git a/SearchListApplications/src/components/TagSelect/index.less b/SearchListApplications/src/components/TagSelect/index.less
new file mode 100644
index 0000000000000000000000000000000000000000..93694653133b449b2e6447d0b4aa20ae6d2823b4
--- /dev/null
+++ b/SearchListApplications/src/components/TagSelect/index.less
@@ -0,0 +1,33 @@
+@import '~antd/lib/style/themes/default.less';
+
+.tagSelect {
+ position: relative;
+ max-height: 32px;
+ margin-left: -8px;
+ overflow: hidden;
+ line-height: 32px;
+ transition: all 0.3s;
+ user-select: none;
+ :global {
+ .ant-tag {
+ margin-right: 24px;
+ padding: 0 8px;
+ font-size: @font-size-base;
+ }
+ }
+ &.expanded {
+ max-height: 200px;
+ transition: all 0.3s;
+ }
+ .trigger {
+ position: absolute;
+ top: 0;
+ right: 0;
+ i {
+ font-size: 12px;
+ }
+ }
+ &.hasExpandTag {
+ padding-right: 50px;
+ }
+}
diff --git a/SearchListApplications/src/components/TagSelect/index.tsx b/SearchListApplications/src/components/TagSelect/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..96416a4b96b762e81def938dbef7c1754ea82dc6
--- /dev/null
+++ b/SearchListApplications/src/components/TagSelect/index.tsx
@@ -0,0 +1,169 @@
+import React, { Component } from 'react';
+import classNames from 'classnames';
+import { Tag, Icon } from 'antd';
+
+import styles from './index.less';
+
+const { CheckableTag } = Tag;
+
+export interface TagSelectOptionProps {
+ value?: string | number;
+ style?: React.CSSProperties;
+ checked?: boolean;
+ onChange?: (value: string | number | undefined, state: boolean) => void;
+}
+
+export interface TagSelectProps {
+ onChange?: (value: (string | number)[]) => void;
+ expandable?: boolean;
+ value?: (string | number)[];
+ defaultValue?: (string | number)[];
+ style?: React.CSSProperties;
+ hideCheckAll?: boolean;
+ actionsText?: {
+ expandText?: React.ReactNode;
+ collapseText?: React.ReactNode;
+ selectAllText?: React.ReactNode;
+ };
+ className?: string;
+ Option?: TagSelectOptionProps;
+ children?: React.ReactElement | Array>;
+}
+
+const TagSelectOption: React.SFC & {
+ isTagSelectOption: boolean;
+} = ({ children, checked, onChange, value }) => (
+ onChange && onChange(value, state)}
+ >
+ {children}
+
+);
+
+TagSelectOption.isTagSelectOption = true;
+
+interface TagSelectState {
+ expand: boolean;
+ value: (string | number)[];
+}
+
+class TagSelect extends Component {
+ static defaultProps = {
+ hideCheckAll: false,
+ actionsText: {
+ expandText: 'Expand',
+ collapseText: 'Collapse',
+ selectAllText: 'All',
+ },
+ };
+ static Option: TagSelectOption = TagSelectOption;
+ constructor(props: TagSelectProps) {
+ super(props);
+ this.state = {
+ expand: false,
+ value: props.value || props.defaultValue || [],
+ };
+ }
+
+ static getDerivedStateFromProps(nextProps: TagSelectProps) {
+ if ('value' in nextProps) {
+ return { value: nextProps.value || [] };
+ }
+ return null;
+ }
+
+ onChange = (value: (string | number)[]) => {
+ const { onChange } = this.props;
+ if (!('value' in this.props)) {
+ this.setState({ value });
+ }
+ if (onChange) {
+ onChange(value);
+ }
+ };
+
+ onSelectAll = (checked: boolean) => {
+ let checkedTags: (string | number)[] = [];
+ if (checked) {
+ checkedTags = this.getAllTags();
+ }
+ this.onChange(checkedTags);
+ };
+
+ getAllTags() {
+ let { children } = this.props;
+ const childrenArray = React.Children.toArray(children) as React.ReactElement[];
+ const checkedTags = childrenArray
+ .filter(child => this.isTagSelectOption(child))
+ .map(child => child.props.value);
+ return checkedTags || [];
+ }
+
+ handleTagChange = (value: string | number, checked: boolean) => {
+ const { value: StateValue } = this.state;
+ const checkedTags: (string | number)[] = [...StateValue];
+
+ const index = checkedTags.indexOf(value);
+ if (checked && index === -1) {
+ checkedTags.push(value);
+ } else if (!checked && index > -1) {
+ checkedTags.splice(index, 1);
+ }
+ this.onChange(checkedTags);
+ };
+
+ handleExpand = () => {
+ const { expand } = this.state;
+ this.setState({
+ expand: !expand,
+ });
+ };
+
+ isTagSelectOption = (node: React.ReactElement) =>
+ node &&
+ node.type &&
+ (node.type.isTagSelectOption || node.type.displayName === 'TagSelectOption');
+
+ render() {
+ const { value, expand } = this.state;
+ const { children, hideCheckAll, className, style, expandable, actionsText = {} } = this.props;
+ const checkedAll = this.getAllTags().length === value.length;
+ const { expandText = 'Expand', collapseText = 'Collapse', selectAllText = 'All' } = actionsText;
+
+ const cls = classNames(styles.tagSelect, className, {
+ [styles.hasExpandTag]: expandable,
+ [styles.expanded]: expand,
+ });
+
+ return (
+
+ {hideCheckAll ? null : (
+
+ {selectAllText}
+
+ )}
+ {value &&
+ React.Children.map(children, (child: React.ReactElement
) => {
+ if (this.isTagSelectOption(child)) {
+ return React.cloneElement(child, {
+ key: `tag-select-${child.props.value}`,
+ value: child.props.value,
+ checked: value.indexOf(child.props.value) > -1,
+ onChange: this.handleTagChange,
+ });
+ }
+ return child;
+ })}
+ {expandable && (
+
+ {expand ? collapseText : expandText}
+
+ )}
+
+ );
+ }
+}
+
+export default TagSelect;
diff --git a/SearchListApplications/src/data.d.ts b/SearchListApplications/src/data.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6a4a88ce1a0c1b9d32dd8a5925828858d27cc0b4
--- /dev/null
+++ b/SearchListApplications/src/data.d.ts
@@ -0,0 +1,29 @@
+export interface Member {
+ avatar: string;
+ name: string;
+ id: string;
+}
+
+export interface ListItemDataType {
+ id: string;
+ owner: string;
+ title: string;
+ avatar: string;
+ cover: string;
+ status: 'normal' | 'exception' | 'active' | 'success';
+ percent: number;
+ logo: string;
+ href: string;
+ body?: any;
+ updatedAt: number;
+ createdAt: number;
+ subDescription: string;
+ description: string;
+ activeUser: number;
+ newUser: number;
+ star: number;
+ like: number;
+ message: number;
+ content: string;
+ members: Member[];
+}
diff --git a/SearchListApplications/src/index.js b/SearchListApplications/src/index.js
deleted file mode 100644
index 5de54a0853159cff604673c3fbb37ef986bfefce..0000000000000000000000000000000000000000
--- a/SearchListApplications/src/index.js
+++ /dev/null
@@ -1,213 +0,0 @@
-import React, { PureComponent } from 'react';
-import numeral from 'numeral';
-import { connect } from 'dva';
-import {
- Row,
- Col,
- Form,
- Card,
- Select,
- Icon,
- Avatar,
- List,
- Tooltip,
- Dropdown,
- Menu,
- Input,
-} from 'antd';
-import { TagSelect } from 'ant-design-pro';
-
-import StandardFormRow from './components/StandardFormRow';
-import PageHeaderWrapper from './components/PageHeaderWrapper';
-import { formatWan } from './utils/utils';
-import styles from './style.less';
-
-const { Option } = Select;
-const FormItem = Form.Item;
-
-@connect(({ BLOCK_NAME_CAMEL_CASE, loading }) => ({
- BLOCK_NAME_CAMEL_CASE,
- loading: loading.models.BLOCK_NAME_CAMEL_CASE,
-}))
-@Form.create({
- onValuesChange({ dispatch }, changedValues, allValues) {
- // 表单项变化时请求数据
- // eslint-disable-next-line
- console.log(changedValues, allValues);
- // 模拟查询表单生效
- dispatch({
- type: 'BLOCK_NAME_CAMEL_CASE/fetch',
- payload: {
- count: 8,
- },
- });
- },
-})
-class PAGE_NAME_UPPER_CAMEL_CASE extends PureComponent {
- componentDidMount() {
- const { dispatch } = this.props;
- dispatch({
- type: 'BLOCK_NAME_CAMEL_CASE/fetch',
- payload: {
- count: 8,
- },
- });
- }
-
- render() {
- const {
- BLOCK_NAME_CAMEL_CASE: { list },
- loading,
- form,
- } = this.props;
- const { getFieldDecorator } = form;
-
- const CardInfo = ({ activeUser, newUser }) => (
-
- );
-
- const formItemLayout = {
- wrapperCol: {
- xs: { span: 24 },
- sm: { span: 16 },
- },
- };
-
- const itemMenu = (
-
- );
-
- const mainSearch = (
-
-
-
- );
-
- return (
-
-
-
-
-
-
(
-
-
-
- ,
-
-
- ,
-
-
- ,
-
-
- ,
- ]}
- >
- }
- title={item.title}
- />
-
-
-
-
-
- )}
- />
-
-
- );
- }
-}
-
-export default PAGE_NAME_UPPER_CAMEL_CASE;
diff --git a/SearchListApplications/src/index.tsx b/SearchListApplications/src/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5160d0d0cbe4e8c9083a7678ca4f07c9a6da7826
--- /dev/null
+++ b/SearchListApplications/src/index.tsx
@@ -0,0 +1,212 @@
+import React, { Component } from 'react';
+import numeral from 'numeral';
+import { connect } from 'dva';
+import {
+ Row,
+ Col,
+ Form,
+ Card,
+ Select,
+ Icon,
+ Avatar,
+ List,
+ Tooltip,
+ Dropdown,
+ Menu,
+ Input,
+} from 'antd';
+import TagSelect from './components/TagSelect';
+import StandardFormRow from './components/StandardFormRow';
+import PageHeaderWrapper from './components/PageHeaderWrapper';
+import { formatWan } from './utils/utils';
+import styles from './style.less';
+import { IStateType } from './model';
+import { Dispatch } from 'redux';
+import { FormComponentProps } from 'antd/lib/form';
+import { ListItemDataType } from './data';
+
+const { Option } = Select;
+const FormItem = Form.Item;
+
+interface PAGE_NAME_UPPER_CAMEL_CASEProps extends FormComponentProps {
+ dispatch: Dispatch;
+ BLOCK_NAME_CAMEL_CASE: IStateType;
+ loading: boolean;
+}
+
+@connect(
+ ({
+ BLOCK_NAME_CAMEL_CASE,
+ loading,
+ }: {
+ BLOCK_NAME_CAMEL_CASE: IStateType;
+ loading: { models: { [key: string]: boolean } };
+ }) => ({
+ BLOCK_NAME_CAMEL_CASE,
+ loading: loading.models.BLOCK_NAME_CAMEL_CASE,
+ })
+)
+class PAGE_NAME_UPPER_CAMEL_CASE extends Component {
+ componentDidMount() {
+ const { dispatch } = this.props;
+ dispatch({
+ type: 'BLOCK_NAME_CAMEL_CASE/fetch',
+ payload: {
+ count: 8,
+ },
+ });
+ }
+
+ render() {
+ const {
+ BLOCK_NAME_CAMEL_CASE: { list },
+ loading,
+ form,
+ } = this.props;
+ const { getFieldDecorator } = form;
+
+ const CardInfo: React.SFC<{
+ activeUser: React.ReactNode;
+ newUser: React.ReactNode;
+ }> = ({ activeUser, newUser }) => (
+
+ );
+
+ const formItemLayout = {
+ wrapperCol: {
+ xs: { span: 24 },
+ sm: { span: 16 },
+ },
+ };
+
+ const itemMenu = (
+
+ );
+
+ return (
+
+
+
+
+
+ rowKey="id"
+ grid={{ gutter: 24, xl: 4, lg: 3, md: 3, sm: 2, xs: 1 }}
+ loading={loading}
+ dataSource={list}
+ renderItem={item => (
+
+
+
+ ,
+
+
+ ,
+
+
+ ,
+
+
+ ,
+ ]}
+ >
+ } title={item.title} />
+
+
+
+
+
+ )}
+ />
+
+ );
+ }
+}
+
+export default Form.create({
+ onValuesChange({ dispatch }: PAGE_NAME_UPPER_CAMEL_CASEProps, changedValues, allValues) {
+ // 表单项变化时请求数据
+ // 模拟查询表单生效
+ dispatch({
+ type: 'BLOCK_NAME_CAMEL_CASE/fetch',
+ payload: {
+ count: 8,
+ },
+ });
+ },
+})(PAGE_NAME_UPPER_CAMEL_CASE);
diff --git a/SearchListApplications/src/model.js b/SearchListApplications/src/model.js
deleted file mode 100644
index ead65a8df48a91a8b103af60429206eb865c7230..0000000000000000000000000000000000000000
--- a/SearchListApplications/src/model.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import { queryFakeList } from './service';
-
-export default {
- namespace: 'BLOCK_NAME_CAMEL_CASE',
-
- state: {
- list: [],
- },
-
- effects: {
- *fetch({ payload }, { call, put }) {
- const response = yield call(queryFakeList, payload);
- yield put({
- type: 'queryList',
- payload: Array.isArray(response) ? response : [],
- });
- },
- },
-
- reducers: {
- queryList(state, action) {
- return {
- ...state,
- list: action.payload,
- };
- },
- },
-};
diff --git a/SearchListApplications/src/model.ts b/SearchListApplications/src/model.ts
new file mode 100644
index 0000000000000000000000000000000000000000..24c2230c35d4fbff940fed19f6231cb21faee61b
--- /dev/null
+++ b/SearchListApplications/src/model.ts
@@ -0,0 +1,54 @@
+import { queryFakeList } from './service';
+import { ListItemDataType } from './data';
+import { Reducer } from 'redux';
+import { EffectsCommandMap } from 'dva';
+import { AnyAction } from 'redux';
+
+export interface IStateType {
+ list: ListItemDataType[];
+}
+
+export type Effect = (
+ action: AnyAction,
+ effects: EffectsCommandMap & { select: (func: (state: IStateType) => T) => T }
+) => void;
+
+export interface ModelType {
+ namespace: string;
+ state: IStateType;
+ effects: {
+ fetch: Effect;
+ };
+ reducers: {
+ queryList: Reducer;
+ };
+}
+
+const Model: ModelType = {
+ namespace: 'BLOCK_NAME_CAMEL_CASE',
+
+ state: {
+ list: [],
+ },
+
+ effects: {
+ *fetch({ payload }, { call, put }) {
+ const response = yield call(queryFakeList, payload);
+ yield put({
+ type: 'queryList',
+ payload: Array.isArray(response) ? response : [],
+ });
+ },
+ },
+
+ reducers: {
+ queryList(state, action) {
+ return {
+ ...state,
+ list: action.payload,
+ };
+ },
+ },
+};
+
+export default Model;
diff --git a/SearchListApplications/src/service.js b/SearchListApplications/src/service.ts
similarity index 100%
rename from SearchListApplications/src/service.js
rename to SearchListApplications/src/service.ts
diff --git a/SearchListArticles/src/index.js b/SearchListArticles/src/index.js
index 34e7f2dfeccfbc57f3a41e368a98ef63e86b1e4f..773a81bab2656ca543a4348a03b5cb8d61306b88 100644
--- a/SearchListArticles/src/index.js
+++ b/SearchListArticles/src/index.js
@@ -1,11 +1,10 @@
import React, { Component } from 'react';
import { connect } from 'dva';
-import { Form, Card, Select, List, Tag, Icon, Row, Col, Button, Input } from 'antd';
+import { Form, Card, Select, List, Tag, Icon, Row, Col, Button } from 'antd';
-import TagSelect from 'ant-design-pro/lib/TagSelect';
+import TagSelect from './components/TagSelect';
import StandardFormRow from './components/StandardFormRow';
import ArticleListContent from './components/ArticleListContent';
-import PageHeaderWrapper from './components/PageHeaderWrapper';
import styles from './style.less';
const { Option } = Select;
@@ -120,20 +119,8 @@ class SearchList extends Component {
) : null;
- const mainSearch = (
-
-
-
- );
-
return (
-
+ <>
-
+ >
);
}
}
diff --git a/SearchListProjects/src/index.js b/SearchListProjects/src/index.js
index 4db3ba69960aedb32448a28eedc68bf8c283a499..f5869fb2e1bbc80e8f3557c6048b886d735ab5db 100644
--- a/SearchListProjects/src/index.js
+++ b/SearchListProjects/src/index.js
@@ -6,7 +6,6 @@ import { Row, Col, Form, Card, Select, List, Input } from 'antd';
import { TagSelect, AvatarList, Ellipsis } from 'ant-design-pro';
import StandardFormRow from './components/StandardFormRow';
-import PageHeaderWrapper from './components/PageHeaderWrapper';
import styles from './style.less';
const { Option } = Select;
@@ -107,58 +106,56 @@ class CoverCardList extends PureComponent {
);
return (
-
-
-
+
);
}
}