开发步骤
1.添加菜单 router.config.js
{
path: '/testData',
name: 'datatest',
icon: 'form',
routes: [
{
path: '/testData/getList',
name: 'datatestList',
component: './datatest/DataTestList',
},
],
},
2.配置菜单显示的名称 zh-CN.js
'menu.datatest': '测试功能',
'menu.datatest.datatest_getList': '测试功能-查询列表',
3.新建服务 在包 /src/services 下 (datatestService.js)
import request from '@/utils/request';
export async function queryGetList(params) {
return request(`/data/test/getList`, {
method: 'POST',
body: {
...params,
},
});
}
export async function deleteById(params) {
return request(`/data/test/delete`, {
method: 'POST',
body: {
...params,
},
});
}
export async function detailById(params) {
return request(`/data/test/detail`, {
method: 'POST',
body: {
...params,
},
});
}
export async function dataSave(params) {
return request(`/data/test/insert`, {
method: 'POST',
body: {
...params,
},
});
}
export async function dataUpdate(params) {
return request(`/data/test/update`, {
method: 'POST',
body: {
...params,
},
});
}
4.新建 model(调用serivce) 在/src/pages/[模块文件夹]/models 下
样例:新建文件 /src/pages/datatest/models/datatest.js
import {
queryGetList,
deleteById,
detailById,
dataSave,
dataUpdate,
} from '@/services/datatestService';
// 注意此处 interfaceData 未项目统一封装方法(统一格式)
import { interfaceData } from '@/utils/interface';
export default {
namespace: 'datatest',
state: {
data: {
list: [],
pagination: {},
},
},
effects: {
*datatestQueryList({ payload }, { call, put }) {
const response = yield call(queryGetList, payload);
yield put({
type: 'datatestReduce',
// 注意此处 interfaceData 未项目统一封装方法(统一格式)
payload: { data: interfaceData(response) },
});
},
*datatestDeleteById({ payload, callback }, { call }) {
const response = yield call(deleteById, payload);
if (callback) callback(response);
},
*datatestDetailById({ payload, callback }, { call }) {
const response = yield call(detailById, payload);
if (callback) callback(response);
},
*datatestSave({ payload, callback }, { call }) {
const response = yield call(dataSave, payload);
if (callback) callback(response);
},
*datatestUpdate({ payload, callback }, { call }) {
const response = yield call(dataUpdate, payload);
if (callback) callback(response);
},
},
// 处理所有的同步逻辑,将数据返回给页面
// reducer 是一个函数,接受 state 和 action,返回老的或新的 state 。即:(state, action) => state
reducers: {
datatestReduce(state, { payload }) {
return {
...state,
...payload, // 将数据返回给页面
};
},
},
};
5.新建 组件(渲染页面) 在/src/pages/[模块文件夹]/ 下
创建以下两个文件
/src/pages/datatest/DataTestList.less(内容从其他地方Copy并修改即可)
/src/pages/datatest/DataTestList.js
import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import moment from 'moment';
import TraceTable from '@/components/TraceTable';
import { formatMessage, FormattedMessage } from 'umi/locale';
import {
Row,
Col,
Card,
Form,
Input,
Radio,
Select,
Button,
Modal,
message,
Divider,
Dropdown,
Menu,
Icon,
DatePicker,
Popconfirm,
} from 'antd';
const { TextArea } = Input;
import StandardTable from '@/components/StandardTable';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
// import { jsonFormat } from '@/utils/jsonUtils';
import styles from './DataTestList.less';
import numeral from 'numeral';
const FormItem = Form.Item;
const { Option } = Select;
/**
* 数据详情 弹层显示
*/
const DataDetail = Form.create()(props => {
/**
* visibleFlag : 控制是否显示
* form : 表单元素
* handleVisibleFunction : 处理是否显示的方法
* detailData : 数据详情
*/
//这里代表了使用将父类的属性或方法传递给当前 操作
const { visibleFlag, form, handleVisibleFunction, dataFormEdit, detailData } = props;
// alert(JSON.stringify(detailData));
// 编辑确定提交功能
const okHandleEdit = () => {
form.validateFields((err, fieldsValue) => {
if (err) return;
dataFormEdit(fieldsValue);
});
};
// 样式响应式布局格式(表单)
const formItemLayout = {
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 8 },
md: { span: 16 },
},
};
return (
<Modal
destroyOnClose
title="数据详情"
visible={visibleFlag}
onCancel={() => handleVisibleFunction()}
onOk={okHandleEdit}
// className={styles.modelFooter}//使用该样式会隐藏确定按钮
>
<Form>
<FormItem {...formItemLayout} label="日期:">
{form.getFieldDecorator('createTime', {
// initialValue: detailData.createTime || ''
initialValue: detailData.createTime ? moment(detailData.createTime) : '',
rules: [{ required: true, message: '日期必填' }],
})(
<DatePicker
// showTime
placeholder="请选择"
format="YYYY-MM-DD"
style={{ width: '100%' }}
/>
)}
</FormItem>
<FormItem {...formItemLayout} label="字段1:">
{form.getFieldDecorator('field1', {
initialValue: detailData.field1 || '',
rules: [{ required: true, message: '字段1必填' }],
})(<Input placeholder="请输入字段1" />)}
</FormItem>
<FormItem {...formItemLayout} label="字段2:">
{form.getFieldDecorator('field2', {
initialValue: detailData.field2 || '',
rules: [{ required: true, message: '字段2必填' }],
})(<Input placeholder="请输入字段2" />)}
</FormItem>
<FormItem {...formItemLayout} label="字段3:">
{form.getFieldDecorator('field3', {
initialValue: detailData.field3 || '',
rules: [{ required: true, message: '字段3必填' }],
})(<Input placeholder="请输入字段3" />)}
</FormItem>
<FormItem {...formItemLayout} label="字段4:">
{form.getFieldDecorator('field4', {
initialValue: detailData.field4 || '',
rules: [{ required: true, message: '字段4必填' }],
})(<Input placeholder="请输入字段4" />)}
</FormItem>
<FormItem {...formItemLayout} label="字段5:">
{form.getFieldDecorator('field5', {
initialValue: detailData.field5 || '',
rules: [{ required: true, message: '字段5必填' }],
})(<TextArea style={{ minHeight: 30 }} rows={4} placeholder="请输入字段5" />)}
</FormItem>
<FormItem {...formItemLayout} label="字段6:">
{form.getFieldDecorator('field6', {
initialValue: detailData.field6 || '',
rules: [{ required: true, message: '字段6必填' }],
})(
<Radio.Group>
<Radio value="1">选项1</Radio>
<Radio value="2">选项2</Radio>
<Radio value="3">选项3</Radio>
<Radio value="4">选项4</Radio>
</Radio.Group>
)}
</FormItem>
<FormItem {...formItemLayout} label="字段7:">
{form.getFieldDecorator('field7', {
initialValue: detailData.field7 || '',
rules: [{ required: true, message: '字段7必填' }],
})(
<Select placeholder="请选择字段7" style={{ width: '100%' }}>
<Option value="">请选择</Option>
<Option value="1">选项1</Option>
<Option value="2">选项2</Option>
<Option value="3">选项3</Option>
<Option value="4">选项4</Option>
<Option value="5">选项5</Option>
<Option value="6">选项6</Option>
</Select>
)}
</FormItem>
<FormItem>
{form.getFieldDecorator('id', {
initialValue: detailData.id || '',
})(<Input placeholder="请输入Id" type="hidden" />)}
</FormItem>
</Form>
</Modal>
);
});
@connect(({ datatest, loading }) => ({
datatest,
loading: loading.models.datatest,
}))
@Form.create()
class DataTestList extends PureComponent {
// 初始化状态值
state = {
formValues: {}, //存放查询条件
visibleFlag: false,
detailData: {},
selectedRows: [], // 选中的行,进行多行操作时用到
};
// 页面渲染完成后初始化方法
// dispatch中的参数就是一个Action。第一个type字段由两部分组成,前半部分是model的namespace(命名空间),
// 后半部分是该Action的处理位置,对应model中的effects(处理异步逻辑),或reducers(处理同步逻辑)。
componentDidMount() {
const { dispatch } = this.props;
dispatch({
type: 'datatest/datatestQueryList',
});
}
// 离开该页面时渲状态值初始化
componentWillUnmount() {
this.setState({
formValues: {},
visibleFlag: false,
detailData: {},
selectedRows: [], // 选中的行,进行多行操作时用到
});
}
// 数据查询提交
datatestSearch = e => {
e.preventDefault();
const { dispatch, form } = this.props;
form.validateFields((err, fieldsValue) => {
if (err) return;
const values = {
...fieldsValue,
};
// let BeginTime = new Date(values.beginDate).getTime();
// let EndTime = new Date(values.endDate).getTime();
// if (BeginTime == 0) {
// BeginTime = null;
// }
// if (EndTime == 0) {
// EndTime = null;
// }
// values.beginDate = BeginTime; // 开始日期非空处理
// values.endDate = EndTime; // 开始日期非空处理
this.setState({
formValues: values,
});
// values.pageNumber = 1; // 当前页码,默认1
// values.pageSize = 10; // 每页数据条数,默认10
dispatch({
type: 'datatest/datatestQueryList',
payload: values,
});
});
};
// table列表发生变化时触发(分页,排序)
tableChange = pagination => {
const { dispatch } = this.props;
const { formValues } = this.state;
// let begintime = ''; // 开始时间为空时
// let endtime = ''; // 结束时间为空时
// if (formValues != undefined) {
// if (formValues.beginDate != undefined) {
// begintime = formValues.beginDate;
// }
// if (formValues.endDate != undefined) {
// endtime = formValues.endDate;
// }
// }
// formValues.beginDate = begintime; // 开始时间
// formValues.endDate = endtime; // 结束时间
formValues.pageNumber = pagination.current; // 当前页码
formValues.pageSize = pagination.pageSize; // 每页条数
dispatch({
type: 'datatest/datatestQueryList',
payload: formValues,
});
};
// 删除确认对话框
deleteConfirm = id => {
Modal.confirm({
title: '删除任务',
content: '确定删除该条数据吗?',
okText: '确认',
cancelText: '取消',
onOk: () => this.deleteAction(id),
});
};
// 确认删除该任务
deleteAction = keyId => {
const { dispatch } = this.props;
const { formValues } = this.state;
dispatch({
type: 'datatest/datatestDeleteById',
payload: {
id: keyId, // 文档编号
},
callback: response => {
if (response.code == 20000) {
message.success('删除成功');
// let beginDate = ''; // 开始时间为空时
// let endDate = ''; // 结束时间为空时
// if (formValues != undefined) {
// if (formValues.beginDate != undefined) {
// beginDate = formValues.beginDate;
// }
// if (formValues.endDate != undefined) {
// endDate = formValues.endDate;
// }
// }
// formValues.beginDate = beginDate; // 开始时间
// formValues.endDate = endDate; // 结束时间
// formValues.pageNumber = 1; // 当前页码
// formValues.pageSize = 10; // 每页条数
dispatch({
// 删除成功后刷新列表
type: 'datatest/datatestQueryList',
payload: formValues,
});
}
},
});
};
// 编辑功能(新增或更新)
dataFormEdit = fields => {
const { dispatch } = this.props;
const updateUrl = 'datatestUpdate';
const insertUrl = 'datatestSave';
// 根据是否存在ID 判断是更新还是新增操作(还是比较通用的)
const id = fields.id;
dispatch({
type: 'datatest/' + (id ? updateUrl : insertUrl),
payload: fields,
callback: response => {
if (response.code == 20000) {
message.success('编辑成功');
} else {
message.error(response.msg);
}
// 表单管理创建成功,弹层取消
this.setState({
visibleFlag: false,
});
},
});
};
dataFormInsert() {
this.setState({
visibleFlag: true,
detailData: {},
});
}
// 扫码数据详情弹层显示/隐藏
detailHandle = (flag, id) => {
if (id) {
const { dispatch } = this.props;
dispatch({
type: 'datatest/datatestDetailById',
payload: {
id: id,
},
callback: response => {
if (response.code == 20000) {
// let sweepDetail = jsonFormat(response.data); // json化格式处理
this.setState({
visibleFlag: !!flag,
detailData: response.data, // 详情model 会监听 detailData 数据并渲染
});
} else {
message.error(response.msg);
}
},
});
} else {
this.setState({
visibleFlag: !!flag,
});
}
};
//选中行
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
};
// 更多操作
moreMenuHandle = e => {
const { selectedRows } = this.state;
if (!selectedRows) return;
let moreIds = selectedRows.map(row => row.id); //选中的IDs
switch (e.key) {
case 'moreRemove':
Modal.confirm({
title: '删除任务',
content: '确定删除数据吗?',
okText: '确认',
cancelText: '取消',
onOk: () => {
message.info('已经确认,操作成功:' + moreIds);
this.setState({
selectedRows: [],
});
},
});
break;
case 'moreActivate':
Modal.confirm({
title: '激活任务',
content: '确定激活数据吗?',
okText: '确认',
cancelText: '取消',
onOk: () => {
message.info('已经确认,操作成功:' + moreIds);
this.setState({
selectedRows: [],
});
},
});
break;
default:
break;
}
};
/**
* 查询条件筛选表单
*/
renderSearchForm() {
const {
form: { getFieldDecorator },
} = this.props;
return (
//查询条件表单
<Form onSubmit={this.datatestSearch} layout="inline">
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<FormItem label="查询字段1">
{getFieldDecorator('field1')(<Input placeholder="请输入查询字段1" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
<FormItem label="查询字段2">
{getFieldDecorator('field2')(<Input placeholder="请输入查询字段2" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
<FormItem label="查询字段3">
{getFieldDecorator('field3')(<Input placeholder="请输入查询字段3" />)}
</FormItem>
</Col>
</Row>
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<FormItem label="查询字段4">
{getFieldDecorator('field4')(<Input placeholder="请输入查询字段4" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
<FormItem label="查询字段5">
{getFieldDecorator('field5')(
<Select placeholder="请选择查询字段5" style={{ width: '100%' }}>
<Option value="true">成功</Option>
<Option value="false">失败</Option>
</Select>
)}
</FormItem>
</Col>
<Col md={8} sm={24}>
<FormItem label="查询字段6">
{getFieldDecorator('field6')(
<Select placeholder="请选择查询字段6" style={{ width: '100%' }}>
<Option value="true">成功</Option>
<Option value="false">失败</Option>
</Select>
)}
</FormItem>
</Col>
</Row>
<Row gutter={{ md: 8, lg: 24, xl: 48 }}>
<Col md={8} sm={24}>
<FormItem label="开始时间">
{getFieldDecorator('beginDate')(<DatePicker placeholder="请选择开始时间" />)}
</FormItem>
</Col>
<Col md={8} sm={24}>
<FormItem label="结束时间">
{getFieldDecorator('endDate')(<DatePicker placeholder="请选择结束时间" />)}
</FormItem>
</Col>
<Col md={8} sm={24} className={styles.queryButtons}>
<span className={styles.submitButtons}>
<Button type="primary" htmlType="submit">
查询
</Button>
</span>
</Col>
</Row>
</Form>
);
}
// 扫码数据列表名字段
columns = [
{
title: 'field1',
dataIndex: 'field1',
},
{
title: '时间',
dataIndex: 'createTime',
render(val) {
if (val != null) {
return <span>{moment(val).format('YYYY-MM-DD HH:mm:ss')}</span>;
} else {
return <span />;
}
},
},
{
title: 'field2',
dataIndex: 'field2',
},
{
title: 'field3',
dataIndex: 'field3',
},
{
title: 'field4',
dataIndex: 'field4',
},
{
title: 'field5',
dataIndex: 'field5',
},
{
title: 'field6',
dataIndex: 'field6',
},
{
title: 'field7',
dataIndex: 'field7',
},
{
title: '操作',
render: record => (
<Fragment>
<span
className={styles.operateSpan}
// onClick={() => this.handleSweepVisible(true, record.id, record.indexName)}
onClick={() => this.detailHandle(true, record.id)}
>
详情
</span>
<Divider type="vertical" />
<span
className={styles.operateSpan}
// onClick={() => this.removeRecord(record.id, record.indexName)}
onClick={() => this.deleteConfirm(record.id)}
>
删除
</span>
</Fragment>
),
},
];
// 渲染扫码数据列表界面
render() {
const {
datatest: { data },
loading,
} = this.props;
const { visibleFlag, detailData, selectedRows } = this.state;
// 扫码数据详情组件参数信息值
const parentMethods = {
handleVisibleFunction: this.detailHandle,
dataFormEdit: this.dataFormEdit,
};
// 定义批量操作更多menu
const moreMenu = (
<Menu onClick={this.moreMenuHandle} selectedKeys={[]}>
<Menu.Item key="moreRemove">批量删除</Menu.Item>
<Menu.Item key="moreActivate">批量激活</Menu.Item>
</Menu>
);
return (
<PageHeaderWrapper>
<Card bordered={false}>
<div className={styles.tableList}>
<div className={styles.tableListForm}>{this.renderSearchForm()}</div>
<div className={styles.tableListOperator}>
<Button icon="plus" type="primary" onClick={() => this.dataFormInsert()}>
新 增
</Button>
{selectedRows.length > 0 && (
<Dropdown overlay={moreMenu}>
<Button>
更多操作 <Icon type="down" />
</Button>
</Dropdown>
)}
</div>
{/* 有批量处理的功能 sy封装过的 */}
<TraceTable
data={data}
loading={loading}
columns={this.columns}
selectedRows={selectedRows}
onSelectRow={this.handleSelectRows}
/>
{/* 没有批量处理的功能 */}
{/*<StandardTable*/}
{/*loading={loading}*/}
{/*data={data}*/}
{/*columns={this.columns}*/}
{/*selectedRows={[]}*/}
{/*onChange={this.tableChange}*/}
{/*/>*/}
{data.pagination.total > 0 ? (
<div className={styles.dataListTotal}>
总共
<span className={styles.dataTotalColor}>
{numeral(data.pagination.total).format('0,0')}
</span>
条数据
</div>
) : null}
</div>
</Card>
<DataDetail {...parentMethods} visibleFlag={visibleFlag} detailData={detailData} />
</PageHeaderWrapper>
);
}
}
export default DataTestList;
6.RAP配置截图如下:
7.如果需要RAP测试,请确保配置了代理 config.js
proxy: {
'/data': {
target: 'http://rap.**.com/mockjsdata/149/',
changeOrigin: true,
},
'/template': {
target: 'http://rap.**.com/mockjsdata/151/',
changeOrigin: true,
},
},
8.效果如下