Ver código fonte

New page - step modal (#855)

* temp save

* add new page & make some improve
ddcat1115 8 anos atrás
pai
commit
44ca66763a
4 arquivos alterados com 332 adições e 84 exclusões
  1. 16 8
      mock/rule.js
  2. 9 1
      src/models/rule.js
  3. 297 75
      src/routes/List/TableList.js
  4. 10 0
      src/services/api.js

+ 16 - 8
mock/rule.js

@@ -8,10 +8,10 @@ for (let i = 0; i < 46; i += 1) {
     disabled: ((i % 6) === 0),
     href: 'https://ant.design',
     avatar: ['https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png'][i % 2],
-    no: `TradeCode ${i}`,
+    name: `TradeCode ${i}`,
     title: `一个任务名称 ${i}`,
     owner: '曲丽丽',
-    description: '这是一段描述',
+    desc: '这是一段描述',
     callNo: Math.floor(Math.random() * 1000),
     status: Math.floor(Math.random() * 10) % 4,
     updatedAt: new Date(`2017-07-${Math.floor(i / 2) + 1}`),
@@ -51,8 +51,8 @@ export function getRule(req, res, u) {
     dataSource = filterDataSource;
   }
 
-  if (params.no) {
-    dataSource = dataSource.filter(data => data.no.indexOf(params.no) > -1);
+  if (params.name) {
+    dataSource = dataSource.filter(data => data.name.indexOf(params.name) > -1);
   }
 
   let pageSize = 10;
@@ -83,12 +83,12 @@ export function postRule(req, res, u, b) {
   }
 
   const body = (b && b.body) || req.body;
-  const { method, no, description } = body;
+  const { method, name, desc, key } = body;
 
   switch (method) {
     /* eslint no-case-declarations:0 */
     case 'delete':
-      tableListDataSource = tableListDataSource.filter(item => no.indexOf(item.no) === -1);
+      tableListDataSource = tableListDataSource.filter(item => key.indexOf(item.key) === -1);
       break;
     case 'post':
       const i = Math.ceil(Math.random() * 10000);
@@ -96,10 +96,10 @@ export function postRule(req, res, u, b) {
         key: i,
         href: 'https://ant.design',
         avatar: ['https://gw.alipayobjects.com/zos/rmsportal/eeHMaZBwmTvLdIwMfBpg.png', 'https://gw.alipayobjects.com/zos/rmsportal/udxAbMEhpwthVVcjLXik.png'][i % 2],
-        no: `TradeCode ${i}`,
+        name: `TradeCode ${i}`,
         title: `一个任务名称 ${i}`,
         owner: '曲丽丽',
-        description,
+        desc,
         callNo: Math.floor(Math.random() * 1000),
         status: Math.floor(Math.random() * 10) % 2,
         updatedAt: new Date(),
@@ -107,6 +107,14 @@ export function postRule(req, res, u, b) {
         progress: Math.ceil(Math.random() * 100),
       });
       break;
+    case 'update':
+      tableListDataSource = tableListDataSource.map((item) => {
+        if (item.key === key) {
+          return { ...item, desc, name };
+        }
+        return item;
+      });
+      break;
     default:
       break;
   }

+ 9 - 1
src/models/rule.js

@@ -1,4 +1,4 @@
-import { queryRule, removeRule, addRule } from '../services/api';
+import { queryRule, removeRule, addRule, updateRule } from '../services/api';
 
 export default {
   namespace: 'rule',
@@ -34,6 +34,14 @@ export default {
       });
       if (callback) callback();
     },
+    *update({ payload, callback }, { call, put }) {
+      const response = yield call(updateRule, payload);
+      yield put({
+        type: 'save',
+        payload: response,
+      });
+      if (callback) callback();
+    },
   },
 
   reducers: {

+ 297 - 75
src/routes/List/TableList.js

@@ -1,77 +1,21 @@
 import React, { PureComponent, Fragment } from 'react';
 import { connect } from 'dva';
 import moment from 'moment';
-import { Row, Col, Card, Form, Input, Select, Icon, Button, Dropdown, Menu, InputNumber, DatePicker, Modal, message, Badge, Divider } from 'antd';
+import { Row, Col, Card, Form, Input, Select, Icon, Button, Dropdown, Menu,
+  InputNumber, DatePicker, Modal, message, Badge, Divider, Steps, Radio } from 'antd';
 import StandardTable from '../../components/StandardTable';
 import PageHeaderLayout from '../../layouts/PageHeaderLayout';
 
 import styles from './TableList.less';
 
 const FormItem = Form.Item;
+const { Step } = Steps;
+const { TextArea } = Input;
 const { Option } = Select;
+const RadioGroup = Radio.Group;
 const getValue = obj => Object.keys(obj).map(key => obj[key]).join(',');
 const statusMap = ['default', 'processing', 'success', 'error'];
 const status = ['关闭', '运行中', '已上线', '异常'];
-const columns = [
-  {
-    title: '规则编号',
-    dataIndex: 'no',
-  },
-  {
-    title: '描述',
-    dataIndex: 'description',
-  },
-  {
-    title: '服务调用次数',
-    dataIndex: 'callNo',
-    sorter: true,
-    align: 'right',
-    render: val => `${val} 万`,
-    // mark to display a total number
-    needTotal: true,
-  },
-  {
-    title: '状态',
-    dataIndex: 'status',
-    filters: [
-      {
-        text: status[0],
-        value: 0,
-      },
-      {
-        text: status[1],
-        value: 1,
-      },
-      {
-        text: status[2],
-        value: 2,
-      },
-      {
-        text: status[3],
-        value: 3,
-      },
-    ],
-    render(val) {
-      return <Badge status={statusMap[val]} text={status[val]} />;
-    },
-  },
-  {
-    title: '更新时间',
-    dataIndex: 'updatedAt',
-    sorter: true,
-    render: val => <span>{moment(val).format('YYYY-MM-DD HH:mm:ss')}</span>,
-  },
-  {
-    title: '操作',
-    render: () => (
-      <Fragment>
-        <a href="">配置</a>
-        <Divider type="vertical" />
-        <a href="">订阅警报</a>
-      </Fragment>
-    ),
-  },
-];
 
 const CreateForm = Form.create()((props) => {
   const { modalVisible, form, handleAdd, handleModalVisible } = props;
@@ -83,6 +27,7 @@ const CreateForm = Form.create()((props) => {
   };
   return (
     <Modal
+      destroyOnClose
       title="新建规则"
       visible={modalVisible}
       onOk={okHandle}
@@ -94,7 +39,7 @@ const CreateForm = Form.create()((props) => {
         label="描述"
       >
         {form.getFieldDecorator('desc', {
-          rules: [{ required: true, message: 'Please input some description...' }],
+          rules: [{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }],
         })(
           <Input placeholder="请输入" />
         )}
@@ -103,6 +48,190 @@ const CreateForm = Form.create()((props) => {
   );
 });
 
+@Form.create()
+class UpdateForm extends PureComponent {
+  constructor(props) {
+    super(props);
+
+    this.state = {
+      formVals: {
+        name: props.values.name,
+        desc: props.values.desc,
+        key: props.values.key,
+        target: '0',
+        template: '0',
+        type: '1',
+        time: '',
+        frequency: 'month',
+      },
+      currentStep: 0,
+    };
+
+    this.formLayout = {
+      labelCol: { span: 7 },
+      wrapperCol: { span: 13 },
+    };
+  }
+  handleNext = (currentStep) => {
+    const { form, handleUpdate } = this.props;
+    form.validateFields((err, fieldsValue) => {
+      if (err) return;
+      const formVals = { ...this.state.formVals, ...fieldsValue };
+      this.setState({
+        formVals,
+      }, () => {
+        if (currentStep < 2) {
+          this.forward();
+        } else {
+          handleUpdate(this.state.formVals);
+        }
+      });
+    });
+  }
+  backward = () => {
+    this.setState({
+      currentStep: this.state.currentStep - 1,
+    });
+  }
+  forward = () => {
+    this.setState({
+      currentStep: this.state.currentStep + 1,
+    });
+  }
+  renderContent = (currentStep, formVals) => {
+    const { form } = this.props;
+    if (currentStep === 1) {
+      return [
+        <FormItem key="target" {...this.formLayout} label="监控对象">
+          {form.getFieldDecorator('target', {
+            initialValue: formVals.target,
+          })(
+            <Select style={{ width: '100%' }}>
+              <Option value="0">表一</Option>
+              <Option value="1">表二</Option>
+            </Select>
+          )}
+        </FormItem>,
+        <FormItem key="template" {...this.formLayout} label="规则模板">
+          {form.getFieldDecorator('template', {
+            initialValue: formVals.template,
+          })(
+            <Select style={{ width: '100%' }}>
+              <Option value="0">规则模板一</Option>
+              <Option value="1">规则模板二</Option>
+            </Select>
+          )}
+        </FormItem>,
+        <FormItem key="type" {...this.formLayout} label="规则类型">
+          {form.getFieldDecorator('type', {
+            initialValue: formVals.type,
+          })(
+            <RadioGroup>
+              <Radio value="0">强</Radio>
+              <Radio value="1">弱</Radio>
+            </RadioGroup>
+          )}
+        </FormItem>,
+      ];
+    }
+    if (currentStep === 2) {
+      return [
+        <FormItem key="time" {...this.formLayout} label="开始时间">
+          {form.getFieldDecorator('time', {
+            rules: [{ required: true, message: '请选择开始时间!' }],
+          })(
+            <DatePicker
+              style={{ width: '100%' }}
+              showTime
+              format="YYYY-MM-DD HH:mm:ss"
+              placeholder="选择开始时间"
+            />
+          )}
+        </FormItem>,
+        <FormItem key="frequency" {...this.formLayout} label="调度周期">
+          {form.getFieldDecorator('frequency', {
+            initialValue: formVals.frequency,
+          })(
+            <Select style={{ width: '100%' }}>
+              <Option value="month">月</Option>
+              <Option value="week">周</Option>
+            </Select>
+          )}
+        </FormItem>,
+      ];
+    }
+    return [
+      <FormItem key="name" {...this.formLayout} label="规则名称">
+        {form.getFieldDecorator('name', {
+          rules: [{ required: true, message: '请输入规则名称!' }],
+          initialValue: formVals.name,
+        })(
+          <Input placeholder="请输入" />
+        )}
+      </FormItem>,
+      <FormItem key="desc" {...this.formLayout} label="规则描述">
+        {form.getFieldDecorator('desc', {
+          rules: [{ required: true, message: '请输入至少五个字符的规则描述!', min: 5 }],
+          initialValue: formVals.desc,
+        })(
+          <TextArea rows={4} placeholder="请输入至少五个字符" />
+        )}
+      </FormItem>,
+    ];
+  }
+  renderFooter = (currentStep) => {
+    const { handleUpdateModalVisible } = this.props;
+    if (currentStep === 1) {
+      return [
+        <Button key="back" style={{ float: 'left' }} onClick={this.backward}>上一步</Button>,
+        <Button key="cancel" onClick={() => handleUpdateModalVisible()}>取消</Button>,
+        <Button key="forward" type="primary" onClick={() => this.handleNext(currentStep)}>
+          下一步
+        </Button>,
+      ];
+    }
+    if (currentStep === 2) {
+      return [
+        <Button key="back" style={{ float: 'left' }} onClick={this.backward}>上一步</Button>,
+        <Button key="cancel" onClick={() => handleUpdateModalVisible()}>取消</Button>,
+        <Button key="submit" type="primary" onClick={() => this.handleNext(currentStep)}>
+          完成
+        </Button>,
+      ];
+    }
+    return [
+      <Button key="cancel" onClick={() => handleUpdateModalVisible()}>取消</Button>,
+      <Button key="forward" type="primary" onClick={() => this.handleNext(currentStep)}>
+        下一步
+      </Button>,
+    ];
+  }
+  render() {
+    const { updateModalVisible, handleUpdateModalVisible } = this.props;
+    const { currentStep, formVals } = this.state;
+
+    return (
+      <Modal
+        width={640}
+        bodyStyle={{ padding: '32px 40px 48px' }}
+        destroyOnClose
+        title="规则配置"
+        visible={updateModalVisible}
+        footer={this.renderFooter(currentStep)}
+        onCancel={() => handleUpdateModalVisible()}
+      >
+        <Steps style={{ marginBottom: 32 }} size="small" current={currentStep}>
+          <Step title="基本信息" />
+          <Step title="配置规则属性" />
+          <Step title="设定调度周期" />
+        </Steps>
+        { this.renderContent(currentStep, formVals) }
+      </Modal>
+    );
+  }
+}
+
+/* eslint react/no-multi-comp:0 */
 @connect(({ rule, loading }) => ({
   rule,
   loading: loading.models.rule,
@@ -111,9 +240,11 @@ const CreateForm = Form.create()((props) => {
 export default class TableList extends PureComponent {
   state = {
     modalVisible: false,
+    updateModalVisible: false,
     expandForm: false,
     selectedRows: [],
     formValues: {},
+    stepFormValues: {},
   };
 
   componentDidMount() {
@@ -123,6 +254,67 @@ export default class TableList extends PureComponent {
     });
   }
 
+  columns = [
+    {
+      title: '规则名称',
+      dataIndex: 'name',
+    },
+    {
+      title: '描述',
+      dataIndex: 'desc',
+    },
+    {
+      title: '服务调用次数',
+      dataIndex: 'callNo',
+      sorter: true,
+      align: 'right',
+      render: val => `${val} 万`,
+      // mark to display a total number
+      needTotal: true,
+    },
+    {
+      title: '状态',
+      dataIndex: 'status',
+      filters: [
+        {
+          text: status[0],
+          value: 0,
+        },
+        {
+          text: status[1],
+          value: 1,
+        },
+        {
+          text: status[2],
+          value: 2,
+        },
+        {
+          text: status[3],
+          value: 3,
+        },
+      ],
+      render(val) {
+        return <Badge status={statusMap[val]} text={status[val]} />;
+      },
+    },
+    {
+      title: '上次调度时间',
+      dataIndex: 'updatedAt',
+      sorter: true,
+      render: val => <span>{moment(val).format('YYYY-MM-DD HH:mm:ss')}</span>,
+    },
+    {
+      title: '操作',
+      render: (text, record) => (
+        <Fragment>
+          <a onClick={() => this.handleUpdateModalVisible(true, record)}>配置</a>
+          <Divider type="vertical" />
+          <a href="">订阅警报</a>
+        </Fragment>
+      ),
+    },
+  ];
+
   handleStandardTableChange = (pagination, filtersArg, sorter) => {
     const { dispatch } = this.props;
     const { formValues } = this.state;
@@ -172,13 +364,12 @@ export default class TableList extends PureComponent {
     const { selectedRows } = this.state;
 
     if (!selectedRows) return;
-
     switch (e.key) {
       case 'remove':
         dispatch({
           type: 'rule/remove',
           payload: {
-            no: selectedRows.map(row => row.no).join(','),
+            key: selectedRows.map(row => row.key),
           },
           callback: () => {
             this.setState({
@@ -228,18 +419,37 @@ export default class TableList extends PureComponent {
     });
   }
 
+  handleUpdateModalVisible = (flag, record) => {
+    this.setState({
+      updateModalVisible: !!flag,
+      stepFormValues: record || {},
+    });
+  }
+
   handleAdd = (fields) => {
     this.props.dispatch({
       type: 'rule/add',
       payload: {
-        description: fields.desc,
+        desc: fields.desc,
       },
     });
 
     message.success('添加成功');
-    this.setState({
-      modalVisible: false,
+    this.handleModalVisible();
+  }
+
+  handleUpdate = (fields) => {
+    this.props.dispatch({
+      type: 'rule/update',
+      payload: {
+        name: fields.name,
+        desc: fields.desc,
+        key: fields.key,
+      },
     });
+
+    message.success('配置成功');
+    this.handleUpdateModalVisible();
   }
 
   renderSimpleForm() {
@@ -248,8 +458,8 @@ export default class TableList extends PureComponent {
       <Form onSubmit={this.handleSearch} layout="inline">
         <Row gutter={{ md: 8, lg: 24, xl: 48 }}>
           <Col md={8} sm={24}>
-            <FormItem label="规则编号">
-              {getFieldDecorator('no')(
+            <FormItem label="规则名称">
+              {getFieldDecorator('name')(
                 <Input placeholder="请输入" />
               )}
             </FormItem>
@@ -284,8 +494,8 @@ export default class TableList extends PureComponent {
       <Form onSubmit={this.handleSearch} layout="inline">
         <Row gutter={{ md: 8, lg: 24, xl: 48 }}>
           <Col md={8} sm={24}>
-            <FormItem label="规则编号">
-              {getFieldDecorator('no')(
+            <FormItem label="规则名称">
+              {getFieldDecorator('name')(
                 <Input placeholder="请输入" />
               )}
             </FormItem>
@@ -356,8 +566,7 @@ export default class TableList extends PureComponent {
 
   render() {
     const { rule: { data }, loading } = this.props;
-    const { selectedRows, modalVisible } = this.state;
-
+    const { selectedRows, modalVisible, updateModalVisible, stepFormValues } = this.state;
     const menu = (
       <Menu onClick={this.handleMenuClick} selectedKeys={[]}>
         <Menu.Item key="remove">删除</Menu.Item>
@@ -369,7 +578,10 @@ export default class TableList extends PureComponent {
       handleAdd: this.handleAdd,
       handleModalVisible: this.handleModalVisible,
     };
-
+    const updateMethods = {
+      handleUpdateModalVisible: this.handleUpdateModalVisible,
+      handleUpdate: this.handleUpdate,
+    };
     return (
       <PageHeaderLayout title="查询表格">
         <Card bordered={false}>
@@ -398,7 +610,7 @@ export default class TableList extends PureComponent {
               selectedRows={selectedRows}
               loading={loading}
               data={data}
-              columns={columns}
+              columns={this.columns}
               onSelectRow={this.handleSelectRows}
               onChange={this.handleStandardTableChange}
             />
@@ -408,6 +620,16 @@ export default class TableList extends PureComponent {
           {...parentMethods}
           modalVisible={modalVisible}
         />
+        {
+          stepFormValues && Object.keys(stepFormValues).length ?
+            (
+              <UpdateForm
+                {...updateMethods}
+                updateModalVisible={updateModalVisible}
+                values={stepFormValues}
+              />
+            ) : null
+        }
       </PageHeaderLayout>
     );
   }

+ 10 - 0
src/services/api.js

@@ -33,6 +33,16 @@ export async function addRule(params) {
   });
 }
 
+export async function updateRule(params) {
+  return request('/api/rule', {
+    method: 'POST',
+    body: {
+      ...params,
+      method: 'update',
+    },
+  });
+}
+
 export async function fakeSubmitForm(params) {
   return request('/api/forms', {
     method: 'POST',