index.tsx 10.7 KB
Newer Older
jim's avatar
jim committed
1
import {
陈帅's avatar
陈帅 committed
2 3
  Avatar,
  Button,
jim's avatar
jim committed
4 5
  Card,
  Col,
陈帅's avatar
陈帅 committed
6
  DatePicker,
jim's avatar
jim committed
7
  Dropdown,
陈帅's avatar
陈帅 committed
8 9 10 11
  Form,
  Icon,
  Input,
  List,
jim's avatar
jim committed
12 13
  Menu,
  Modal,
陈帅's avatar
陈帅 committed
14 15 16
  Progress,
  Radio,
  Row,
jim's avatar
jim committed
17 18
  Select,
} from 'antd';
陈帅's avatar
陈帅 committed
19 20
import React, { Component } from 'react';

陈帅's avatar
陈帅 committed
21
import { Dispatch } from 'redux';
陈帅's avatar
陈帅 committed
22
import { FormComponentProps } from 'antd/es/form';
陈帅's avatar
陈帅 committed
23
import { PageHeaderWrapper } from '@ant-design/pro-layout';
陈帅's avatar
陈帅 committed
24 25 26 27
import { connect } from 'dva';
import { findDOMNode } from 'react-dom';
import moment from 'moment';
import Result from './Result';
陈帅's avatar
陈帅 committed
28
import { IStateType } from './model';
陈帅's avatar
陈帅 committed
29
import { BasicListItemDataType } from './data.d';
30
import styles from './style.less';
31

valleykid's avatar
valleykid committed
32
const FormItem = Form.Item;
33 34
const RadioButton = Radio.Button;
const RadioGroup = Radio.Group;
valleykid's avatar
valleykid committed
35 36
const SelectOption = Select.Option;
const { Search, TextArea } = Input;
37

陈帅's avatar
陈帅 committed
38 39
interface PAGE_NAME_UPPER_CAMEL_CASEProps extends FormComponentProps {
  BLOCK_NAME_CAMEL_CASE: IStateType;
陈帅's avatar
陈帅 committed
40
  dispatch: Dispatch<any>;
陈帅's avatar
陈帅 committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
  loading: boolean;
}
interface PAGE_NAME_UPPER_CAMEL_CASEState {
  visible: boolean;
  done: boolean;
  current?: Partial<BasicListItemDataType>;
}
@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,
陈帅's avatar
陈帅 committed
60
  }),
陈帅's avatar
陈帅 committed
61 62 63 64 65 66
)
class PAGE_NAME_UPPER_CAMEL_CASE extends Component<
  PAGE_NAME_UPPER_CAMEL_CASEProps,
  PAGE_NAME_UPPER_CAMEL_CASEState
> {
  state: PAGE_NAME_UPPER_CAMEL_CASEState = { visible: false, done: false, current: undefined };
valleykid's avatar
valleykid committed
67

68 69 70 71
  formLayout = {
    labelCol: { span: 7 },
    wrapperCol: { span: 13 },
  };
陈帅's avatar
陈帅 committed
72

陈帅's avatar
陈帅 committed
73
  addBtn: HTMLButtonElement | undefined | null;
74

75
  componentDidMount() {
陈帅's avatar
陈帅 committed
76 77
    const { dispatch } = this.props;
    dispatch({
78
      type: 'BLOCK_NAME_CAMEL_CASE/fetch',
79 80 81 82 83
      payload: {
        count: 5,
      },
    });
  }
陈帅's avatar
陈帅 committed
84

valleykid's avatar
valleykid committed
85 86 87 88 89
  showModal = () => {
    this.setState({
      visible: true,
      current: undefined,
    });
jim's avatar
jim committed
90
  };
陈帅's avatar
陈帅 committed
91

陈帅's avatar
陈帅 committed
92
  showEditModal = (item: BasicListItemDataType) => {
valleykid's avatar
valleykid committed
93 94 95 96
    this.setState({
      visible: true,
      current: item,
    });
jim's avatar
jim committed
97
  };
陈帅's avatar
陈帅 committed
98

valleykid's avatar
valleykid committed
99
  handleDone = () => {
陈帅's avatar
陈帅 committed
100
    setTimeout(() => this.addBtn && this.addBtn.blur(), 0);
valleykid's avatar
valleykid committed
101 102 103 104
    this.setState({
      done: false,
      visible: false,
    });
jim's avatar
jim committed
105
  };
陈帅's avatar
陈帅 committed
106

valleykid's avatar
valleykid committed
107
  handleCancel = () => {
陈帅's avatar
陈帅 committed
108
    setTimeout(() => this.addBtn && this.addBtn.blur(), 0);
valleykid's avatar
valleykid committed
109 110 111
    this.setState({
      visible: false,
    });
jim's avatar
jim committed
112
  };
陈帅's avatar
陈帅 committed
113

陈帅's avatar
陈帅 committed
114
  handleSubmit = (e: React.FormEvent) => {
valleykid's avatar
valleykid committed
115 116
    e.preventDefault();
    const { dispatch, form } = this.props;
陈帅's avatar
陈帅 committed
117 118
    const { current } = this.state;
    const id = current ? current.id : '';
valleykid's avatar
valleykid committed
119

陈帅's avatar
陈帅 committed
120 121
    setTimeout(() => this.addBtn && this.addBtn.blur(), 0);
    form.validateFields((err: string | undefined, fieldsValue: BasicListItemDataType) => {
valleykid's avatar
valleykid committed
122 123 124 125 126
      if (err) return;
      this.setState({
        done: true,
      });
      dispatch({
127
        type: 'BLOCK_NAME_CAMEL_CASE/submit',
valleykid's avatar
valleykid committed
128 129 130
        payload: { id, ...fieldsValue },
      });
    });
jim's avatar
jim committed
131
  };
陈帅's avatar
陈帅 committed
132

陈帅's avatar
陈帅 committed
133
  deleteItem = (id: string) => {
陈帅's avatar
陈帅 committed
134 135
    const { dispatch } = this.props;
    dispatch({
136
      type: 'BLOCK_NAME_CAMEL_CASE/submit',
valleykid's avatar
valleykid committed
137 138
      payload: { id },
    });
jim's avatar
jim committed
139
  };
140 141

  render() {
陈帅's avatar
陈帅 committed
142
    const {
143
      BLOCK_NAME_CAMEL_CASE: { list },
陈帅's avatar
陈帅 committed
144 145 146 147 148
      loading,
    } = this.props;
    const {
      form: { getFieldDecorator },
    } = this.props;
陈帅's avatar
陈帅 committed
149

valleykid's avatar
valleykid committed
150 151
    const { visible, done, current = {} } = this.state;

陈帅's avatar
陈帅 committed
152
    const editAndDelete = (key: string, currentItem: BasicListItemDataType) => {
valleykid's avatar
valleykid committed
153 154 155 156 157 158 159 160 161 162 163 164
      if (key === 'edit') this.showEditModal(currentItem);
      else if (key === 'delete') {
        Modal.confirm({
          title: '删除任务',
          content: '确定删除该任务吗?',
          okText: '确认',
          cancelText: '取消',
          onOk: () => this.deleteItem(currentItem.id),
        });
      }
    };

jim's avatar
jim committed
165 166 167
    const modalFooter = done
      ? { footer: null, onCancel: this.handleDone }
      : { okText: '保存', onOk: this.handleSubmit, onCancel: this.handleCancel };
168

陈帅's avatar
陈帅 committed
169 170 171 172 173
    const Info: React.SFC<{
      title: React.ReactNode;
      value: React.ReactNode;
      bordered?: boolean;
    }> = ({ title, value, bordered }) => (
174 175 176 177 178 179 180 181 182 183 184 185 186 187
      <div className={styles.headerInfo}>
        <span>{title}</span>
        <p>{value}</p>
        {bordered && <em />}
      </div>
    );

    const extraContent = (
      <div className={styles.extraContent}>
        <RadioGroup defaultValue="all">
          <RadioButton value="all">全部</RadioButton>
          <RadioButton value="progress">进行中</RadioButton>
          <RadioButton value="waiting">等待中</RadioButton>
        </RadioGroup>
jim's avatar
jim committed
188
        <Search className={styles.extraContentSearch} placeholder="请输入" onSearch={() => ({})} />
189 190 191 192 193 194 195 196 197 198
      </div>
    );

    const paginationProps = {
      showSizeChanger: true,
      showQuickJumper: true,
      pageSize: 5,
      total: 50,
    };

陈帅's avatar
陈帅 committed
199 200 201 202 203
    const ListContent = ({
      data: { owner, createdAt, percent, status },
    }: {
      data: BasicListItemDataType;
    }) => (
204
      <div className={styles.listContent}>
afc163's avatar
afc163 committed
205
        <div className={styles.listContentItem}>
206 207 208
          <span>Owner</span>
          <p>{owner}</p>
        </div>
afc163's avatar
afc163 committed
209
        <div className={styles.listContentItem}>
210
          <span>开始时间</span>
spiritree's avatar
spiritree committed
211
          <p>{moment(createdAt).format('YYYY-MM-DD HH:mm')}</p>
212
        </div>
afc163's avatar
afc163 committed
213 214
        <div className={styles.listContentItem}>
          <Progress percent={percent} status={status} strokeWidth={6} style={{ width: 180 }} />
215 216 217 218
        </div>
      </div>
    );

陈帅's avatar
陈帅 committed
219
    const MoreBtn: React.SFC<{
陈帅's avatar
陈帅 committed
220 221
      item: BasicListItemDataType;
    }> = ({ item }) => (
jim's avatar
jim committed
222 223
      <Dropdown
        overlay={
陈帅's avatar
陈帅 committed
224
          <Menu onClick={({ key }) => editAndDelete(key, item)}>
jim's avatar
jim committed
225 226 227 228
            <Menu.Item key="edit">编辑</Menu.Item>
            <Menu.Item key="delete">删除</Menu.Item>
          </Menu>
        }
valleykid's avatar
valleykid committed
229
      >
230 231 232 233 234 235
        <a>
          更多 <Icon type="down" />
        </a>
      </Dropdown>
    );

valleykid's avatar
valleykid committed
236 237 238 239 240 241 242
    const getModalContent = () => {
      if (done) {
        return (
          <Result
            type="success"
            title="操作成功"
            description="一系列的信息描述,很短同样也可以带标点。"
jim's avatar
jim committed
243 244 245 246 247
            actions={
              <Button type="primary" onClick={this.handleDone}>
                知道了
              </Button>
            }
valleykid's avatar
valleykid committed
248
            className={styles.formResult}
valleykid's avatar
valleykid committed
249 250 251 252 253 254 255 256 257
          />
        );
      }
      return (
        <Form onSubmit={this.handleSubmit}>
          <FormItem label="任务名称" {...this.formLayout}>
            {getFieldDecorator('title', {
              rules: [{ required: true, message: '请输入任务名称' }],
              initialValue: current.title,
jim's avatar
jim committed
258
            })(<Input placeholder="请输入" />)}
valleykid's avatar
valleykid committed
259 260 261 262 263 264 265 266 267 268 269
          </FormItem>
          <FormItem label="开始时间" {...this.formLayout}>
            {getFieldDecorator('createdAt', {
              rules: [{ required: true, message: '请选择开始时间' }],
              initialValue: current.createdAt ? moment(current.createdAt) : null,
            })(
              <DatePicker
                showTime
                placeholder="请选择"
                format="YYYY-MM-DD HH:mm:ss"
                style={{ width: '100%' }}
陈帅's avatar
陈帅 committed
270
              />,
valleykid's avatar
valleykid committed
271 272 273 274 275 276 277 278 279 280
            )}
          </FormItem>
          <FormItem label="任务负责人" {...this.formLayout}>
            {getFieldDecorator('owner', {
              rules: [{ required: true, message: '请选择任务负责人' }],
              initialValue: current.owner,
            })(
              <Select placeholder="请选择">
                <SelectOption value="付晓晓">付晓晓</SelectOption>
                <SelectOption value="周毛毛">周毛毛</SelectOption>
陈帅's avatar
陈帅 committed
281
              </Select>,
valleykid's avatar
valleykid committed
282 283 284 285 286 287
            )}
          </FormItem>
          <FormItem {...this.formLayout} label="产品描述">
            {getFieldDecorator('subDescription', {
              rules: [{ message: '请输入至少五个字符的产品描述!', min: 5 }],
              initialValue: current.subDescription,
jim's avatar
jim committed
288
            })(<TextArea rows={4} placeholder="请输入至少五个字符" />)}
valleykid's avatar
valleykid committed
289 290 291 292
          </FormItem>
        </Form>
      );
    };
293
    return (
294 295
      <>
        <PageHeaderWrapper>
陈帅's avatar
陈帅 committed
296 297 298 299 300 301 302 303 304 305 306 307 308 309
          <div className={styles.standardList}>
            <Card bordered={false}>
              <Row>
                <Col sm={8} xs={24}>
                  <Info title="我的待办" value="8个任务" bordered />
                </Col>
                <Col sm={8} xs={24}>
                  <Info title="本周任务平均处理时间" value="32分钟" bordered />
                </Col>
                <Col sm={8} xs={24}>
                  <Info title="本周完成任务数" value="24个任务" />
                </Col>
              </Row>
            </Card>
310

陈帅's avatar
陈帅 committed
311 312 313 314 315 316 317
            <Card
              className={styles.listCard}
              bordered={false}
              title="基本列表"
              style={{ marginTop: 24 }}
              bodyStyle={{ padding: '0 32px 40px 32px' }}
              extra={extraContent}
valleykid's avatar
valleykid committed
318
            >
陈帅's avatar
陈帅 committed
319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
              <Button
                type="dashed"
                style={{ width: '100%', marginBottom: 8 }}
                icon="plus"
                onClick={this.showModal}
                ref={component => {
                  this.addBtn = findDOMNode(component) as HTMLButtonElement;
                }}
              >
                添加
              </Button>
              <List
                size="large"
                rowKey="id"
                loading={loading}
                pagination={paginationProps}
                dataSource={list}
                renderItem={item => (
                  <List.Item
                    actions={[
                      <a
陈帅's avatar
陈帅 committed
340
                        key="edit"
陈帅's avatar
陈帅 committed
341 342 343 344 345 346 347
                        onClick={e => {
                          e.preventDefault();
                          this.showEditModal(item);
                        }}
                      >
                        编辑
                      </a>,
陈帅's avatar
陈帅 committed
348
                      <MoreBtn key="more" item={item} />,
陈帅's avatar
陈帅 committed
349 350 351 352 353 354 355 356 357 358 359 360 361
                    ]}
                  >
                    <List.Item.Meta
                      avatar={<Avatar src={item.logo} shape="square" size="large" />}
                      title={<a href={item.href}>{item.title}</a>}
                      description={item.subDescription}
                    />
                    <ListContent data={item} />
                  </List.Item>
                )}
              />
            </Card>
          </div>
362
        </PageHeaderWrapper>
陈帅's avatar
陈帅 committed
363

valleykid's avatar
valleykid committed
364
        <Modal
陈帅's avatar
陈帅 committed
365
          title={done ? null : `任务${current ? '编辑' : '添加'}`}
valleykid's avatar
valleykid committed
366
          className={styles.standardListForm}
valleykid's avatar
valleykid committed
367
          width={640}
valleykid's avatar
valleykid committed
368
          bodyStyle={done ? { padding: '72px 0' } : { padding: '28px 0 0' }}
valleykid's avatar
valleykid committed
369 370 371 372 373 374
          destroyOnClose
          visible={visible}
          {...modalFooter}
        >
          {getModalContent()}
        </Modal>
375
      </>
376 377 378
    );
  }
}
lijiehua's avatar
lijiehua committed
379

陈帅's avatar
陈帅 committed
380
export default Form.create<PAGE_NAME_UPPER_CAMEL_CASEProps>()(PAGE_NAME_UPPER_CAMEL_CASE);