提交 adfefd92 authored 作者: 王绍森's avatar 王绍森

增加List组件

上级 fbf8b038
/**
* 国家励志奖学金
* 钟是志
* 2019年11月28日
* 因业务复杂只能特殊开发
* */
import React, { Component } from 'react';
import ApplyPage from '../index';
import { getDefaultValues } from '../../destruction';
import { message } from 'antd';
const getIndex = (arr, name) => {
return arr.findIndex((x) => {
return x.name === name;
});
};
const GJLZJXJApply = WrappedComponent => class extends Component {
diyFunction = () => {
this.instanceComponent.handleButtonSet = () => {
let that = this.instanceComponent;
const { addFields, workId, tableInfo } = that.state;
const bankNumIndex = getIndex(addFields, '工商银行卡号');
const defaultValues = getDefaultValues(addFields, tableInfo);
const beforeSubmit = (data, ModalFormComponent) => {
const bankKey = addFields[bankNumIndex].key;
if(data[bankKey] && data[bankKey].replace(/\s/g,"").length !== 19){
message.warning('请输入正确的19位工商银行卡卡号');
return false;
}
return data;
};
return [
{
type: 'add',
name: '申请',
component: 'ModalForm',
workId,
fields: addFields,
modalWidth: 800,
values: {
...defaultValues,
},
beforeSubmit,
nameSpan: { big: 6, small: 6 },
fileSpan: { big: 1, small: 1 },
},
];
};
};
componentDidMount() {
console.log(this.instanceComponent);
this.diyFunction();
}
render() {
return (
<WrappedComponent
ref={instanceComponent => this.instanceComponent = instanceComponent}
/>
);
}
};
export default KNXSRDApply(ApplyPage); // 高阶组件
/**
* 困难学生家庭情况调查-申请
* 钟是志
* 2019年11月6日
* 因业务复杂只能特殊开发
* */
import React, { Component } from 'react';
import ApplyPage from '../index';
import { getDefaultValues } from '../../destruction';
import { deepCopy } from '@/baseComponent/utils';
const getIndex = (arr, name) => {
return arr.findIndex((x) => {
return x.name === name;
});
};
const KNXSJTQKSQ = WrappedComponent => class extends Component {
diyFunction = () => {
this.instanceComponent.handleButtonSet = () => {
let that = this.instanceComponent;
const { addFields, workId, tableInfo } = that.state;
const familyTypeIndex = getIndex(addFields, '家庭类型');
const fileIndex = getIndex(addFields, '家庭类型证明材料');
const famliyMemberIndex = getIndex(addFields, '家庭成员(不含自己)');
const famliyMoneyIndex = getIndex(addFields, '家庭人均年收入(元)');
const familyNumberIndex = getIndex(addFields, '家庭人口数');
const defaultValues = getDefaultValues(addFields, tableInfo);
const diyFormStateChange = (value, key, ModalFormComponent) => {
let oldValue = ModalFormComponent.state.formValues;
if (typeof value === 'object') {
oldValue[key] = deepCopy(value);
} else {
oldValue[key] = value;
}
if (familyTypeIndex >= 0 && key === addFields[familyTypeIndex].key) { // 改变家庭类型时.
let testOne = value.substring(0, 1);
if ([2, 3, 4, 5, 6, 7].indexOf(Number(testOne)) > -1) {
// 如果学生勾选了项目234567,就必须要上传附件;
addFields[fileIndex].required = true;
} else {
addFields[fileIndex].required = false;
}
that.setState({ addFields });
}
if (famliyMemberIndex >= 0 && key === addFields[famliyMemberIndex].key) { // 改变家庭成员时
let money = 0;
const famliyMemberFileds = addFields[famliyMemberIndex].componentProps.thisFields;
const onePersonIndex = getIndex(famliyMemberFileds, '年收入(元)');
for (let item of value) {
money = money + item[famliyMemberFileds[onePersonIndex].key];
}
oldValue[addFields[famliyMoneyIndex].key] = parseInt(money / (value.length + 1 ), 10); // 计算家庭平均年收入
oldValue[addFields[familyNumberIndex].key] = value.length + 1; // 计算家庭人数
}
ModalFormComponent.setState({
formValues: oldValue,
});
};
return [
{
type: 'add',
name: '申请',
component: 'ModalForm',
diyFormStateChange,
workId,
fields: addFields,
modalWidth: 800,
values: {
...defaultValues,
},
nameSpan: { big: 6, small: 6 },
fileSpan: { big: 1, small: 1 },
},
];
};
};
componentDidMount() {
console.log(this.instanceComponent);
this.diyFunction();
}
render() {
return (
<WrappedComponent
ref={instanceComponent => this.instanceComponent = instanceComponent}
/>
);
}
};
export default KNXSJTQKSQ(ApplyPage); // 高阶组件
/**
* 困难学生申请
* 钟是志
* 2019年11月6日
* 因业务复杂只能特殊开发
* */
import React, { Component } from 'react';
import ApplyPage from '../index';
import { getDefaultValues } from '../../destruction';
import { message } from 'antd';
const getIndex = (arr, name) => {
return arr.findIndex((x) => {
return x.name === name;
});
};
const KNXSRDApply = WrappedComponent => class extends Component {
diyFunction = () => {
this.instanceComponent.handleButtonSet = () => {
let that = this.instanceComponent;
const { addFields, workId, tableInfo } = that.state;
const bankNumIndex = getIndex(addFields, '工商银行卡号');
const defaultValues = getDefaultValues(addFields, tableInfo);
const beforeSubmit = (data, ModalFormComponent) => {
const bankKey = addFields[bankNumIndex].key;
if(data[bankKey] && data[bankKey].replace(/\s/g,"").length !== 19){
message.warning('请输入正确的19位工商银行卡卡号');
return false;
}
return data;
};
return [
{
type: 'add',
name: '申请',
component: 'ModalForm',
workId,
fields: addFields,
modalWidth: 800,
values: {
...defaultValues,
},
beforeSubmit,
nameSpan: { big: 6, small: 6 },
fileSpan: { big: 1, small: 1 },
},
];
};
};
componentDidMount() {
console.log(this.instanceComponent);
this.diyFunction();
}
render() {
return (
<WrappedComponent
ref={instanceComponent => this.instanceComponent = instanceComponent}
/>
);
}
};
export default KNXSRDApply(ApplyPage); // 高阶组件
import React, { Component, Fragment } from 'react';
import SearchDom from '@/highOrderComponent/SearchDom';
import ButtonListDom from '../ButtonListDom';
import Shell from '@/baseComponent/Shell';
import ColumnsRender from '@/highOrderComponent/ColumnsRender';
import StandardTable from '@/components/StandardTable';
import PropTypes from 'prop-types';
import { deepCopy } from '@/baseComponent/utils';
import { date, format, text } from '../../config';
import moment from 'moment';
import { Tooltip } from 'antd';
export default class List extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
selectRows: [],
formValues: this.giveDefaultValue(props),
loading: true,
sortGetPageFields: {},
pagination: {
current: 1,
total: 1,
pageSize: this.props.listConfig.pageSize || 10,
pageSizeOptions: ['10', '20', '50', '100', '500'],
showQuickJumper: true,
onShowSizeChange: (current, size) => {
this.pageChange(current, size);
},
onChange: (current, size) => {
this.pageChange(current, size);
},
},
};
}
giveDefaultValue = (props) => {
// 如果设置了 giveFieldsToFormValues 则将默认值赋值给formValues
let formValues = {};
if(props.pageSearch && props.pageSearch.search && props.pageSearch.search.giveFieldsToFormValues){
for(let x in props.pageSearch.search.field){
if(props.pageSearch.search.field[x].required === true){
formValues[x] = props.pageSearch.search.field[x].defaultValue;
}
}
}
return formValues;
};
giveGetPageFields = () => {
const { listConfig, pageSearch, beforeGetPage } = this.props;
const { pagination, formValues } = this.state;
const search = pageSearch.search;
let data = deepCopy(formValues);
/** 如果配置了默认值 则 加进去 **/
for (let item in search.field) {
let one = search.field[item];
if (one.required && (typeof data[item] === 'undefined')) {
/**
* 存在必填项 且当前必填项没有值时 则传入. 如果必填项有值则不需要修改
* */
data[item] = one.defaultValue;
}
}
if (listConfig.paging) { // 是否分页
data.pageSize = pagination.pageSize;
data.pageNo = pagination.current;
}
if(search.beforeGetPage){
data = search.beforeGetPage(data);
}
return data;
};
getPage = () => {
const { listConfig, pageSearch, dataBaseId, workId, addFields } = this.props;
const { pagination, sortGetPageFields } = this.state;
const { search } = pageSearch;
let data = this.giveGetPageFields();
if(!data){
return false;
}
if(search.handleSort){
data = {
...data,
...sortGetPageFields, // 增加排序的搜索条件
}
}
this.setState({
list: [],
loading: true,
});
search.getPageService({ ...data, appId: workId }).then((response) => {
this.setState({
loading: false,
});
if (!response || (search.paging && typeof response.total === 'undefined') || response.errMsg) {
return false;
}
if (listConfig.paging) {
pagination.total = Number(response.total);
}
if (typeof search.responseCallBack !== 'undefined') {
response = search.responseCallBack(response);
}
this.setState({
list: response.rows || response,
selectRows: [],
pagination: pagination,
});
});
};
stateChange = (key, value) => {
this.setState({
[key]: value,
});
};
pageChange = (current, size) => {
this.setState({
pagination: {
...this.state.pagination,
current: current,
pageSize: size,
},
}, () => {
this.getPage();
});
};
formStateChange = (value, key) => {
const { search } = this.props.pageSearch;
const { condition } = search;
let oldValue = this.state.formValues;
oldValue[key] = value;
/**
* 如果设置了beforeChange回调函数 则调用此回调函数改变另外的字段的值
* */
const index = condition.findIndex((item)=>{
return item.key === key;
});
if(index !== -1){
const thisConfig = condition[index];
if(thisConfig.beforeChange){
oldValue = thisConfig.beforeChange(oldValue,thisConfig);
}
}
this.setState({
formValues: oldValue,
},()=>{
if(search.afterFormValuesChange){
search.afterFormValuesChange(key, oldValue, this.getPage);
}
});
};
handleSelectRows = rows => {
this.setState({
selectRows: rows,
});
};
componentDidMount() {
const { search } = this.props.pageSearch;
if(!search.noNeedInitData){
this.getPage();
}
}
componentWillMount() {
}
componentWillUnmount(){
}
resetFormValues = () => {
const { beforeResetFormValues } = this.props.pageSearch.search;
let { formValues } = this.state;
if(beforeResetFormValues){
formValues = beforeResetFormValues(formValues);
}else{
formValues = {} ;
}
this.setState({
formValues,
})
};
/**
* 处理排序
* */
handleOnChange = (pagination, filters, sorter) => {
const { pageSearch } = this.props;
if(sorter){
const sortGetPageFields = pageSearch.search.handleSort(sorter);
this.setState({
sortGetPageFields,
},()=>{
this.getPage();
})
}
};
render() {
const { formValues, selectRows, list, pagination, loading } = this.state;
const { listConfig, pageSearch, pageButton ,children, addFields} = this.props;
const { columns, search } = pageSearch;
for(let item of columns){
if(typeof item.renderConfig !== 'undefined' && !item.render){
item.render = (text,record)=>{
return <ColumnsRender text={text}
getPage={this.getPage}
config={item.renderConfig}
record={record} />
}
}
if (item.dataType && text.indexOf(item.dataType)> -1){
item.render = (text) => {
if (typeof text === 'string' && text.length > 20) {
const oldTitle = text;
const newTitle = text.slice(0, 7) + '...';
return (
<Tooltip title={oldTitle} key={oldTitle} style={{ width: 260 }}>
<span key={text}>{newTitle}</span>
</Tooltip>
);
} else if (typeof text === 'object' && Array.isArray(text.files) && text.files.length){
return <a href={text.files[0].path} target={'_blank'}>点击查看</a>;
}else{
return text;
}
}
}
if(item.dataType && date.indexOf(item.dataType) > -1){
item.render = (text, record) => {
if(!text){
return '';
}
if(!isNaN(parseInt(text)) && parseInt(text) > 10000000 ){
text = parseInt(text);
}
return moment(text).format(format[item.dataType]);
};
}
if(item.dataIndex === 'rate'){
item.render = (text, record) => {
if(text || text == 0){
return Number(text) + '%';
}else{
return '';
}
}
}
}
let data = list;
for(let item of addFields){
if(item.type === 'tableSelect' && item.c1){
for(let i = 0; i < data.length; i++ ){
let nameKey = item.componentProps.labelName;
if(data[i][item.c1] && data[i][item.c1].selects){
let res = [];
for(let x in data[i][item.c1].selects){
res.push(data[i][item.c1].selects[x][nameKey]);
}
data[i][item.c1] = res.join(',');
}
}
}
}
const tableProps = {
rowKey: pageSearch.tableRowKey || 'id',
selectedRows: selectRows,
data: {list: data, pagination},
columns,
bordered: pageSearch.bordered || false,
loading,
noSelectRow: !listConfig.selectRows,
onSelectRow: this.handleSelectRows,
};
if(!listConfig.paging){
tableProps.data = {list: data, pagination:false};
}
if(search && search.handleSort){
tableProps.onChange = this.handleOnChange;
}
return (
<Fragment>
{listConfig.searchArea ?
<SearchDom formStateChange={this.formStateChange}
formValues={formValues}
getPage={this.getPage}
resetFormValues={this.resetFormValues}
config={pageSearch.search}
/> : null}
<Shell>
{listConfig.buttonArea ?
<ButtonListDom config={pageButton}
handleSelectRows={this.handleSelectRows}
selectRows={selectRows}
formValues={formValues}
listData={list}
search={pageSearch.search}
getPage={this.getPage}
children={children}
/> : null}
<StandardTable {...tableProps}/>
</Shell>
</Fragment>
);
}
}
List.propTypes = {
listConfig: PropTypes.object.isRequired,
// pageButton: PropTypes.array,
pageSearch: PropTypes.object.isRequired,
};
List.defaultProps = {
listConfig: {
selectRows: true, // 是否可以行选择,
paging: true, // 是否可以分页,
searchArea: true, // 是否拥有 搜索区dom,
buttonArea: true, // 是否拥有 按钮区,
},
pageSearch: {
search: {
url: '',
field: {
},
responseCallBack: (response) => {
return response;
},
condition: [
{
key: 'studentNo',
name: '学号',
type: 'input',
},
],
tableRowKey: 'id',
columns: [
{
title: '姓名',
dataIndex: '',
},
{
title: '操作',
dataIndex: 'operation',
renderType: 'update', // 修改
},
],
nameSpan: { big: 8, small: 9 },
fileSpan: { big: 4, small: 4 },
},
},
};
/**
* 事务页面。 根据一站式服务大厅的事务接口。达到增删发起事务流程
* 2019年10月23日 09:48:13
* 钟是志
*
* */
import { message } from 'antd';
import React, { Fragment } from 'react';
import * as service from '../publicApiService';
import * as destructionFunc from '../destruction';
import { Link, hashHistory } from 'dva/router';
import { getDefaultValues } from '../destruction';
import { getApplyPage } from '../publicApiService';
import { getHuanGeToken } from '@/utils/authority';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import List from './List';
import pageSetting from './pageSetting';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import Shell from '@/baseComponent/Shell';
import config from '@/config/config';
// import test from './2333';
export default class AffairPage extends React.Component {
constructor(props) {
super(props);
// const idObj = service.getId();
if (!idObj) {
message.error('没有配置数据id,无法使用该功能');
}
this.state = {
showIframe: false,
columns: [],
workId: idObj.workId,
searchCondition: [],
dataBaseId: idObj.dataBaseId,
addFields: [], // 新增时填写的字段。
};
};
getFormDetail = (workId) => {
service.getFormDetail(workId).then((response) => {
if (typeof response.unifiedServicePatternModel === 'undefined') {
return false;
}
destructionFunc.destructionGetDetail(response).then((x) => {
const { addFields, tableInfo, allConfigSetInfo } = x;
this.setState({
addFields,
tableInfo,
allConfigSetInfo,
}, () => {
this.giveDetailColumns();
});
});
});
};
giveDetailColumns = () => {
const { columns, workId, dataBaseId, addFields } = this.state;
columns.push(
{
dataIndex: 'operation',
title: '操作',
fixed: columns.length > 12 ? 'right' : false,
render: (text, record) => {
return (<Link to={
{
pathname: './Detail',
state: {
workId,
dataBaseId,
record,
addFields,
},
}}>
详情
</Link>);
},
},
);
this.setState({
columns,
});
};
handleButtonSet = () => {
return [
{
type: 'add',
name: '申请',
component: 'Normal',
handleClick: () => {
this.setState({
showIframe: true,
}, () => {
});
},
},
];
};
handleSearchSet = () => {
const { columns, searchCondition } = this.state;
const pageSearch = {
search: {
field: {},
getPageService: getApplyPage,
responseCallBack: (response) => {
return response;
},
condition: searchCondition,
nameSpan: { big: 8, small: 9 },
fileSpan: { big: 4, small: 4 },
},
tableRowKey: 'id',
columns,
};
return pageSearch;
};
componentDidMount() {
if (!getHuanGeToken()) {
message.error('您的数据未同步,请联系管理员!');
return false;
}
const { workId } = this.state;
service.getColumns(workId).then((response) => {
if (response) {
this.setState({
columns: response,
}, () => {
this.getFormDetail(workId);
});
}
});
window.addEventListener('message', (event) => {
if (event.data === 'returnList') {
this.setState({
showIframe: false,
}, () => {
this.ListComponent.getPage();
});
}
if(event.data.indexOf('iframeHeight') > -1){
let height = Number(event.data.split('-')[1]);
document.getElementById('applyIframeId').height = height;
}
}, false);
return true;
}
render() {
const { workId, dataBaseId, addFields, showIframe } = this.state;
const url = config.onestopPC.split('/#/');
let iframeUrl = `${url[0]}/#/IFrameForApply?id=${workId}&token=${getHuanGeToken()}`;
// iframeUrl = `http://localhost:8000/onestop/IFrameForApply?id=${workId}&token=${getHuanGeToken()}`;
return (
<PageHeaderWrapper title="">
<div style={{
display: showIframe ? 'none' : 'block',
}}>
<List listConfig={pageSetting.listConfig}
pageButton={this.handleButtonSet({})}
pageSearch={this.handleSearchSet({})}
addFields={addFields}
ref={ListComponent => this.ListComponent = ListComponent}
workId={workId}
dataBaseId={dataBaseId}
/>
</div>
<div style={{
visibility: showIframe ? 'visible' : 'hidden',
width: '100%',
backgroundColor: '#fff',
paddingLeft: '24px',
}}>
<Shell>
<div style={{
height: '54px',
padding: '12px 0 12px 12px',
display: showIframe ? 'block' : 'none',
}}>
<ButtonDiy name="返回"
className="defaultBlue"
handleClick={() => {
this.setState({
showIframe: false,
});
}}
icon="arrow-left"
/>
</div>
</Shell>
<iframe src={iframeUrl}
frameBorder={0}
id='applyIframeId'
name='applyIframe'
marginWidth="0"
marginHeight="0"
allowTransparency="yes"
seamless
scrolling={'no'}
style={{
width: '100%',
minHeight: '800px',
overflowY: 'hidden',
backgroundColor: '#fff',
}}
/>
</div>
</PageHeaderWrapper>
);
}
}
const pageSetting = {
type: 'list', // 页面类型 list列表 可能包含有其他类型的 比如 detail 详情 add 新增 update 更新 等等 ....
listConfig:{
selectRows: true, // 是否可以行选择,
paging: true, // 是否可以分页,
searchArea: false, // 是否拥有 搜索区dom,
buttonArea: true, // 是否拥有 按钮区,
}
};
export default pageSetting;
import pageSetting from './pageSetting';
import React, { Component, Fragment } from 'react';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import List from '../ApplyPage/List';
import ListTab from './ListTab';
import { deepCopy } from '@/baseComponent/utils';
import { getApplyPage, getHandledPage, getWaitPage } from '@/pages/App/FormInsertDiy/AffairPage/publicApiService';
export default class AuditPage extends Component {
constructor(props) {
super(props);
this.state={
}
};
componentDidMount(){
}
handleButtonSet = () => {
const { addFields, workId } = this.props;
return {
tab1: [
],
tab2: [],
};
};
handleSearchSet = () => {
const { columns, searchCondition} = this.props;
const tab1 = {
search: {
field: {
},
getPageService: getWaitPage,
responseCallBack: (response) => {
return response;
},
condition: searchCondition,
nameSpan: { big: 8, small: 9 },
fileSpan: { big: 4, small: 4 },
},
tableRowKey: 'id',
columns,
};
const tab2 = {
search: {
field: {
},
getPageService: getHandledPage,
responseCallBack: (response) => {
return response;
},
condition: searchCondition,
nameSpan: { big: 8, small: 9 },
fileSpan: { big: 4, small: 4 },
},
tableRowKey: 'id',
columns,
};
return {
tab1,
tab2,
};
};
render() {
const { workId, dataBaseId, addFields } = this.props;
return (
<PageHeaderWrapper title="">
<ListTab tabList={pageSetting.tabList}
pageButton={this.handleButtonSet({
})}
workId={workId}
dataBaseId={dataBaseId}
addFields={addFields}
pageSearch={this.handleSearchSet({
})}/>
</PageHeaderWrapper>
);
}
}
import React, { Component, Fragment } from 'react';
import SearchDom from '@/highOrderComponent/SearchDom';
import ButtonListDom from '../ButtonListDom';
import Shell from '@/baseComponent/Shell';
import ColumnsRender from '@/highOrderComponent/ColumnsRender';
import * as services from '@/highOrderComponent/Service';
import StandardTable from '@/components/StandardTable';
import PropTypes from 'prop-types';
import { deepCopy } from '@/baseComponent/utils';
import { date, format, text } from '@/pages/App/FormInsertDiy/config';
import moment from 'moment';
import { handleAudit } from '@/pages/App/FormInsertDiy/AffairPage/publicApiService';
import { Tooltip } from 'antd';
export default class List extends Component {
constructor(props) {
super(props);
this.state = {
list: [],
selectRows: [],
formValues: this.giveDefaultValue(props),
loading: true,
sortGetPageFields: {},
pagination: {
current: 1,
total: 1,
pageSize: this.props.listConfig.pageSize || 10,
pageSizeOptions: ['10', '20', '50', '100', '500'],
showQuickJumper: true,
onShowSizeChange: (current, size) => {
this.pageChange(current, size);
},
onChange: (current, size) => {
this.pageChange(current, size);
},
},
};
}
giveDefaultValue = (props) => {
// 如果设置了 giveFieldsToFormValues 则将默认值赋值给formValues
let formValues = {};
if(props.pageSearch && props.pageSearch.search && props.pageSearch.search.giveFieldsToFormValues){
for(let x in props.pageSearch.search.field){
if(props.pageSearch.search.field[x].required === true){
formValues[x] = props.pageSearch.search.field[x].defaultValue;
}
}
}
return formValues;
};
giveGetPageFields = () => {
const { listConfig, pageSearch, beforeGetPage } = this.props;
const { pagination, formValues } = this.state;
const search = pageSearch.search;
let data = deepCopy(formValues);
/** 如果配置了默认值 则 加进去 **/
for (let item in search.field) {
let one = search.field[item];
if (one.required && (typeof data[item] === 'undefined')) {
/**
* 存在必填项 且当前必填项没有值时 则传入. 如果必填项有值则不需要修改
* */
data[item] = one.defaultValue;
}
}
if (listConfig.paging) { // 是否分页
data.pageSize = pagination.pageSize;
data.pageNo = pagination.current;
}
if(search.beforeGetPage){
data = search.beforeGetPage(data);
}
return data;
};
getPage = () => {
const { listConfig, pageSearch, dataBaseId, workId, getpageService } = this.props;
const { pagination, sortGetPageFields } = this.state;
const { search } = pageSearch;
let data = this.giveGetPageFields();
if(!data){
return false;
}
if(search.handleSort){
data = {
...data,
...sortGetPageFields, // 增加排序的搜索条件
}
}
this.setState({
list: [],
loading: true,
});
search.getPageService({ ...data, appId: workId }).then((response) => {
this.setState({
loading: false,
});
if (!response || (search.paging && typeof response.total === 'undefined') || response.errMsg) {
return false;
}
if (listConfig.paging) {
pagination.total = Number(response.total);
}
if (typeof search.responseCallBack !== 'undefined') {
response = search.responseCallBack(response);
}
this.setState({
list: response.rows || response,
selectRows: [],
pagination: pagination,
});
});
};
stateChange = (key, value) => {
this.setState({
[key]: value,
});
};
pageChange = (current, size) => {
this.setState({
pagination: {
...this.state.pagination,
current: current,
pageSize: size,
},
}, () => {
this.getPage();
});
};
formStateChange = (value, key) => {
const { search } = this.props.pageSearch;
const { condition } = search;
let oldValue = this.state.formValues;
oldValue[key] = value;
/**
* 如果设置了beforeChange回调函数 则调用此回调函数改变另外的字段的值
* */
const index = condition.findIndex((item)=>{
return item.key === key;
});
if(index !== -1){
const thisConfig = condition[index];
if(thisConfig.beforeChange){
oldValue = thisConfig.beforeChange(oldValue,thisConfig);
}
}
this.setState({
formValues: oldValue,
},()=>{
if(search.afterFormValuesChange){
search.afterFormValuesChange(key, oldValue, this.getPage);
}
});
};
handleSelectRows = rows => {
this.setState({
selectRows: rows,
});
};
componentDidMount() {
const { search } = this.props.pageSearch;
if(!search.noNeedInitData){
this.getPage();
}
}
componentWillMount() {
}
componentWillUnmount(){
}
resetFormValues = () => {
const { beforeResetFormValues } = this.props.pageSearch.search;
let { formValues } = this.state;
if(beforeResetFormValues){
formValues = beforeResetFormValues(formValues);
}else{
formValues = {} ;
}
this.setState({
formValues,
})
};
/**
* 处理排序
* */
handleOnChange = (pagination, filters, sorter) => {
const { pageSearch } = this.props;
if(sorter){
const sortGetPageFields = pageSearch.search.handleSort(sorter);
this.setState({
sortGetPageFields,
},()=>{
this.getPage();
})
}
};
pageButton = () => {
return [];
const { list } = this.state;
let re = {};
let buttonConfig = [];
for(let item of list){
if(item.btns && Array.isArray(item.btns)){
for( let x of item.btns){
if(typeof re[x.name] === 'undefined'){
re[x.name] = x;
}
}
}
}
for(let z in re){
let info = re[z];
buttonConfig.push(
{
type: z,
name: z,
component: 'ModalBatch',
className: z !== '通过' ? 'defaultRed' : 'defaultBlue',
nameSpan: { big: 4, small: 5 },
fileSpan: { big: 1, small: 1 },
values: {
[info.key]: info.value,
},
fields: [
{
key: 'reason',
name: '审核意见',
type: 'textarea',
},
],
beforeSubmit: (props, formValues) => {
return {
taskForm : {},
examineMap: JSON.stringify(formValues),
};
},
sourceKey: 'taskId',
postKey: 'taskIds',
apiServiceApi: handleAudit,
}
)
}
return buttonConfig;
};
render() {
const { formValues, selectRows, list, pagination, loading } = this.state;
const { listConfig, pageSearch, pageButton ,children, addFields} = this.props;
const { columns, search } = pageSearch;
for(let item of columns){
if(typeof item.renderConfig !== 'undefined' && !item.render){
item.render = (text,record)=>{
return <ColumnsRender text={text}
getPage={this.getPage}
config={item.renderConfig}
record={record} />
}
}
if(item.dataType && date.indexOf(item.dataType) > -1){
item.render = (text, record) => {
if(!text){
return '';
}
if(!isNaN(parseInt(text)) && parseInt(text) > 10000000 ){
text = parseInt(text);
}
return moment(text).format(format[item.dataType]);
};
}
if (item.dataType && text.indexOf(item.dataType)> -1){
item.render = (text) => {
if (typeof text === 'string' && text.length > 20) {
const oldTitle = text;
const newTitle = text.slice(0, 7) + '...';
return (
<Tooltip title={oldTitle} key={oldTitle} style={{ width: 260 }}>
<span key={text}>{newTitle}</span>
</Tooltip>
);
} else if (typeof text === 'object' && Array.isArray(text.files) && text.files.length){
return <a href={text.files[0].path} target={'_blank'}>点击查看</a>;
}else{
return text;
}
}
}
if(item.dataIndex === 'rate'){
item.render = (text, record) => {
if(text || text == 0){
return Number(text) + '%';
}else{
return '';
}
}
}
}
let data = list;
for(let item of addFields){
if(item.type === 'tableSelect' && item.c1){
for(let i = 0; i < data.length; i++ ){
let nameKey = item.componentProps.labelName;
if(data[i][item.c1] && data[i][item.c1].selects){
let res = [];
for(let x in data[i][item.c1].selects){
res.push(data[i][item.c1].selects[x][nameKey]);
}
data[i][item.c1] = res.join(',');
}
}
}
}
const tableProps = {
rowKey: pageSearch.tableRowKey || 'id',
selectedRows: selectRows,
data: {list: data, pagination},
columns,
bordered: pageSearch.bordered || false,
loading,
noSelectRow: !listConfig.selectRows,
onSelectRow: this.handleSelectRows,
};
if(!listConfig.paging){
tableProps.data = {list: data, pagination:false};
}
if(search && search.handleSort){
tableProps.onChange = this.handleOnChange;
}
return (
<Fragment>
{listConfig.searchArea ?
<SearchDom formStateChange={this.formStateChange}
formValues={formValues}
getPage={this.getPage}
resetFormValues={this.resetFormValues}
config={pageSearch.search}
/> : null}
<Shell>
{this.pageButton().length ?
<ButtonListDom config={this.pageButton()}
handleSelectRows={this.handleSelectRows}
selectRows={selectRows}
formValues={formValues}
listData={list}
search={pageSearch.search}
getPage={this.getPage}
children={children}
/> : null}
<StandardTable {...tableProps}/>
</Shell>
</Fragment>
);
}
}
List.propTypes = {
listConfig: PropTypes.object.isRequired,
// pageButton: PropTypes.array,
pageSearch: PropTypes.object.isRequired,
};
List.defaultProps = {
listConfig: {
selectRows: true, // 是否可以行选择,
paging: true, // 是否可以分页,
searchArea: true, // 是否拥有 搜索区dom,
buttonArea: true, // 是否拥有 按钮区,
},
pageSearch: {
search: {
url: '',
field: {
// status:{
// required: true,
// defaultValue: undefined,
// 如果有查询的字段必填且defaultValue=undefined 应该在页面的constructor方法中 通过各种方法把默认值传进去.
// }
},
responseCallBack: (response) => {
return response;
},
condition: [
{
key: 'studentNo',
name: '学号',
type: 'input',
},
],
tableRowKey: 'id',
columns: [
{
title: '姓名',
dataIndex: '',
},
{
title: '操作',
dataIndex: 'operation',
renderType: 'update', // 修改
},
],
nameSpan: { big: 8, small: 9 },
fileSpan: { big: 4, small: 4 },
},
},
};
import React, { Component, Fragment } from 'react';
import { Tabs } from 'antd';
import styles from '@/baseComponent/index.less';
import PropTypes from 'prop-types';
import Shell from '@/baseComponent/Shell';
import List from './List';
const TabPane = Tabs.TabPane;
export default class ListTab extends Component {
constructor(props) {
super(props);
const { tabList } = this.props;
const tabKeys = Object.keys(tabList);
this.state = {
activeKey: tabKeys[0],
tabKeys: tabKeys,
};
}
handleChangeTab = (activeKey) => {
this.setState({
activeKey: '-111111',
},()=>{
setTimeout(()=>{
this.setState({
activeKey: activeKey,
})
} ,30);
});
};
render() {
const { tabList, pageSearch, pageButton, workId, dataBaseId, addFields } = this.props;
const { activeKey, tabKeys } = this.state;
return (
<Fragment>
<Shell>
<Tabs activeKey={activeKey}
className={styles.ListTab}
onChange={this.handleChangeTab}>
{tabKeys.map((item) => {
return <TabPane tab={tabList[item].name} key={item}>
</TabPane>
})}
</Tabs>
</Shell>
{tabKeys.map((item) => {
return activeKey === item ?
<List listConfig={tabList[item].listConfig}
key={item}
workId={workId}
addFields={addFields}
dataBaseId={dataBaseId}
pageSearch={pageSearch[item]}
pageButton={pageButton[item]}
/> : null;
})}
</Fragment>
);
}
}
ListTab.propTypes = {};
ListTab.defaultProps = {};
/**
* 事务页面。 根据一站式服务大厅的事务接口。达到增删发起事务流程
* 2019年10月23日 09:48:13
* 钟是志
*
* */
import { Row, Col, message } from 'antd';
import React, { Fragment } from 'react';
import * as service from '../publicApiService';
import AuditPage from './AuditPage';
import * as destructionFunc from '../destruction';
import { Link ,hashHistory} from 'dva/router';
export default class Index extends React.Component {
constructor(props) {
super(props);
// const idObj = service.getId();
if (!idObj) {
message.error('没有配置数据id,无法使用该功能');
}
this.state = {
columns: [],
dataList: [],
headerInfo: [],
workId: idObj.workId,
searchCondition: [],
dataBaseId: idObj.dataBaseId,
addCondition: [],
addFields: [], // 新增时填写的字段。
tableInfo: {}, // 表格配置属性
allConfigSetInfo: {}, // getFormDetail 返回的数据
};
};
getFormDetail = (workId) => {
const { dataBaseId } = this.state;
/*service.getQueryCondition(dataBaseId).then((response) => {
this.setState({searchCondition: response})
});*/
service.getFormDetail(workId).then((response) => {
if (typeof response.unifiedServicePatternModel === 'undefined') {
return false;
}
destructionFunc.destructionGetDetail(response).then((x) => {
const { addFields, tableInfo, allConfigSetInfo } = x;
this.setState({
addFields,
tableInfo,
allConfigSetInfo,
},() => {
this.giveDetailColumns();
});
});
});
};
giveDetailColumns = () =>{
const { columns, workId, dataBaseId, addFields, tableInfo } = this.state;
columns.push(
{
dataIndex: 'operation',
title: '操作',
fixed: columns.length > 12 ? 'right' : false,
render: (text, record) => {
return ( <Link to={
{
pathname: "./Detail",
state: {
workId,
dataBaseId,
record,
addFields,
tableInfo
},
}}>
详情
</Link> );
},
},
);
this.setState({
columns,
})
};
componentDidMount() {
const { workId, dataBaseId, addFields } = this.state;
service.getColumns(workId).then((response) => {
if (response && response.length) {
this.setState({
columns: response, // 表头
},()=>{
this.getFormDetail(workId);
});
}
});
}
render() {
const { workId, dataBaseId, columns, searchCondition, addFields, allConfigSetInfo, tableInfo } = this.state;
return (
<AuditPage
workId={workId}
dataBaseId={dataBaseId}
columns={columns}
addFields={addFields}
tableInfo={tableInfo}
allConfigSetInfo={allConfigSetInfo}
searchCondition={searchCondition}
/>
);
}
}
const pageSetting = {
type: 'listTab', // 页面类型
tabList: {
tab1:{
name:'待处理',
listConfig:{
selectRows: true, // 是否可以行选择,
paging: true, // 是否可以分页,
searchArea: false, // 是否拥有 搜索区dom,
buttonArea: true, // 是否拥有 按钮区,
}
},
tab2:{
name:'已处理',
listConfig:{
selectRows: true, // 是否可以行选择,
paging: true, // 是否可以分页,
searchArea: false, // 是否拥有 搜索区dom,
buttonArea: true, // 是否拥有 按钮区,
}
},
},
};
export default pageSetting;
/**
* 赖井平
* 2019年3月2日
* 用于 批量弹窗操作
* */
import ButtonDiy from '@/baseComponent/ButtonDiy';
import ModalDiy from '@/baseComponent/ModalDiy';
import FormArray from '../component/FormArray';
import React, { Component, Fragment } from 'react';
import { checkDate } from '@/baseComponent/utils';
import { message } from 'antd';
import PropTypes from 'prop-types';
export default class ModalBatch extends Component {
constructor(props) {
super(props);
const { values } = this.props;
this.state = {
showModal: false,
formValues: { ...values }, // 将默认值传进去 用于新增时可能遇到的需要传值的情况
};
}
componentWillUnmount() {
}
changeShow = () => {
const { beforeShowModel, selectRows, initFormValues } = this.props;
const { formValues, showModal } = this.state;
if (!selectRows.length && !this.state.showModal) {
message.warning('请至少选择一条数据');
return false;
}
if(initFormValues && !showModal){
initFormValues(selectRows,formValues).then((response)=>{
this.setState({
formValues: response ,
},()=>{
//console.log(this.state.formValues);
})
});
}
/**
* 设置modal是否显示
* */
let flag;
if (!showModal && beforeShowModel) {
beforeShowModel(this.props, ({ text, type, isNotShow }) => {
flag = isNotShow;
if (isNotShow && text) {
message[type](text);
}
});
}
if (flag) {
return false;
}
/**
* 设置modal是否显示
* */
this.clearData();
this.setState({
showModal: !showModal,
});
};
formStateChange = (value, key) => {
let oldValue = this.state.formValues;
oldValue[key] = value;
this.setState({
formValues: oldValue,
});
};
clearData = () => {
const { values, giveDefaultValue, selectRows} = this.props;
let formValues = {
...values,
};
if(giveDefaultValue){
formValues = giveDefaultValue(selectRows,formValues);
}
this.setState({
formValues,
});
};
handleOk = () => {
let { formValues } = this.state;
let param = { ...formValues };
const { fields, url, responseCallBack, getPage,
beforeSubmit, selectRows, postKey, sourceKey,
handleSelectRows, apiServiceApi } = this.props;
for (let item of fields) {
if (item.required && !formValues[item.key] && formValues[item.key] !== 0) {
message.warning(`${item.name}是必填项,请填写`);
return false;
}
/**
* 校验开始时间必须在结束时间之前
* */
if (item.rule && item.rule === 'mustAfterStart') {
const check = checkDate(formValues[item.key], formValues[item.checkKey]);
if (!check) {
message.warning(`${item.name}必须在${item.checkKeyName}之后`);
return false;
}
}
}
param[postKey] = selectRows.map((item) => {
return item[sourceKey];
});
if (beforeSubmit) {
let postData = beforeSubmit(this.props, formValues);
param = {
...param,
...postData,
};
}
apiServiceApi(param).then((response) => {
if (response) {
if (responseCallBack && !responseCallBack(response)) {
this.changeShow();
return false;
} else {
handleSelectRows([]);
message.success('保存成功');
this.changeShow();
getPage();
}
} else {
this.changeShow();
return false;
}
});
};
render() {
const { showModal, formValues } = this.state;
const { name, className, fields, nameSpan, fileSpan } = this.props;
return (
<Fragment>
<ButtonDiy name={name}
className={className}
handleClick={this.changeShow}/>
{showModal ?
<ModalDiy handleOk={this.handleOk}
title={name}
handleCancel={this.changeShow}
>
<FormArray config={fields}
value={formValues}
changeValue={this.formStateChange}
nameSpan={nameSpan}
fileSpan={fileSpan}
style={{ paddingTop: '0px' }}
/>
</ModalDiy> : null}
</Fragment>);
}
}
ModalBatch.propTypes = {
name: PropTypes.string, // 按钮名称和 弹窗的标题
className: PropTypes.string, // 按钮样式
fields: PropTypes.array.isRequired, // 填写的字段的配置
values: PropTypes.object, // 如果有默认参数 则在页面的业务逻辑中传进来
url: PropTypes.string.isRequired, // 接口url
responseCallBack: PropTypes.func, // 接口返回数据检查
getPage: PropTypes.func, // 刷新页面的方法
nameSpan: PropTypes.object, // 页面排版
fileSpan: PropTypes.object, // 页面排版
};
ModalBatch.defaultProps = {
name: '新增',
className: 'primaryBlue',
values: {},
sourceKey: 'id',
postKey: 'ids',
selectRows: [],
url: 'asdasd/asdasd',
responseCallBack: (response) => {
return !!response;
},
/*beforeShowModel: (props, callback) => {
},*/
nameSpan: { big: 4, small: 4 },
fileSpan: { big: 1, small: 1 },
};
/**
* 钟是志
* 2019年2月26日
* 用于 弹出提示信息 确认用户是否执行XXX操作
* 一个按钮 + 点击按钮显示的提示
* 点确定 调接口->关闭弹窗 刷新页面
* */
import ButtonDiy from '@/baseComponent/ButtonDiy';
import React, { Component, Fragment } from 'react';
import { message, Modal } from 'antd';
import PropTypes from 'prop-types';
import * as service from '@/highOrderComponent/Service';
export default class ModalConfirm extends Component {
handleConfirm = () => {
const { selectRows,name, contentSentence, onlyOne, checkSelectRow, noNeedCheckSelect,listData } = this.props;
if(typeof noNeedCheckSelect === 'undefined' && !selectRows.length){
message.warning('请至少选择一条数据');
return false;
}
if(onlyOne && selectRows.length > 1){
message.warning('只能选择一条数据进行操作');
return false;
}
if(checkSelectRow){
let res = checkSelectRow(selectRows, listData);
if(res && res.result === false){
message.warning(res.info);
return false;
}
}
Modal.confirm({
title: name,
content: contentSentence,
onOk: this.handleOk,
okText: '确定',
cancelText: '取消',
});
};
handleOk = () => {
const { selectRows, postKey, sourceKey, url,
responseCallBack, getPage,fields,formValues,
beforeUpdate,search } = this.props;
let data = {};
if(fields){
data = {...fields};
}
data[postKey] = selectRows.map( (item) => {
return item[sourceKey];
});
data[postKey] = data[postKey].join(',');
if(beforeUpdate){
data = beforeUpdate(data,selectRows,formValues,search);
}
service.addOrUpdate(data,url).then((response) => {
if(responseCallBack && !responseCallBack(response)){
return false;
}
if(!response){
return false;
}else{
message.success('操作成功');
getPage();
}
});
};
render() {
const { name, className } = this.props;
return (
<Fragment>
<ButtonDiy name={name}
className={className}
handleClick={this.handleConfirm}/>
</Fragment>);
}
}
ModalConfirm.propTypes = {
name: PropTypes.string, // 按钮名称和 弹窗的标题
selectRows: PropTypes.array.isRequired, // 选择的数据.数组类型
className: PropTypes.string, // 按钮样式
sourceKey: PropTypes.string.isRequired, // 通过什么字段删除
postKey: PropTypes.string, // 提交的字段名.
url: PropTypes.string.isRequired, // 接口url
responseCallBack: PropTypes.func, // 接口返回数据检查
getPage: PropTypes.func.isRequired, // 刷新页面的方法
};
ModalConfirm.defaultProps = {
name: '一键审核通过',
className: 'defaultBlue',
url: 'asdasd/asdasd',
contentSentence: '您确认xxxxx吗?',
sourceKey: 'id',
postKey: 'ids',
selectRows: [],
responseCallBack: (response)=>{
return !!response;
},
};
/**
* 钟是志
* 2019年2月26日
* 用于 弹出提示信息 确认用户是否删除数据
* 一个删除按钮 + 点击按钮显示的提示
* 点确定 调接口->关闭弹窗 刷新页面
* */
import ButtonDiy from '@/baseComponent/ButtonDiy';
import React, { Component, Fragment } from 'react';
import { message, Modal } from 'antd';
import PropTypes from 'prop-types';
import * as service from '@/highOrderComponent/Service';
export default class ModalDelete extends Component {
handleDelete = () => {
const { selectRows, checkBeforeDelete, cannotDeleteSentence, deleteSentence} = this.props;
if(!selectRows.length){
message.warning('请选择你要删除的数据');
return false;
}
if(checkBeforeDelete){
const check = checkBeforeDelete(selectRows);
if(!check){
if(cannotDeleteSentence){
message.warning(cannotDeleteSentence);
return false;
}else{
message.warning('数据关联,不能删除');
return false;
}
}
}
Modal.confirm({
title: '删除',
content: deleteSentence || `你确定要删除吗?`,
onOk: this.handleOk,
okText: '确认',
cancelText: '取消',
});
};
handleOk = () => {
const { selectRows, postKey, sourceKey, url, responseCallBack, getPage } = this.props;
const data = {};
data[postKey] = selectRows.map( (item) => {
return item[sourceKey];
});
data[postKey] = data[postKey].join(',');
service.deleteData(data,url).then((response) => {
if(!response){
getPage();
}
if(responseCallBack && !responseCallBack(response)){
return false;
}else{
message.success('删除成功');
getPage();
}
});
};
render() {
const { name, className } = this.props;
return (
<Fragment>
<ButtonDiy name={name}
className={className}
handleClick={this.handleDelete}/>
</Fragment>);
}
}
ModalDelete.propTypes = {
name: PropTypes.string, // 按钮名称和 弹窗的标题
selectRows: PropTypes.array.isRequired, // 选择的数据.
className: PropTypes.string, // 按钮样式
sourceKey: PropTypes.string.isRequired, // 通过什么字段删除
postKey: PropTypes.string, // 提交的字段名. ids
url: PropTypes.string.isRequired, // 接口url
responseCallBack: PropTypes.func, // 接口返回数据检查
getPage: PropTypes.func, // 刷新页面的方法
checkBeforeDelete: PropTypes.func, // 在删除前对数据进行检查 如果返回false 则不能删除数据
};
ModalDelete.defaultProps = {
name: '删除',
className: 'defaultRed',
url: 'asdasd/asdasd',
deleteKey: 'id',
postKey: 'ids',
selectRows: [],
responseCallBack: (response)=>{
return !!response;
},
};
/**
* 钟是志
* 2019年2月26日
* 用于 新增弹出modal
* 一个按钮 + 点击按钮显示的弹窗
* 弹窗中包含一个表单 并填写数据后点确定 调接口->关闭弹窗 刷新页面
* */
import ButtonDiy from '@/baseComponent/ButtonDiy';
import ModalDiy from '@/baseComponent/ModalDiy';
import React, { Component, Fragment } from 'react';
import { deepCopy, } from '@/baseComponent/utils';
import { mustHaveValue } from '../../config/index';
import { message } from 'antd';
import PropTypes from 'prop-types';
import { startProcess } from '../publicApiService';
import { transLateTimeTOUnix } from '@/pages/App/FormInsertDiy/config';
import FormArray from '../component/FormArray';
export default class ModalForm extends Component {
constructor(props) {
super(props);
const { values } = this.props;
this.state={
showModal: false,
formValues: { ...values }, // 将默认值传进去 用于新增时可能遇到的需要传值的情况
requireOtherFiled:{}
};
}
componentWillUnmount(){
}
changeShow = () => {
const { showModal } = this.state;
this.clearData();
this.setState({
showModal: !showModal,
});
};
formStateChange = (value, key) => {
const {diyFormStateChange} = this.props;
if(diyFormStateChange){
return diyFormStateChange(value, key, this);
}
let oldValue = this.state.formValues;
if(typeof value === 'object'){
oldValue[key] = deepCopy(value);
}else{
oldValue[key] = value;
}
this.setState({
formValues: oldValue,
});
};
clearData = () => {
const { values } = this.props;
this.setState({
formValues: {...values},
});
};
handleOk = () => {
let { formValues} = this.state;
const { fields, url, responseCallBack, getPage, beforeSubmit, workId, seriousOptions } = this.props;
if(!mustHaveValue(fields,formValues)){
return false;
}
let data = {
...formValues,
};
for(let item of fields){
if(data[item.key]){
data[item.key] = transLateTimeTOUnix(data[item.key], item.dataType);
}
if(data[item.endKey]){
data[item.endKey] = transLateTimeTOUnix(data[item.endKey], item.dataType);
}
}
if(beforeSubmit){
data = beforeSubmit(data,this);
if(!data){
return false;
}
}
const postData = {
content: JSON.stringify(data),
appId: workId,
};
if(seriousOptions && seriousOptions.length){
postData.level = seriousOptions[0].key;
}
startProcess(postData).then((response) => {
if(!responseCallBack(response)){
this.changeShow();
return false;
}else{
message.success('保存成功');
getPage();
this.changeShow();
}
})
};
render() {
const { showModal, formValues } = this.state;
const { name, className, fields, nameSpan, fileSpan, icon ,modalWidth} = this.props;
return (
<Fragment>
<ButtonDiy name={name}
className={className}
icon={icon}
handleClick={this.changeShow}/>
{showModal ?
<ModalDiy handleOk={this.handleOk}
title={name}
handleCancel={this.changeShow}
width={modalWidth}
>
<FormArray config={fields}
value={formValues}
changeValue={this.formStateChange}
nameSpan={nameSpan}
fileSpan={fileSpan}/>
</ModalDiy> : null}
</Fragment>);
}
}
ModalForm.propTypes = {
name: PropTypes.string, // 按钮名称和 弹窗的标题
className: PropTypes.string, // 按钮样式
fields: PropTypes.array.isRequired, // 填写的字段的配置
values: PropTypes.object, // 如果有默认参数 则在页面的业务逻辑中传进来
url: PropTypes.string.isRequired, // 接口url
icon: PropTypes.string, // 按钮图标
responseCallBack: PropTypes.func, // 接口返回数据检查
getPage: PropTypes.func, // 刷新页面的方法
nameSpan: PropTypes.object, // 页面排版
fileSpan: PropTypes.object, // 页面排版
};
ModalForm.defaultProps = {
name: '新增',
className: 'primaryBlue',
values: {},
url: 'asdasd/asdasd',
responseCallBack: (response)=>{
return !!response;
},
getPage: () => {
},
nameSpan: {big: 5, small: 5 },
fileSpan: {big: 1, small: 1 },
};
import ButtonDiy from '@/baseComponent/ButtonDiy';
import React, { Component, Fragment } from 'react';
/*
import ExportInfo from '@/components/App/ExportInfo';
import ImportUtil from '@/components/App/ImportUtil';
import ModalDelete from './ModalDelete';
import ModalConfirm from './ModalConfirm';
*/
import ModalBatch from './ModalBatch';
import ModalForm from './ModalForm';
export default class ButtonListDom extends Component {
render() {
const { config, getPage, selectRows, formValues, children, search,listData } = this.props;
return (<div style={{ height: '50px', padding: '12px 0 12px 12px', positon:'relative'}}>
{config.map((item, i) => {
switch (item.component) {
case 'ModalForm': // 新增按钮 + 弹窗
return <ModalForm {...item}
key={item.type}
getPage={getPage}
selectRows={selectRows}
/>;
/* case 'ModalDelete': // 删除按钮
return <ModalDelete {...item}
key={item.type}
getPage={getPage}
selectRows={selectRows}
/>;
case 'ImportUtil': // 导入
return <ImportUtil {...item.props}
key={item.type}
callback={() => getPage()}
/>;
case 'ExportInfo': // 导出
return <ExportInfo {...item.props}
key={item.type}
/>;
case 'ModalConfirm': // 一般按钮 点击后弹出是否确定的 Modal Info
return <ModalConfirm key={item.type}
{...item}
getPage={getPage}
listData={listData}
formValues={formValues}
search={search}
selectRows={selectRows}/>;
*/
case 'ModalBatch': // 一般按钮 点击后弹出 填写一些类似 审核理由 意见之类的信息
return <ModalBatch key={item.type}
{...item}
handleSelectRows={this.props.handleSelectRows}
getPage={getPage}
selectRows={selectRows}/>;
case 'OpenUrl': // 点击按钮 打开一个新窗口
return window.open(item.url);
case "Normal":
return(
<ButtonDiy name={item.name}
key={item.type}
className={item.className || 'defaultBule'}
handleClick={() => {item.handleClick(selectRows, formValues, getPage,search)}}
/>
);
case 'RenderComponent':
return item.render({
name: item.name,
selectRows,
formValues,
getPage,
search,
listData
});
default:
break;
// return <ButtonDiy></ButtonDiy>;
}
})}
<span style={{display:'inline-block'}}>{children}</span>
</div>);
}
}
import React, { Fragment, Component } from 'react';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import Shell from '@/baseComponent/Shell';
import BlockTitle from '@/baseComponent/BlockTitle';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import router from 'umi/router';
import FormArray from './component/FormArray';
import { getDetailInfo, handleAudit } from '@/pages/App/FormInsertDiy/AffairPage/publicApiService';
import { isJSON } from '@/baseComponent/utils';
import { Col, Row, Timeline, Icon, Tabs } from 'antd';
import ModalBatch from './ButtonListDom/ModalBatch';
import FlowImg from './component/FlowImg';
import { getHuanGeToken } from '@/utils/authority';
import config from '@/config/config';
const { TabPane } = Tabs;
/*
export default class Detail extends Component {
/!**
* workId,dataBaseId,record,addFields
* *!/
constructor(props) {
super(props);
this.state = {
detailInfo: {
content: {},
taskInfo: [],
},
show: false,
};
}
componentDidMount() {
const { state } = this.props.location;
const { record } = state;
getDetailInfo(record.id).then((x) => {
if (x) {
if (isJSON(x.content)) {
x.content = JSON.parse(x.content);
}
if(typeof x.content === 'object' && x.content.defaultValues){
for(let z in x.content.defaultValues){
x.content = {
...x.content,
...x.content.defaultValues[z],
}
} }
this.setState({
detailInfo: x,
show: true,
});
}
});
}
buttonDom = () => {
const { detailInfo } = this.state;
const { btns } = detailInfo;
let res = [];
if(typeof btns !== 'undefined' && Array.isArray(btns)){
for(let z of btns){
res.push(
{
type: z.name,
name: z.name,
component: 'ModalBatch',
className: z.name !== '通过' ? 'defaultRed' : 'defaultBlue',
nameSpan: { big: 4, small: 5 },
fileSpan: { big: 1, small: 1 },
values: {
[z.key]: z.value,
},
fields: [
{
key: 'reason',
name: '审核意见',
type: 'textarea',
},
],
beforeSubmit: (props, formValues) => {
return {
taskForm : {},
examineMap: JSON.stringify(formValues),
};
},
sourceKey: 'taskId',
postKey: 'taskIds',
apiServiceApi: handleAudit,
}
)
}
return res;
}
return [];
};
render() {
const { state } = this.props.location;
const { record, addFields, workId } = state;
const { detailInfo, show } = this.state;
const Btns = this.buttonDom();
const dot1 = <Icon type={'check-circle'}
style={{ fontSize: '16px', color: 'rgb(82, 196, 26)' }}/>;
const dot2 = <Icon type={'clock-circle-o'}
style={{ fontSize: '16px', color: 'red' }}/>;
if(!show){
return null;
}
return (<PageHeaderWrapper title="">
<Shell>
<div style={{ height: '54px', padding: '12px 0 12px 12px' }}>
<ButtonDiy name="返回"
className="defaultBlue"
icon="arrow-left"
handleClick={() => {
router.goBack();
}}
/>
{
Btns.map((item)=>{
return <ModalBatch key={item.type}
{...item}
handleSelectRows={()=>{console.log('清空')}}
getPage={()=>{router.goBack()}}
selectRows={[record]}/>
})
}
</div>
</Shell>
<Shell>
<BlockTitle
isSmall={true}
title={'申请信息'}
/>
<Row>
<Col span={20}>
<FormArray config={addFields}
value={detailInfo.content}
changeValue={() => {
console.log(xxx);
}}
disabled={true}
readOnly={true}
fileSpan={{ big: 2, small: 2 }}
nameSpan={{ big: 6, small: 7 }}
/>
</Col>
</Row>
</Shell>
<Shell>
<Tabs>
<TabPane tab={'审批状态'} key={'1'}>
<Row>
<Col span={16} offset={2} style={{paddingTop: '30px', paddingBottom: '30px'}}>
<Timeline>
{
detailInfo.taskInfo.map((item) => {
let reason = item.respdesc;
if(item.taskVariable && item.taskVariable.reason){
reason = item.taskVariable.reason;
}
return (
<Timeline.Item dot={item.endTime ? dot1 : dot2}
key={item.id}
>
{item.assignee ? <p><b>{item.assignee}</b></p> : <p>&nbsp; </p>}
<p>审批流程: {item.name}</p>
<p>审批状态: {item.status}</p>
<p>审批原因: {reason}</p>
</Timeline.Item>
);
})
}
</Timeline>
</Col>
</Row>
</TabPane>
<TabPane tab={'流程图'} key={'2'}>
<FlowImg id={workId}/>
</TabPane>
</Tabs>
</Shell>
</PageHeaderWrapper>)
;
}
}*/
export default class Detail extends Component{
constructor(props){
super(props);
const { state } = this.props.location;
let id = '';
if(state && state.record && state.record.id){
const { record } = state;
id = record.id;
}
this.state={
id,
};
}
componentDidMount(){
window.addEventListener('message', (event) => {
if(event.data.indexOf('iframeDetailHeight') > -1){
let height = Number(event.data.split('-')[1]);
document.getElementById('detailIframeId').height = height;
}
}, false);
}
showAll = () => {
this.setState({
showAll: true,
});
};
render(){
const { id, showAll } = this.state;
const url = config.onestopPC.split('/#/');
let iframeUrl = `${url[0]}/#/IframeForDetail?id=${id}&token=${getHuanGeToken()}`;
// iframeUrl = `http://localhost:8000/onestop/IframeForDetail?id=${id}&token=${getHuanGeToken()}`;
return (
<PageHeaderWrapper title="">
<Shell>
<div style={{
height: '54px',
padding: '12px 0 12px 12px',
}}>
{
showAll ?
<ButtonDiy name="返回"
className="defaultBlue"
handleClick={()=>{
router.goBack();
}}
icon="arrow-left"
/>
: null
}
</div>
</Shell>
<Shell>
<iframe src={iframeUrl}
frameBorder={0}
id='detailIframeId'
name='applyIframe'
marginWidth="0"
marginHeight="0"
onLoad={this.showAll}
allowTransparency="yes"
seamless
scrolling={'no'}
style={{
width: '100%',
overflowY: 'hidden',
minHeight: '800px',
}}
/>
</Shell>
</PageHeaderWrapper>
)
}
}
import React, { Component, Fragment } from 'react';
import { Upload, message } from 'antd';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import * as service from '@/baseComponent/UploadImgDiy/service';
import PropTypes from 'prop-types';
export default class ButtonUpload extends Component {
constructor(props) {
super(props);
this.state = {
fileSize: props.fileSize || 2,
loading: false,
};
}
checkSize(file) {
const { fileSize } = this.state;
let flag = false;
if (fileSize && file.size / 1024 / 1024 > fileSize) {
message.error(`单个文件大小不能超过${fileSize}MB!`);
flag = true;
}
return flag;
}
uploadFile = () => {
const { onChange } = this.props;
const file = this.fileInput.files[this.fileInput.files.length - 1];
if (!file || this.checkSize(file)) {
return;
}
this.setState({
loading: true,
});
service.uploadFile({
file: file,
}).then(res => {
this.setState({
loading: false,
});
if (res) {
message.success('上传成功');
let data = {
files: [
{
path: res.url,
name: file.name,
},
],
};
onChange && onChange(data, this.fileInput);
}
});
};
selectFile = () => {
this.fileInput.click();
};
render() {
const { accept, buttonName, buttonClassName, value, readOnly, disabled } = this.props;
const { loading } = this.state;
const viewDom = <a href={value}
target="_blank">点击查看</a>;
if (readOnly || disabled) {
if(typeof value === 'object'){
if(Array.isArray(value.files) && value.files.length){
return <a href={value.files[0].path}
target="_blank">点击查看</a>;
}else{
return null;
}
}
if (value) {
return viewDom;
}
return null;
}
return (
<Fragment>
<label>
<ButtonDiy name={loading ? '上传中' : buttonName}
loading={loading}
handleClick={this.selectFile}
className={buttonClassName}
/>
<input type="file"
accept={accept}
style={{ display: 'none' }}
onChange={this.uploadFile}
ref={input => {
this.fileInput = input;
}}
/>
{this.fileInput && this.fileInput.value.split('\\').pop()
|| value
|| <span style={{ color: '#D2D2D2' }}>未选择任何文件</span>}
</label>
</Fragment>
);
}
}
ButtonUpload.propTypes = {
fileSize: PropTypes.number, // 文件大小限制
accept: PropTypes.string, // 上传类型限制
buttonName: PropTypes.string, // 上传按钮名称
buttonClassName: PropTypes.string, //按钮样式
onChange: PropTypes.func, // 上传成功回调
};
ButtonUpload.defaultProps = {
fileSize: 2,
accept: '',
buttonName: '选择文件',
buttonClassName: 'defaultBlue',
onChange: () => {
},
};
/**
* 钟是志
* 2019年11月5日
* 流程引擎 ChildForm组件
*
* */
import ButtonDiy from '@/baseComponent/ButtonDiy';
import ModalDiy from '@/baseComponent/ModalDiy';
import React, { Component, Fragment } from 'react';
import { mustHaveValue } from '@/baseComponent/utils';
import { Badge, Icon } from 'antd';
import FormArray from './FormArray';
export default class ChildForm extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
formValues: [{
formKey: Math.random(),
}],
requireOtherFiled: {},
};
}
changeShow = () => {
const { value } = this.props;
const { showModal } = this.state;
if (!value || typeof value !== 'object' || !Array.isArray(value)) {
this.setState({
formValues: [{
formKey: Math.random(),
}],
showModal: !showModal,
});
} else {
let formValues = [];
for (let item of value) {
formValues.push(
{
formKey: Math.random(),
...item,
});
}
this.setState({
formValues,
showModal: !showModal,
});
}
};
formStateChange = (value, key, index) => {
let oldValue = this.state.formValues;
oldValue[index][key] = value;
this.setState({
formValues: oldValue,
});
};
addOneForm = () => {
let oldValue = this.state.formValues;
oldValue.push({
formKey: Math.random(),
});
this.setState({
formValues: oldValue,
});
};
deleteOneForm = (index) => {
let oldValue = this.state.formValues;
oldValue.splice(index, 1);
this.setState({
formValues: oldValue,
});
};
componentDidMount() {
}
handleOk = () => {
const { formValues } = this.state;
const { config } = this.props;
const { componentProps: { thisFields } } = config;
for (let item of formValues) {
if (!mustHaveValue(thisFields, item)) {
return false;
}
}
this.props.onChange(formValues, config.key);
this.changeShow();
return false;
};
render() {
const { showModal, formValues } = this.state;
const { config, disabled } = this.props;
const { componentProps: { thisFields } } = config;
const modalProps = {
handleOk: this.handleOk,
title: config.name,
handleCancel: this.changeShow,
width: 800,
};
if(disabled){
modalProps.footer = null;
}
const Fields = [];
for(let item of thisFields){
if(item.comName !== 'Label'){
Fields.push(item.name);
}
}
const Filter = [];
for(let item of thisFields){
let name = '';
if(item.defaultValue){
name = item.defaultValue.replace(/[\r\n]/g,"");
}
if(item.comName === 'Label' && name && Fields.indexOf(name) > -1){
continue;
}else{
Filter.push(item);
}
}
return (
<Fragment>
<ButtonDiy name={disabled ? '查看' : '编辑'}
handleClick={this.changeShow}/>
{showModal ?
<ModalDiy {...modalProps}>
{
formValues.map((x, index) => {
return (
<div
style={{
border: '1px solid gray',
width: '95%',
margin: '0 auto',
marginBottom: '15px',
}}
key={x.formKey}>
{
disabled ?
<Badge count={
<Icon type={'check'}
style={{
color: '#52c41a',
paddingTop: '20px',
paddingRight: '20px',
}}/>
}
>
<FormArray config={thisFields}
value={x}
changeValue={(value, key) => {
this.formStateChange(value, key, index);
}}
disabled={disabled}
nameSpan={{ big: 7, small: 7 }}
fileSpan={{ big: 2, small: 2 }}/>
</Badge>
: <Badge count={
<Icon type={'close-circle'}
onClick={() => {
this.deleteOneForm(index);
}}
style={{
color: '#f5222d',
paddingTop: '20px',
paddingRight: '20px',
}}/>
}
>
<FormArray config={Filter}
value={x}
changeValue={(value, key) => {
this.formStateChange(value, key, index);
}}
disabled={disabled}
nameSpan={{ big: 9, small: 9 }}
fileSpan={{ big: 2, small: 2 }}/>
</Badge>
}
</div>
);
})
}
{
disabled ? null :
<div style={{ paddingTop: '20px', textAlign: 'center' }}>
<ButtonDiy name={'新增'}
className={'defaultRed'}
handleClick={this.addOneForm}
/>
</div>
}
</ModalDiy> : null}
</Fragment>);
}
}
/**
* 徐立
* 2019年9月22日
* 流程图
*/
import React, { Component } from 'react'
import config from '@/config/config';
export default class FlowImg extends Component {
render() {
let { id } = this.props;
return (
<div style={{
width:'98%',
textAlign:'center',
minHeight: '300px',
paddingTop: '50px',
paddingBottom: '50px',
overflowX: 'auto',
}}>
<img src={config.sqlFormsServer + '/UnifiedAppFormApi/getProcessImg?appId='+id} alt=""/>
</div>
)
}
}
import {
Col, Form, Input, Select, DatePicker,
TimePicker,
Checkbox, Button, Radio, Switch, Upload,
Icon, InputNumber, Cascader, TreeSelect,
message,
} from 'antd';
import React, { Component, Fragment } from 'react';
import styles from './index.less';
import PropTypes from 'prop-types';
import moment from 'moment';
import { countSpecialField } from '@/baseComponent/utils';
import TableSelect from './TableSelect';
import ChildForm from './ChildForm';
import ReactQuill from 'react-quill';
import baseConfig from '@/config/config';
import 'react-quill/dist/quill.snow.css';
import ButtonUpload from './ButtonUpload';
const RadioGroup = Radio.Group;
const Option = Select.Option;
const { TextArea } = Input;
const FormItem = Form.Item;
const CheckboxGroup = Checkbox.Group;
const { MonthPicker, RangePicker } = DatePicker;
const quillConfig = {
toolbar:
[
[{ size: [] }],
['bold', 'italic', 'underline', 'strike', 'blockquote'],
[
{ list: 'ordered' },
{ list: 'bullet' },
{ indent: '-1' },
{ indent: '+1' },
],
['link', 'image', 'video'],
['clean'],
],
};
const ColDom = ({ children, filedSpan }) => {
const bigSpan = Math.ceil(24 / filedSpan.big);
const smallSpan = Math.ceil(24 / filedSpan.small);
return (
<Col xl={smallSpan}
xxl={bigSpan}
className={styles.colDom}
style={countSpecialField(filedSpan.big)}
>
{children}
</Col>)
;
};
const FormItemDom = ({ info, children, nameSpan }) => {
return <FormItem label={info.name}
required={info.required || false}
labelCol={{
xl: nameSpan.small,
xxl: nameSpan.big,
}}
wrapperCol={{
xl: 24 - nameSpan.small,
xxl: 24 - nameSpan.big,
}}
colon={false}
>
{children}
</FormItem>;
};
export default class FormArray extends Component {
constructor(props) {
super(props);
this.state = {};
}
formatTime = (time, formatTimeConfig = 'YYYY-MM-DD HH:mm') => {
return moment(time);
};
datePickerOnchange = (dateString, key) => {
const { changeValue } = this.props;
changeValue(dateString, key);
};
defaultPropsCount = (info, value) => {
const itemDisabled = typeof info.disabled !== 'undefined' ? info.disabled : false;
const readOnly = typeof info.readOnly !== 'undefined' ? info.readOnly : false;
const placeholder = typeof info.placeholder !== 'undefined' ? info.placeholder : '';
const options = typeof info.options !== 'undefined' ? info.options : [];
let itemValue = typeof value[info.key] === 'undefined' ? '' : value[info.key];
if (['select', 'radioGroup'].indexOf(info.type) > -1) {
itemValue = typeof itemValue === 'number' ? itemValue.toString() : itemValue;
itemValue = typeof itemValue === 'boolean' ? itemValue + '' : itemValue;
} else if (['selectMultiple', 'checkBoxMutiple', 'cascader'].indexOf(info.type) > -1) {
itemValue = typeof itemValue === 'number' ? itemValue.toString() : itemValue;
// 数字变成 字符串
itemValue = typeof itemValue === 'string' && itemValue ? itemValue.split(',') : itemValue;
// 有值且值是字符串则 变成数组
itemValue = !itemValue ? [] : itemValue;
// 没有值则变成空数组
for (let i = 0; i < itemValue.length; i++) {
itemValue[i] = typeof itemValue[i] === 'number' ? itemValue[i].toString() : itemValue[i];
// 每一个值数字变成字符串
}
} else if (['datePicker', 'monthPicker', 'timePicker'].indexOf(info.type) > -1) {
if (typeof itemValue !== 'object') {
if (itemValue) {
if (!isNaN(parseInt(itemValue)) && parseInt(itemValue) > 10000000) {
itemValue = parseInt(itemValue);
itemValue = moment(itemValue);
} else {
if (info.format) {
itemValue = moment(itemValue, info.format);
} else {
itemValue = moment(itemValue);
}
}
} else {
itemValue = null;
}/*格式化时间*/
}
} else if (['rangePicker'].indexOf(info.type) > -1) {
if (typeof itemValue !== 'object') {
let endValue = typeof value[info.endKey] === 'undefined' ? null : value[info.endKey];
if (itemValue) {
if (!isNaN(parseInt(itemValue)) && parseInt(itemValue) > 10000000) {
itemValue = parseInt(itemValue);
}
if (!isNaN(parseInt(endValue)) && parseInt(endValue) > 10000000) {
endValue = parseInt(endValue);
}
itemValue = [moment(itemValue), moment(endValue)];
} else {
itemValue = undefined;
}
}
} else if (info.type === 'checkBox') {
itemValue = !!itemValue;
} else if (info.type === 'switch') {
itemValue = !!value[info.key];
}
/*if(info.type === 'selectPeople'){
itemValue = typeof itemValue !== 'object' ? {key:itemValue,label: ''} : itemValue;
}*/
const defaultProps = {
readOnly: this.props.readOnly ? true : readOnly,
disabled: this.props.disabled ? true : itemDisabled,
value: itemValue,
placeholder: placeholder,
options: options,
className: styles[info.className] || '',
};
if (typeof info.precision !== 'undefined') {
defaultProps.precision = info.precision;
}
return defaultProps;
};
rangeOnChange = (dateStrings = [], key, endKey) => {
const { changeValue } = this.props;
changeValue(dateStrings[0], key);
changeValue(dateStrings[1], endKey);
};
changeInputNumber = (value, config) => {
if (typeof value === 'number') {
if (typeof config.min !== 'undefined' && value < config.min) {
message.warning(`${config.name}不能小于${config.min}`);
} else if (typeof config.max !== 'undefined' && value > config.max) {
message.warning(`${config.name}不能大于${config.max}`);
}
}
};
domAssembly = () => {
const { changeValue, value, config, fileSpan, nameSpan } = this.props;
return config.map((info, i) => {
let fieldDom = null;
const defaultProps = this.defaultPropsCount(info, value);
switch (info.type) {
case 'input': // 普通文本
fieldDom = <Input {...defaultProps}
style={info.style || {}}
onChange={(e) => {
changeValue(e.target.value, info.key);
}}/>;
break;
case 'inputNumber': // 数字文本
fieldDom =
<Fragment>
<InputNumber
{...defaultProps}
style={info.style || { width: '100%' }}
min={info.min ? info.min : 0}
max={info.max ? info.max : Infinity}
onChange={(value) => {
this.changeInputNumber(value, info);
changeValue(value, info.key);
}}
/>
{info.formatter ? <span>{info.formatter}</span> : ''}
</Fragment>
;
break;
case 'idCard':
fieldDom = <Fragment>
<Input {...defaultProps}
style={info.style || {}}
onChange={(e) => {
changeValue(e.target.value, info.key);
}}/>
</Fragment>;
break;
case 'phone':
fieldDom = <Fragment>
<InputNumber {...defaultProps}
style={info.style || { width: '100%' }}
min={0}
max={info.max ? info.max : Infinity}
onChange={(value) => {
changeValue(value, info.key);
}}/>
</Fragment>;
break;
case 'checkBoxMutiple': // 多选 checkbox
fieldDom = <CheckboxGroup {...defaultProps}
onChange={(value) => {
changeValue(value, info.key);
}}/>;
break;
case 'cascader': // 级联选择
fieldDom = <Cascader value={defaultProps.value}
options={defaultProps.options}
style={{ width: '100%' }}
onChange={(value, selectedOptions) => {
changeValue(value, info.key);
}}/>; // 返回数组 [parent,child]
break;
case 'selectMultiple': // 下拉多选
fieldDom = <Select {...defaultProps}
mode="multiple"
allowClear
style={{ width: '100%' }}
onChange={(value) => {
changeValue(value, info.key);
}}>
{defaultProps.options.map((optionItem) => {
return <Option key={typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key}>
{optionItem.name}
</Option>;
})}
</Select>;
break;
case 'select': // 下拉单选
fieldDom = <Select {...defaultProps}
style={{ width: '100%' }}
allowClear={typeof info.allowClear !== 'undefined' ? info.allowClear : true}
onChange={(value) => {
changeValue(value, info.key);
}}>
{defaultProps.options.map((optionItem) => {
return <Option key={typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key}
disabled={optionItem.disabled}>
{optionItem.name}
</Option>;
})}
</Select>;
break;
case 'tableSelect':
fieldDom =
<TableSelect
config={info}
value={defaultProps.value}
onChange={changeValue}
disabled={defaultProps.disabled}
/>;
break;
case 'childForm':
fieldDom =
<ChildForm
config={info}
value={defaultProps.value}
onChange={changeValue}
disabled={defaultProps.disabled}
/>;
break;
case 'checkBox': // 布尔值选择
fieldDom = <Checkbox checked={defaultProps.value}
disabled={defaultProps.disabled}
onChange={(e) => {
changeValue(e.target.checked, info.key);
}}>
{info.text}
</Checkbox>;
break;
/* case 'editable': // 可编辑的富文本
fieldDom = <div className={styles.Editable}>
<Editable onChange={changeValue}
filedKey={info.key}
disabled={defaultProps.disabled}
value={defaultProps.value}
/>
</div>;
break;*/
case 'datePicker': // 日期选择
fieldDom = <DatePicker showTime={info.showTime}
{...defaultProps}
style={{ width: '100%' }}
format={info.format}
onChange={(date, dateString) => {
this.datePickerOnchange(dateString, info.key);
}}>
</DatePicker>;
break;
case 'timePicker': // 日期选择
fieldDom = <TimePicker
{...defaultProps}
style={{ width: '100%' }}
format={info.format || 'HH:mm'}
onChange={(date, dateString) => {
this.datePickerOnchange(dateString, info.key);
}}/>;
break;
case 'rangePicker': // 时间段选择
if (info.disabledDate && info.disabledDate === 'afterYesterday') { // 禁用今天之前的时间
defaultProps.disabledDate = (current) => {
// Can not select days before today and today
return current < moment().add(-1, 'days');
};
}
fieldDom = <RangePicker showTime={info.showTime}
{...defaultProps}
style={{ width: '100%' }}
format={info.format}
placeholder={info.placeholder || ['开始日期', '结束日期']}
onChange={(dates, dateStrings) => {
this.rangeOnChange(dateStrings, info.key, info.endKey);
}}>
</RangePicker>;
break;
case 'monthPicker': // 年月 选择
fieldDom = <MonthPicker
{...defaultProps}
style={{ width: '100%' }}
format={info.format}
onChange={(date, dateString) => {
this.datePickerOnchange(dateString, info.key);
}}>
</MonthPicker>;
break;
case 'textarea': // 文本框
fieldDom = <TextArea {...defaultProps}
autoSize={{ minRows: 4, maxRows: 6 }}
onChange={(e) => {
changeValue(e.target.value, info.key);
}}/>;
break;
case 'radioGroup': // 圆形 选择框
fieldDom = <RadioGroup value={defaultProps.value}
disabled={defaultProps.disabled}
style={{ width: '100%' }}
onChange={(e) => {
changeValue(e.target.value, info.key);
}}>
{defaultProps.options.map((optionItem) => {
const radioValue = typeof optionItem.key !== 'boolean' ? optionItem.key + '' : optionItem.key;
return <Radio key={radioValue} value={radioValue}>
{optionItem.name}
</Radio>;
})}
</RadioGroup>;
break;
case 'switch': // 开关
fieldDom = <Switch {...defaultProps}
checked={defaultProps.value}
checkedChildren={info.checkedChildren || ''}
unCheckedChildren={info.unCheckedChildren || ''}
onChange={(e) => {
changeValue(e, info.key);
}}/>;
break;
case 'editor':
let thisClassName = styles.editorLayout;
if (info.className) {
thisClassName = styles[info.className];
}
fieldDom = <ReactQuill {...defaultProps}
className={thisClassName}
modules={quillConfig}
onChange={(e) => {
changeValue(e, info.key);
}}
/>;
break;
case 'upload':
fieldDom = <Upload action={baseConfig.uploadUrl + `&isConvert=${info.isConvert || false}`}
accept={info.accept}
multiple={info.multiple}
{...defaultProps}
defaultFileList={value[info.key]}
name="file"
onChange={({ fileList }) => {
changeValue(fileList, info.key);
}}>
<Button>
<Icon type="upload"/> 上传
</Button>
</Upload>;
break;
case 'buttonUpload':
fieldDom = <ButtonUpload onChange={(url) => {
changeValue(url, info.key);
}}
{...info}
{...defaultProps}
/>;
break;
case 'text':
fieldDom = <div>{defaultProps.value || info.value}</div>;
break;
case 'TreeSelect':
fieldDom = <TreeSelect {...defaultProps} {...info.props} onChange={(v) => changeValue(v, info.key)}/>;
break;
case 'personalRender':
fieldDom = info.render({ value, onChange: (v, key) => changeValue(v, key) });
break;
default:
fieldDom = null;
break;
}
return (
<ColDom filedSpan={info.fileSpan || fileSpan} key={info.key + i}>
<FormItemDom info={info} nameSpan={info.nameSpan || nameSpan}>
{fieldDom}
</FormItemDom>
</ColDom>);
});
};
render() {
const { style } = this.props;
return (
<div className={styles.FormArray} style={style}>
{this.domAssembly()}
</div>
);
}
}
/**
* 最主要的 props 就是config.
* config: 表单填写的每一个字段,根据type的不同渲染不同的组件,
* 包含 [inputNumber(数字input),input,
* selectMultiple(多选下拉),select(单选下拉)
* checkBox(单选checkbox),
* checkBoxMutiple (多选checkbox)
* datePicker日期选择 value 传入 时间戳格式 等等
*
* 具体请查看下面的demo
*
* changeValue: 表单的值改变后的回调
* value : 表单的值应该是一个对象state {name:'',phone:''....}
* fileSpan : { big:5, small:4}
* small: 设置1366*768的屏幕 每一行显示几个字段 如 只显示3个 则 = 3
* big: 设置1920*1080的屏幕 每一行显示几个字段 同上
* nameSpan { big:5, small:4} 同上设置 一个字段的 字段名和填写的值所占的比例
* */
/**
* 2019年3月7日
* 钟是志
* 增加对 时间段rangePicker选择的支持 具体使用见下面的 demo
* */
FormArray.propTypes = {
config: PropTypes.array,
readOnly: PropTypes.bool,
disabled: PropTypes.bool,
changeValue: PropTypes.func,
value: PropTypes.object,
fileSpan: PropTypes.object,
nameSpan: PropTypes.object,
style: PropTypes.object,
};
FormArray.defaultProps = {
config: [
{
name: '数字选择',
type: 'inputNumber',
placeholder: '',
key: 'scoreRank',
},
{
name: '文本框',
type: 'input',
placeholder: '',
key: 'scoreRank2',
},
{
key: 'startDate',
endKey: 'endDate',
name: '时间段选择',
type: 'rangePicker',
format: 'YYYY-MM-DD',
placeholder: ['开始时间', '结束时间'],
required: true,
},
{
name: '日期选择',
type: 'datePicker',
placeholder: '',
key: 'scoreRank5',
},
{
name: '下拉框选择',
type: 'select',
placeholder: '',
key: 'scoreRank6',
}, {
name: '下拉框多选',
type: 'selectMultiple',
placeholder: '',
key: 'scoreRank7',
}, {
key: 'studentType',
name: 'checkBox多选',
type: 'checkBoxMutiple',
options: [
{ label: '本科', value: '本科' },
{ label: '专科', value: '专科' },
{ label: '研究生', value: '研究生' },
],
required: true,
},
],
changeValue: (value, key) => {
},
value: {},
fileSpan: {
big: 5,
small: 4,
},
nameSpan: {
big: 10,
small: 12,
},
disabled: false,
style: {},
};
/**
* 钟是志
* 2019年11月4日 17:39:34
* 流程引擎 TableSelect
*/
import { Divider, Modal, Popconfirm } from 'antd';
import React, { Component, Fragment } from 'react';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import StandardTable from '@/components/StandardTable';
import { Link } from 'react-router-dom';
import { handleSqlData } from '../publicApiService';
import { date, format } from '../../config';
import moment from 'moment';
import { deepCopy } from '@/baseComponent/utils';
export default class TableSelect extends Component {
constructor(props) {
super(props);
this.state = {
showModal: false,
formValues: {},
selectedRows: [],
showDetail: true,
list: [],
pagination: {
current: 1,
total: 1,
pageSize: 10,
showQuickJumper: true,
onChange: (current, size) => {
this.pageChange(current, size);
},
},
};
}
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
};
/*formStateChange = (value, key) => {
let oldValue = this.state.formValues;
oldValue[key] = value;
this.setState({
formValues: oldValue,
});
};*/
showModal = () => {
this.setState(
{
showModal: true,
}, () => {
this.getPeopleInfo();
});
};
pageChange = (current, size) => {
this.setState({
pagination: {
...this.state.pagination,
current: current,
pageSize: size,
},
}, () => {
// this.getPeopleInfo();
});
};
componentDidMount() {
// this.getPeopleInfo();
}
getPeopleInfo = () => {
const { config, value } = this.props;
const { componentProps: { sqlKey, allValues, valueName } } = config;
const { pagination, formValues } = this.state;
const data = {
...formValues,
sqlKey,
allValues,
};
data.pageSize = pagination.pageSize;
data.pageNo = pagination.current;
handleSqlData(data).then((response) => {
if (response.total) { // 后续增加分页.
} else {
pagination.total = response.length;
}
for (let item of response) {
item[valueName] = item[valueName] + '';
}
this.setState({
list: response,
pagination,
});
});
};
stateChange = (key, value) => {
this.setState({
[key]: value,
});
};
onChange = (value) => {
const { config } = this.props;
this.setState({
showDetail: false,
},()=>{
this.props.onChange(value, config.key);
setTimeout(()=>{
this.setState({
showDetail: true,
})
}, 50);
});
};
cancelSelect = (record) => {
const { config } = this.props;
let value = deepCopy(this.props.value);
const { labelName, valueName } = config.componentProps;
if (value && typeof value === 'object' && value.selects) {
delete value.selects[record[valueName]];
}
this.onChange(value);
};
handleSelect = (record) => {
const { config } = this.props;
let value = deepCopy(this.props.value);
const { labelName, valueName, isMultiple } = config.componentProps;
if (typeof value === 'object') {
if (value.selects && isMultiple === true) {
value.selects[record[valueName]] = {
...record,
};
} else {
value.selects = {
[record[valueName]]: {
...record,
},
};
}
} else {
value = {
selects: {
[record[valueName]]: {
...record,
},
},
};
}
this.onChange(value);
};
handleColumns = () => {
const { config, value } = this.props;
const { showDetail } = this.state;
const { valueName } = config.componentProps;
const info = value && typeof value === 'object' && value.selects ? value.selects : {};
let keys = Object.keys(info);
const { componentProps: { columnsData } } = config;
const { cols } = columnsData;
let columns = [];
for (let item in cols) {
columns.push(
{
dataIndex: cols[item].name,
title: cols[item].title,
dataType: cols[item].type,
},
);
}
for (let item of columns) {
if (item.dataType && date.indexOf(item.dataType) > -1) {
item.render = (text, record) => {
if (!text) {
return '';
}
if (!isNaN(parseInt(text, 10)) && parseInt(text, 10) > 10000000) {
text = parseInt(text, 10);
}
return moment(text).format(format[item.dataType]);
};
}
}
if (columns.length && showDetail) {
columns.push(
{
title: '操作',
// fixed: 'right',
dataIndex: 'operation',
render: (text, record) => {
if (keys.indexOf(record[valueName]) > -1) {
return (<a
style={{color: 'red'}}
onClick={() => {
this.cancelSelect(record);
}}>
取消选择
</a>);
}
return (<a onClick={() => {
this.handleSelect(record);
}}>选择</a>);
},
},
);
}
return columns;
};
render() {
const { config, disabled } = this.props;
const { labelName, valueName } = config.componentProps;
const { showModal, list, pagination, selectedRows } = this.state;
const value = deepCopy(this.props.value);
const columns = this.handleColumns();
const info = value && typeof value === 'object' && value.selects ? value.selects : {};
const re = [];
for (let item in info) {
const one = info[item];
re.push(
{
name: one[labelName],
value: one[valueName],
},
);
}
return (
<Fragment>
{!showModal ?
<Fragment>
<span>
{re.length ? re.map((x) => {
return <span key={x.value}>{x.name}&nbsp;&nbsp;</span>;
})
: ''}
</span>
{disabled ? null : <ButtonDiy
name={'选择'}
className={'defaultBlue'}
handleClick={this.showModal}/>}
</Fragment>
:
<Modal title={'选择'}
visible={true}
width={1200}
maskClosable={false}
footer={null}
onCancel={() => {
this.stateChange('showModal', false);
}}>
<div style={{ overflowY: 'auto', maxHeight: '600px' }}>
<StandardTable
rowKey={valueName}
selectedRows={selectedRows}
data={{ list, pagination }}
columns={columns}
onSelectRow={this.handleSelectRows}
noSelectRow={true}
/>
</div>
</Modal>
}
</Fragment>
);
}
}
.FormArray {
padding: 18px 12px 0 12px;
:global {
.ant-form-item {
margin-bottom: 12px;
}
}
.textDecoration {
:global {
.ant-input-number-input {
text-decoration: line-through;
}
}
}
.colDom {
:global {
}
}
}
.spd {
padding: 0;
:global {
.ant-form-item {
margin-bottom: 6px;
}
.ant-tag, .ant-tag a, .ant-tag a:hover {
color: #84d945;
}
}
}
.FieldList {
@height: 30px;
padding-right: 10px;
padding-left: 10px;
.colOut {
padding: 10px;
.group {
border: 1px solid #eee;
height: 30px;
}
.name {
background-color: #eee;
text-align: center;
font-size: 14px;
color: #3a3a3a;
height: 100%;
line-height: @height;
}
.discrib {
padding-left: 5px;
font-size: 12px;
letter-spacing: .1px;
color: #3a3a3a;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 100%;
line-height: @height;
}
}
}
.FieldListWithoutBg {
padding-top: 15px;
padding-right: 10px;
padding-left: 10px;
@height: 15px;
.withoutBgcolOut {
padding: 10px;
.withoutBgGroup {
height: @height;
}
.withoutBgName {
font-size: 14px;
color: #666;
height: 100%;
line-height: @height;
div {
text-align: right;
}
div:after {
content: " ";
display: inline-block;
width: 100%;
}
}
.withoutBgDiscrib {
padding-left: 12px;
font-size: 14px;
letter-spacing: .1px;
color: #555;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 100%;
line-height: @height;
}
}
}
.shell {
margin-top: 20px;
.row {
background-color: rgba(255, 255, 255, 1);;
}
}
.blockTitle {
border-bottom: 1px solid #ccc;
height: 48px;
display: flex;
align-items: center;
padding: 0 40px;
font-size: 18px;
color: #333;
font-weight: bold;
cursor: default;
position: relative;
&.isSmall {
font-size: 14px;
height: 36px;
padding: 0 30px;
border-bottom: 1px solid #eee;
}
}
.CardDiy {
:global {
.ant-card-head {
min-height: 40px;
height: 40px;
font-size: 14px;
padding: 0;
// padding: 13px 0px 12px 14px;
color: rgba(51, 51, 51, 1);
}
.ant-card-head-wrapper {
display: flex;
line-height: 40px;
height: 40px;
padding-left: 12px;
align-items: center;
}
.ant-card-extra {
padding-right: 12px;
}
.ant-card-body {
padding: 0;
span {
height: 40px;
p {
padding-left: 24px;
border-bottom: 1px solid #e8e8e8;
line-height: 40px;
margin-bottom: 0;
}
}
}
}
.handMouse {
cursor: pointer;
}
}
.NormalTable {
@TableThemeColor: #5e9ede;
@TableThemeBgColor: #e6f7ff;
padding: 6px 12px 0 12px;
:global {
.ant-table-thead > tr > th {
padding: 0 12px;
height: 50px;
color: rgba(0, 0, 0, .65);
background-color: #e9f2fb;
}
.ant-table-content {
// min-height: 500px;
}
p {
margin-bottom: 0 !important;
}
a {
color: @TableThemeColor;
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 10px 16px;
}
.ant-pagination-item-active, .ant-pagination-item:focus, .ant-pagination-item:hover {
border-color: @TableThemeColor;
}
.ant-pagination-options-quick-jumper input:focus {
border-color: @TableThemeColor;
box-shadow: 0 0 0 2px @TableThemeBgColor;
}
.ant-pagination-options-quick-jumper input:hover {
border-color: @TableThemeColor;
}
.ant-pagination-item:focus a, .ant-pagination-item:hover a {
color: @TableThemeColor;
}
.ant-pagination-item-active:focus a, .ant-pagination-item-active:hover a {
color: @TableThemeColor;
}
.ant-checkbox-checked .ant-checkbox-inner {
background-color: @TableThemeColor;
border-color: @TableThemeColor;
}
.ant-checkbox-wrapper:hover .ant-checkbox-inner, .ant-checkbox:hover .ant-checkbox-inner, .ant-checkbox-input:focus + .ant-checkbox-inner {
border-color: @TableThemeColor;
}
::selection {
background: @TableThemeColor;
}
.ant-checkbox-indeterminate .ant-checkbox-inner:after {
background: @TableThemeColor;
}
tbody > tr.ant-table-row-hover:not(.ant-table-expanded-row) > td, .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td {
background: @TableThemeBgColor;
}
.ant-pagination {
width: 100%;
text-align: center;
padding-top: 20px;
}
}
}
.ButtonDiy {
@blue: rgba(25, 152, 240, 1);
@white: rgba(255, 255, 255, 1);
@red: #F14B5A;
padding-right: 12px;
button {
height: 30px;
}
.primaryBlue {
font-size: 14px;
font-weight: 400;
color: @white;
height: 30px;
background: @blue;
border-radius: 2px;
border-color: @blue;
&:hover, &:active, &:focus {
background: @blue;
color: @white;
border-color: @white;
}
&:disabled {
color: rgba(0, 0, 0, 0.25);
background-color: #f5f5f5;
border-color: #d9d9d9;
}
}
.primaryRed {
font-size: 14px;
font-weight: 400;
color: @white;
height: 30px;
background: @red;
border-radius: 2px;
border-color: @red;
&:hover, &:active, &:focus {
background: @red;
color: @white;
border-color: @white;
}
}
.defaultBlue {
font-size: 14px;
font-weight: 400;
color: @blue;
height: 30px;
background: @white;
border-radius: 2px;
border-color: @blue;
&:hover, &:active, &:focus {
background: @white;
color: @blue;
border-color: @blue;
}
}
.defaultRed {
font-size: 14px;
font-weight: 400;
color: @red;
height: 30px;
background: @white;
border-radius: 2px;
border-color: @red;
&:hover, &:active, &:focus {
background: @white;
color: @red;
border-color: @red;
}
}
}
.collegeTitle {
color: #333;
font-size: 18px;
text-align: center;
padding-bottom: 74px;
font-weight: 600;
}
.collegeStyle {
// width: 100%;
:global {
.ant-col-2 {
width: 10%;
text-align: center
}
}
}
.colStyle {
color: #4992DF
}
.colStyle:hover {
background: green
}
.picName {
padding-left: 57px;
padding-top: 10px;
}
.modalDiy {
:global {
.ant-modal-title {
text-align: center;
font-size: 16px;
font-family: MicrosoftYaHei-Bold;
font-weight: bold;
color: rgba(51, 51, 51, 1);
}
}
}
/*:global{
.cls-2{
cursor: pointer !important;
}
}*/
.searchChangeMaintain {
margin-bottom: 0;
padding-top: 15px;
:global {
.ant-form-item-control {
line-height: 20px;
}
}
}
.exportModal {
:global {
.ant-modal-body {
padding: 12px;
}
.ant-form-item {
margin-bottom: 0;
}
.ant-form-item-label {
text-align: left;
}
}
}
.DescriptionContext {
width: 98%;
overflow-y: auto;
overflow-x: hidden;
word-break: break-word;
height: 500px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 14px;
color: black;
background-color: white;
}
.Editable {
box-sizing: border-box;
margin: 0;
list-style: none;
position: relative;
display: inline-block;
padding: 4px 11px;
width: 100%;
font-size: 14px;
line-height: 1.5;
color: rgba(0, 0, 0, 0.65);
background-color: #fff;
background-image: none;
border: 1px solid #d9d9d9;
border-radius: 4px;
transition: all .3s;
&:hover {
border-color: #29a6ff;
border-right-width: 1px !important;
}
}
.editorLayout {
line-height: normal;
:global {
.ql-container {
height: 400px;
}
}
}
.editorLayoutMin {
line-height: normal;
:global {
.ql-container {
height: 200px;
}
}
}
// 新闻列表
.horizonWrap {
margin-top: 20px;
.item {
margin-bottom: 20px;
cursor: pointer;
.itemInner {
transition: all .3s linear;
background-color: #fff;
height: 110px;
padding: 20px;
overflow: hidden;
display: flex;
&:hover {
box-shadow: 0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 20px 4px rgba(0, 0, 0, 0.12) !important;
}
.left {
flex: 0 0 70px;
height: 70px;
background-color: rgb(132, 192, 240);
position: relative;
font-size: 26px;
color: #fff;
font-weight: 600;
span {
display: inline-block;
position: absolute;
top: 0px;
left: 5px;
&:last-child {
top: auto;
right: 5px;
bottom: 0;
left: auto;
}
}
&::before {
content: '';
width: 70px;
height: 1px;
background-color: #fff;
transform: rotateZ(-45deg);
display: block;
position: absolute;
top: 34px;
left: 0px;
}
}
.right {
padding-left: 20px;
flex: 1;
overflow: hidden;
.title {
font-weight: 600;
color: #333;
font-size: 22px;
line-height: 1;
margin-bottom: 10px;
}
.content {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
font-size: 14px;
line-height: 20px;
/* autoprefixer: off*/
-webkit-box-orient: vertical;
/* autoprefixer: on*/
}
}
}
}
}
.PieChart {
:global {
.pie-stat {
padding-top: 10px;
}
}
}
.ListTab {
:global {
.ant-tabs-bar {
margin-bottom: 0px;
}
}
}
.customMultiple {
.multipleBox {
width: 100%;
height: 150px;
border: 1px solid rgba(210, 210, 210, 1);
border-radius: 6px;
overflow: auto;
background: white;
.multipleItem {
padding: 5px 10px;
cursor: pointer;
line-height: 1.5;
&:hover {
transition: all .3s linear;
background: #E9F2FB;
}
&.active {
background: #008DFF;
color: white;
}
}
}
.operationBtnBox {
display: flex;
flex-direction: column;
justify-content: center;
> span {
margin-bottom: 10px;
line-height: 1;
&:last-child {
margin-bottom: 0;
}
}
}
}
.specForm {
:global {
.ant-radio-wrapper {
margin-right: 0;
}
}
}
import { text, number, date } from '../config/index';
import { isJSON } from '@/baseComponent/utils';
import { translateAddFields } from '../config/index';
const handleSqlModels = (sqlModels, defaultValues) => {
if (typeof sqlModels === 'undefined' || !Array.isArray(sqlModels)) {
return [];
} else {
let res = [];
for (let x of sqlModels) {
let key = x.key;
if (!isJSON(x.cols)) {
let info = x.dataObjModel.columnModels;
for (let item in info) {
let z = info[item];
let oneFields = {
key: key + '_' + z.name,
name: z.title,
dataType: z.type,
required: false,
dataId: item,
comName: date.indexOf(z.type) > -1 ? 'DatePicker' : 'Input',
disabled: true,
};
oneFields.defaultValue = defaultValues[oneFields.key] || '';
res.push(oneFields);
}
continue;
}
let info = JSON.parse(x.cols); // name, title, type
for (let item in info) {
let z = info[item];
let oneFields = {
key: key + '_' + z.name,
name: z.title,
dataType: z.type,
required: false,
dataId: item,
comName: date.indexOf(z.type) > -1 ? 'DatePicker' : 'Input',
disabled: true,
};
oneFields.defaultValue = defaultValues[oneFields.key] || '';
res.push(oneFields);
}
}
return res;
}
};
const funcHandleFileds = (source, obj, fieldsColumns) => {
let fileds = [];
for (let item of source) {
for (let info of item) {
let oneFiled = {};
if (info.content) {
let content = info.content;
oneFiled = {
comName: content.comName,
name: content.label || '',
};
if(content.comName === 'DatePicker'){
if(content.format){
oneFiled.format = content.format;
}
}
if(content.comName === 'PartForm'){
const { childFormKey, columnIds, } = content;
let thisSource = obj[childFormKey].items;
let thisFields = funcHandleFileds(thisSource, obj, fieldsColumns);
for (let i = 0; i < thisFields.length; i++) {
if (typeof thisFields[i].c1 !== 'undefined') {
thisFields[i] = {
...fieldsColumns[thisFields[i].c1],
...thisFields[i],
};
}
}
oneFiled.componentProps = {
columnIds,
childFormKey,
thisFields,
};
}
if(content.comName === 'RangePicker'){
if(content.format){
oneFiled.format = content.format;
}
}
if (content.comName === 'Description') {
oneFiled.key = content.sqls[1];
}
if(['Radio', 'Select', 'Checkbox'].indexOf(content.comName)> -1){ // 枚举值
if(content.optionType){
oneFiled.optionType = content.optionType;
switch (oneFiled.optionType) {
case 'enum':
if(content.enums){
let options = isJSON(content.enums) ? JSON.parse(content.enums) : [];
options = options.map((x)=>{
return { key: x.value, name: x.label };
});
oneFiled.options = options;
}
break;
case 'reference':
oneFiled.filterSql = content.filterSql;
break;
case 'sql':
oneFiled.sqlKey = content.sqlKey;
oneFiled.labelName = content.labelName;
oneFiled.valueName = content.valueName;
break;
default:
oneFiled.options =[];
break;
}
}
}
if(content.comName === 'ChildForm'){
const { childFormKey, columnIds, } = content;
let thisSource = obj[childFormKey].items;
let thisFields = funcHandleFileds(thisSource, obj, fieldsColumns);
for (let i = 0; i < thisFields.length; i++) {
if (typeof thisFields[i].c1 !== 'undefined' && typeof fieldsColumns[thisFields[i].c1] !== 'undefined') {
thisFields[i] = {
...fieldsColumns[thisFields[i].c1],
...thisFields[i],
};
}
}
oneFiled.componentProps = {
columnIds,
childFormKey,
thisFields,
};
}
if(content.comName === 'TableSelect'){
oneFiled.componentProps = {
sqlKey: content.sqlKey,
labelName: content.labelName,
valueName: content.valueName,
isMultiple: content.isMultiple,
};
}
if(content.comName === 'Label'){ // 提示信息显示
if(info.hidden){
continue;
}
oneFiled.key = content.initialValue ? content.initialValue.slice(0, 10) : ' ';
oneFiled.name = ' ';
oneFiled.defaultValue = content.initialValue;
oneFiled.dataType = 'TEXT';
}
for (let j in content.columnIds) {
let oneFields = content.columnIds[j];
oneFiled[j] = oneFields[1];
}
fileds.push(oneFiled);
}
}
}
return fileds;
};
export async function destructionGetDetail(response) {
/**
* 如果数据校验不通过直接pass 返回默认值,
* */
if (typeof response.unifiedServicePatternModel === 'undefined' ||
!isJSON(response.unifiedServicePatternModel.content) ||
!Array.isArray(response.unifiedServicePatternModel.dataObjModels) ||
!response.unifiedServicePatternModel.dataObjModels.length ||
typeof response.unifiedServicePatternModel.dataObjModels[0].columnModels === 'undefined'
) {
return {
addFields: [],
tableInfo: {},
allConfigSetInfo: response,
};
}
const basicPatternModel = response.unifiedServicePatternModel;
/** 正式开始 **/
/*** 字段name, dataType ***/
let fieldsColumns = {};
for(let dataObjModels of basicPatternModel.dataObjModels){
let columns = dataObjModels.columnModels;
for (let item of columns) {
fieldsColumns[item.base52] = {
name: item.title,
dataType: item.type,
key: item.base52,
dataId: item.id,
referenceCodeName: item.referenceCodeName,
referenceNameName: item.referenceNameName,
required: Boolean(!item.isNull),
};
}
}
/*** 字段组件类型 ***/
let data = JSON.parse(basicPatternModel.content);
let key = data.init;
let source = data.datas[key].items;
let fileds = funcHandleFileds(source, data.datas, fieldsColumns);
/*** 字段默认值 ***/
let sqlModeData = handleSqlModels(basicPatternModel.sqlModels, basicPatternModel.defaultValues); //Array
let defaultBinds = data.datas[key].defaultBinds;
let defaultKeys = {};
if(defaultBinds){
for(let item in defaultBinds){
let one = defaultBinds[item];
if(one && one.columnIds && one.sqls){
defaultKeys[one.sqls[1]] = one.columnIds[1];
}
}
}
for(let item of sqlModeData){
if(defaultKeys[item.key]){
item.defaultKey = defaultKeys[item.key];
}
}
/*** 流程表数据 ***/
let tableInfo = {
base52: basicPatternModel.dataObjModels[0].base52,
name: basicPatternModel.dataObjModels[0].name,
defaultValuesId: key,
};
for(let i = 0; i < fileds.length; i++){
let item = fileds[i];
if(item.comName === 'Description'){
if(item.key && !item.defaultValue && basicPatternModel.defaultValues && basicPatternModel.defaultValues[item.key]){
item.defaultValue = basicPatternModel.defaultValues[item.key];
}
for(let x of sqlModeData){
if(x.key === item.key){
item.c1 = x.defaultKey;
fileds[i] = {
...item,
...x,
}
}
}
}
}
for (let i = 0; i < fileds.length; i++) {
if (typeof fileds[i].c1 !== 'undefined') {
if(fileds[i].key && fieldsColumns[fileds[i].c1] && fieldsColumns[fileds[i].c1].key && fileds[i].key !== fieldsColumns[fileds[i].c1].key){
fileds[i].onestopDefaultKey = fileds[i].key;
}
fileds[i] = {
...fileds[i],
...fieldsColumns[fileds[i].c1],
};
}
}
return {
addFields: await translateAddFields(fileds, tableInfo),
tableInfo,
allConfigSetInfo: response,
};
}
export function getDefaultValues(addFields = [], tableInfo = {}){
const values = {
defaultValues: {
[tableInfo.defaultValuesId]: {},
}
};
const defalutValues = {};
for(let item of addFields){
if(typeof item.defaultValue !== 'undefined'){
values[item.key] = item.defaultValue;
// values[item.onestopDefaultKey] = item.defaultValue;l;l
}
if(typeof item.defaultKey !== 'undefined' && item.defaultKey){
values[item.defaultKey] = item.defaultValue; // 表单渲染需要这个值
defalutValues[item.key] = item.defaultValue;
defalutValues[item.onestopDefaultKey] = item.defaultValue;
}
}
values.defaultValues[tableInfo.defaultValuesId] = defalutValues; //传给后台需要这个值
return values;
}
/**
* 事务页面。 根据一站式服务大厅的事务接口。达到增删发起事务流程
* 2019年10月23日 09:48:13
* 钟是志
*
* */
import { apiRequest } from '../request';
import { getFormArrayConfig } from '../config/index';
import { setHuanGeToken } from '@/utils/authority';
import { isJSON } from '@/baseComponent/utils';
const giveValue = (x) => {
if(x && x.rows){
let res = [];
for(let item of x.rows){
res.push({
...item.hisTaskListData,
...item,
});
}
x.rows = res;
return x;
}else{
return {
rows: [],
total: 1,
};
}
};
const getOtherToken = () => {
let userName = sessionStorage.getItem("currentUser");
if(isJSON(userName)){
let name = JSON.parse(userName).name;
return apiRequest(`/UserApi/loginByCount?username=${name}`, {}).then((res)=>{
if(res){
setHuanGeToken(res.token);
}
});
}
};
const getId = () => { // 获取流程引擎 事务workId 和表dataBaseId
let path = window.location.href;
path = path.split('/');
// let idObj = config[path.pop()];
let idObj;
if (typeof idObj === 'undefined') {
console.error('没有找到对应的流程引擎id');
return false;
} else {
const { dataBaseId, workId } = idObj;
return {
dataBaseId,
workId,
};
}
};
const getColumns2 = (id) => { // 获取表头 workId
return apiRequest('/DataColumnApi/getHeaderList', { dataObjId: id }).then((response)=>{
if(response){
return response.map((x)=>{
return {
title: x.title,
dataIndex: x.name,
type: x.type,
}
})
}
});
};
const getPages = (info) => { // 获取代办事项 分页数据 workId
// workId, pageSize, pageNo,
if (typeof info.pageNo === 'undefined') {
info.pageNo = 1;
info.pageSize = 10;
}
return apiRequest('/UnifiedAppFormApi/getWaitPage', info);
};
const getQueryCondition = (dataObjId) => { // 获取搜索条件 dataBaseId //暂时未生效. 因为欢哥那边不支持
return [];
return apiRequest('/DataColumnApi/getHeaderList', { dataObjId }).then((response) => {
let res = [];
if(response){
for(let item of response){
if(item.isShowQuery){
let sear = getFormArrayConfig([item]);
if(!Array.isArray(sear)){
return false;
}
delete sear[0].required;
delete sear[0].placeHolder;
res.push(sear[0]);
}
}
}
return res;
});
};
const getListPage = (info) => { // 获取表数据。dataObjId
if (typeof info.pageNo === 'undefined') {
info.pageNo = 1;
info.pageSize = 10;
}
return apiRequest('/DataObjApi/getFormDataPage', info);
};
const deleteFormData = (dataBaseId, id) => { // 删除表数据.
const info = {
keys: JSON.stringify({id}),
objId: dataBaseId,
};
return apiRequest('/DataObjApi/deleteFormData', info);
};
/****************************** 以上接口暂时不用 ****************************/
const getColumns = (workId) => { // 获取表头 workId
return apiRequest('/UnifiedAppFormApi/getFormTitle', { id: workId });
};
/**
* 获取下拉枚举值
* */
const getOptions = async (id, filterSql = undefined, key, name) => {
return await apiRequest('/DataColumnApi/getOptions', {id, filterSql}).then((x)=>{
if(x){
return x.map((y)=>{
return {
key: y[key],
name: y[name],
}
})
}else{
return [];
}
});
};
/**
* 获取下拉枚举值 通过sql语句
* */
const getSqlOptions = async (id, sqlKey = undefined, key, name ) => {
return await apiRequest('/DataColumnApi/getSqlOptions', {id, sqlKey}).then((x)=>{
if(x){
return x.map((y)=>{
return {
key: y[key],
name: y[name],
}
})
}else{
return [];
}
});
};
/**
* 获取发起流程填写的字段表单详情
* */
const getFormDetail = (id) => {
return apiRequest('/UnifiedAppApi/getDetail', {id}).then((x)=>{
if(x){
return x;
}else{
return {};
}
});
};
/**
* 发起流程
* */
const startProcess = (info) => {
return apiRequest('/UnifiedAppFormApi/startProcess', info).then((x)=>{
if(x){
return x;
}else{
return null;
}
});
};
/**
* 查询已发起的流程的分页接口
*
* */
const getApplyPage = (info) => {
return apiRequest('/UnifiedAppFormApi/getApplyPage', info).then((x)=>{
return giveValue(x);
});
};
/**
* 查询一个流程的详情数据
*
* */
const getDetailInfo = (id) => {
return apiRequest('/UnifiedAppFormApi/getFormDetail', {id}).then((x)=>{
if(x){
return x;
}else{
return null;
}
});
};
/**
* 待办业务
* pageSize: 10
* appId: 1185524814832467968
* pageNo: 1
* */
const getWaitPage = (info) => {
return apiRequest('/UnifiedAppFormApi/getWaitPage', info).then((x) => {
return giveValue(x);
})
};
/**
* 已办业务
* pageSize: 10
* appId: 1185524814832467968
* pageNo: 1
* */
const getHandledPage = (info) => {
return apiRequest('/UnifiedAppFormApi/getHandledPage', info).then((x) => {
return giveValue(x);
})
};
/**
* 审核接口,支持批量
* taskIds: 08d8d359-f7a6-11e9-9a27-0242b1fd760b
* examineMap: {"examine":"0","reason":"通过"}
* taskForm: {}
* */
const handleAudit = (info) => {
return apiRequest('/UnifiedAppFormApi/examineProcess', info).then((x) => {
if(x){
return x;
}
})
};
const handleSqlData = (info) => {
return apiRequest('/DataColumnApi/getSqlData', info).then((x) => {
if(x){
return x;
}else{
return [];
}
})
};
const handleSqlfind = async(sqlKey = '') => {
return await apiRequest('/SqlManageEntityApi/find', {sqlKey}).then((x) => {
if(x){
return x;
}else{
return null;
}
})
};
/**
* 流程紧急度
* 2019年12月5日
* 钟是志
* 先默认给后台传个值 保证能提交申请
* */
const getSeriousOptions = () => {
return apiRequest('/UnifiedAppFormLevelApi/getAll', {}).then((x)=>{
if(x){
return x.map((s)=>{
return {
key: s.id,
name: s.name,
color: s.color,
}
})
}
});
};
export {
getId, getColumns, getPages, getQueryCondition,
getListPage, deleteFormData, getColumns2, getFormDetail,
getOptions, startProcess, getApplyPage, getOtherToken,
getDetailInfo, getWaitPage, getHandledPage, handleAudit,
handleSqlData,handleSqlfind, getSqlOptions, getSeriousOptions,
};
import React, { Fragment } from 'react';
import {
Button,
Card, Col,
Form, message, Row,
} from 'antd';
import { connect } from 'dva';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import moment from 'moment';
import router from 'umi/router';
import { text, number, date, getFormArrayConfig } from '../config/index';
import FormArray from '../AffairPage/component/FormArray';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import Shell from '../Shell';
@connect(({ formList, loading }) => ({
formList,
}))
@Form.create()
class Edit extends React.Component {
state = {
modalVisible: false,
formData: {},
formItem: [],
isAdd: false,
objId: this.props.id,
recordId: this.props.recordId,
recordKey: this.props.recordKey,
};
columns = [];
//渲染值
componentDidMount() {
const { dispatch } = this.props;
const { objId, recordKey, recordId } = this.state;
dispatch({
type: 'formList/getHead',
payload: { dataObjId: objId },
callback: (dates) => {
if (dates) {
this.setState({
formItem: dates,
});
}
},
});
//渲染表单字段
if (recordId != null) {
dispatch({
type: 'formList/getDetail',
payload: {
dataObjId: objId,
key: recordKey,
value: recordId,
},
callback: (res) => {
if (res) {
this.setState({
formData: res,
});
}
},
});
this.setState({
isAdd: false,
})
}else{
this.setState({
isAdd: true,
})
}
}
onSubmit = () => {
//router.goBack();
const { isAdd, objId, formData } = this.state;
let payload = {
params: {...formData},
objId,
isAdd,
};
this.props.dispatch({
type: 'formList/add',
payload,
callback: () => {
message.success('操作成功');
this.props.returnThis();
},
});
};
goBack = () => {
this.props.returnThis();
};
changeFormData = (value, key) => {
let oldValue = this.state.formData;
oldValue[key] = value;
this.setState({
formData: oldValue,
});
};
render() {
let { formItem, formData } = this.state;
let formConfig = getFormArrayConfig(formItem);
return (
<Shell>
<Row>
<FormArray
config={formConfig}
nameSpan={{ big: 10, small: 12 }}
fileSpan={{ big: 4, small: 3 }}
value={formData}
changeValue={this.changeFormData}
/>
<Col span={24}
style={{ textAlign: 'center', paddingTop: '200px', paddingBottom: '50px' }}>
<ButtonDiy
className={'primaryBlue'}
handleClick={this.onSubmit}
name={'保存'}
/>
<ButtonDiy
className={'defaultRed'}
handleClick={this.goBack}
name={'返回'}
/>
</Col>
</Row>
</Shell>
);
}
}
export default Edit;
import React from 'react'
import { Select,Input,InputNumber,Button } from 'antd';
const Option = Select.Option;
export default class OrderItem extends React.Component {
constructor(props) {
super(props);
const value = props.value || {};
this.state = {
stringX:value.stringX,
};
}
componentWillReceiveProps(nextProps) {
// Should be a controlled component.
if ('value' in nextProps) {
const value = nextProps.value;
this.setState(value);
}
}
triggerChange = (changedValue) => {
// Should provide an event to pass value to Form.
const onChange = this.props.onChange;
if (onChange) {
onChange(Object.assign({}, this.state, changedValue));
}
};
changeStringX=(e)=>{
if (!('value' in this.props)) {
this.setState({ stringX:e });
}
this.triggerChange({ stringX:e });
};
render() {
const {stringX} =this.state;
return (
<div>
<span style={{padding: '0px 10px'}}>
<Select onChange={this.changeStringX}
value={stringX}
style={{width:200}}>
<Option value="desc" key='desc'>降序</Option>
<Option value="asc" key='asc'>升序</Option>
</Select>
</span>
<span style={{paddingLeft:100}}>
<Button type="danger" onClick={this.props.deleteOrder}>删除</Button>
</span>
</div>)
}
}
import React from 'react'
import { Select,Input,InputNumber,Button,DatePicker } from 'antd';
import {date, text, number } from '../config/index';
import moment from 'moment';
const Option = Select.Option;
export default class QueryItem extends React.Component {
constructor(props) {
super(props);
const value = props.value || {};
this.state = {
stringX:value.stringX,
string:value.string,
disabled:value.disabled||false
};
}
componentWillReceiveProps(nextProps) {
// Should be a controlled component.
if ('value' in nextProps) {
const value = nextProps.value;
this.setState(value);
}
}
triggerChange = (changedValue) => {
// Should provide an event to pass value to Form.
const onChange = this.props.onChange;
if (onChange) {
onChange(Object.assign({}, this.state, changedValue));
}
};
changeNumber=(e)=>{
if (!('value' in this.props)) {
this.setState({ string:e});
}
this.triggerChange({ string:e});
};
changeStringX=(e)=>{
var disabled = false
if(e=="IS NOT NULL"||e=="IS NULL"){
disabled=true;
}
if (!('value' in this.props)) {
this.setState({ stringX:e ,disabled});
}
this.triggerChange({ stringX:e ,disabled});
};
changeString=(e)=>{
if (!('value' in this.props)) {
this.setState({ string:e.target.value });
}
this.triggerChange({ string:e.target.value });
};
changeDate=(date)=>{
console.log(date)
if (!('value' in this.props)) {
this.setState({ string:date.format("YYYY-MM-DD HH:mm:ss")});
}
this.triggerChange({ string:date.format("YYYY-MM-DD HH:mm:ss") });
};
render() {
const{obj} = this.props;
const {string,stringX,disabled} =this.state;
if(obj.options && obj.options.length>0){
return(<div> <Select onChange={this.changeStringX}
value={stringX||"="}
style={{width:100}}>
<Option value="=">等于</Option>
<Option value="<>">不等于</Option>
<Option value="IS NOT NULL">不为空</Option>
<Option value="IS NULL">为空</Option>
</Select>
{disabled?"": <span style={{padding: '0px 10px'}}>
<Select onChange={this.changeNumber}
value={string}
style={{width:200}}>
{obj.options.map((r)=><Option key={r.v} value={r.v}>{r.l}</Option>)}
</Select>
</span>}
<Button type="danger" onClick={this.props.deleteQuery}>删除</Button>
</div>)
}
if(text.includes(obj.type)){
return (
<div>
<Select onChange={this.changeStringX}
value={stringX||"="}
style={{width:100}}>
<Option value="=">等于</Option>
<Option value="!=">不等于</Option>
<Option value="like"></Option>
<Option value="IS NOT NULL">不为空</Option>
<Option value="IS NULL">为空</Option>
</Select>
{disabled?"": <span style={{padding: '0px 10px'}}>
<Input onChange={this.changeString}
placeholder="请输入"
value={string}
style={{width:200,}}
/>
</span>}
<Button type="danger" onClick={this.props.deleteQuery}>删除</Button>
</div>)
}else if(number.includes(obj.type)){
return ( <div> <Select onChange={this.changeStringX}
value={stringX||"="}
style={{width:100}}>
<Option value="=">等于</Option>
<Option value="<>">不等于</Option>
<Option value=">">大于</Option>
<Option value=">=">大于等于</Option>
<Option value="<">小于</Option>
<Option value="<=">小于等于</Option>
<Option value="IS NOT NULL">不为空</Option>
<Option value="IS NULL">为空</Option>
</Select>
{disabled?"": <span style={{padding: '0px 10px'}}>
<InputNumber onChange={this.changeNumber}
placeholder="请输入"
value={string}
style={{width:200}}
/>
</span>}
<Button type="danger" onClick={this.props.deleteQuery}>删除</Button>
</div>)
}else if(obj.type === "BIT"){
return ( <div>
<Select onChange={this.changeStringX}
value={stringX||"="}
style={{width:100}}>
<Option value="=">
等于
</Option>
</Select>
{disabled?"": <span style={{padding: '0px 10px'}}>
<Select onChange={this.changeNumber}
value={string}
style={{width:200}}
>
<Option value={true}>
</Option>
<Option value={false}>
</Option>
</Select>
</span>}
<Button type="danger" onClick={this.props.deleteQuery}>删除</Button>
</div>)
}else if(date.includes(obj.type)){
return(<div>
<Select onChange={this.changeStringX}
value={stringX||"="}
style={{width:100}}>
<Option value="=">等于</Option>
<Option value="<>">不等于</Option>
<Option value=">">大于</Option>
<Option value=">=">大于等于</Option>
<Option value="<">小于</Option>
<Option value="<=">小于等于</Option>
<Option value="IS NOT NULL">不为空</Option>
<Option value="IS NULL">为空</Option>
</Select>
{disabled?"": <span style={{padding: '0px 10px'}}>
<DatePicker onChange={this.changeDate}
showTime
format="YYYY-MM-DD HH:mm:ss"
allowClear={false}
style={{width:200}}
value={string?moment(string):null}
/>
</span>}
<Button type="danger" onClick={this.props.deleteQuery}>删除</Button>
</div>)
}else{
return (<span>暂无法处理</span>)
}
}
}
import fetch from 'dva/fetch';
import React from 'react';
import ReactDOM from 'react-dom';
import { Select, Button, Modal, Input, Transfer, Row, Col, Form, message, notification } from 'antd';
import { connect } from 'dva';
import { getToken } from '@/utils/authority';
import config from '@/config/config';
import QueryItem from './QueryItem';
import OrderItem from './OrderItem';
import FormdataWrapper from '@/utils/object-to-formdata-custom';
const Option = Select.Option;
let keyX = 1;
function swapArray(arr, index1, index2) {
arr[index1] = arr.splice(index2, 1, arr[index1])[0];
return arr;
}
const FormItem = Form.Item;
@connect(({ DataObj, loading }) => ({
DataObj,
loading: loading.models.DataObj,
}))
@Form.create()
export default class Index extends React.Component {
constructor(props) {
super(props);
this.state = {
visiable: false,
queryVisiable: false,
groupVisiable: false,
sortVisiable: false,
currentQueryKey: null,
currentGroupKey: null,
orderVisiable: false,
currentOrderKey: null,
querys: [],
orders: [],
groups: [],
gs: [],
os: [],
qs: [],
mockData: [],
targetKeys: [],
sourceSelectedKeys: [],
targetSelectedKeys: [],
infos: {},
confirmLoading: false,
};
}
onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => {
this.setState({ sourceSelectedKeys, targetSelectedKeys });
};
deleteQuery = (i) => {
const querys = this.state.querys;
querys.splice(i, 1);
this.setState({ querys });
};
deleteOrder = (i) => {
const orders = this.state.orders;
orders.splice(i, 1);
this.setState({ orders });
};
deleteGroup = (i) => {
const groups = this.state.groups;
groups.splice(i, 1);
this.setState({ groups });
};
open = () => {
const { dispatch } = this.props;
dispatch({
type: 'DataObj/getExportInfo',
payload: {
objId: this.props.objId,
},
callback: (infos) => {
const mockData = [];
const qs = [];
const gs = [];
const os = [];
for (var key in infos) {
const x = infos[key];
mockData.push({
key: x.field,
title: x.name,
chosen: false,
});
if (x.canQuery) {
qs.push(x);
}
if (x.canGroup) {
gs.push(x);
}
if (x.canOrder) {
os.push(x);
}
}
this.setState({
mockData, infos, visiable: true, qs, gs, os,
});
},
});
};
onCancle = () => {
this.setState({ visiable: false });
};
handleChange = (targetKeys, direction, moveKeys) => {
this.setState({ targetKeys });
};
up = () => {
keyX = keyX + 1;
var { targetKeys, targetSelectedKeys } = this.state;
for (var i = 0; i < targetKeys.length; i++) {
if (targetKeys[i] === targetSelectedKeys[0]) {
if (i === 0) return;
targetKeys = swapArray(targetKeys, i, i - 1);
break;
}
}
this.setState({ targetKeys });
};
down = () => {
keyX = keyX + 1;
var { targetKeys, targetSelectedKeys } = this.state;
for (var i = 0; i < targetKeys.length; i++) {
if (targetKeys[i] === targetSelectedKeys[0]) {
if (i === targetKeys.length - 1) return;
targetKeys = swapArray(targetKeys, i, i + 1);
break;
}
}
this.setState({ targetKeys });
};
bottom = () => {
keyX = keyX + 1;
const { targetKeys, targetSelectedKeys } = this.state;
var x = [];
for (var i = 0; i < targetKeys.length; i++) {
if (!targetSelectedKeys.includes(targetKeys[i])) {
x.push(targetKeys[i]);
}
}
x = [...x, ...targetSelectedKeys];
this.setState({ targetKeys: x });
};
top = () => {
keyX = keyX + 1;
const { targetKeys, targetSelectedKeys } = this.state;
const x = [...targetSelectedKeys];
for (var i = 0; i < targetKeys.length; i++) {
if (!targetSelectedKeys.includes(targetKeys[i])) {
x.push(targetKeys[i]);
}
}
this.setState({ targetKeys: x });
};
renderItem = (item) => {
if (this.state.targetKeys.includes(item.key)) {
const customLabel = (
<span className="custom-item" key={item.key}>
{item.title}
</span>
);
return {
label: customLabel, // for displayed item
value: item.title, // for title and filter matching
};
} else {
const customLabel = (
<span className="custom-item" key={item.key}>
{item.title}
</span>
);
return {
label: customLabel, // for displayed item
value: item.title, // for title and filter matching
};
}
};
addOrder = () => {
this.setState({ orderVisiable: true });
};
okOrder = () => {
const orders = this.state.orders;
orders.push(this.state.infos[this.state.currentOrderKey]);
this.setState({ orders, orderVisiable: false, currentOrderKey: null });
};
okGroup = () => {
const groups = this.state.groups;
groups.push(this.state.infos[this.state.currentGroupKey]);
this.setState({ groups, groupVisiable: false, currentGroupKey: null });
};
addGroup = () => {
this.setState({ groupVisiable: true });
};
addQuery = () => {
this.setState({ queryVisiable: true });
};
okQuery = () => {
const querys = this.state.querys;
querys.push(this.state.infos[this.state.currentQueryKey]);
this.setState({ querys, queryVisiable: false, currentQueryKey: null });
};
export = () => {
this.props.form.validateFields((err, fieldsValue) => {
if (err) return;
//form.resetFields();
var qqs;
if (this.props.mustQuerys != null) {
qqs = [...this.props.mustQuerys];
} else {
qqs = [];
}
const oos = [];
const ggs = [];
for (let key in fieldsValue) {
var x = key.indexOf('__');
let kk = key.substr(x + 2);
if (key.indexOf('q__') > -1) {
qqs.push({
notes: this.state.infos[kk].notes,
hql: this.state.infos[kk].hql,
c: this.state.infos[kk].type,
x: fieldsValue[key].stringX,
v: fieldsValue[key].string,
});
} else if (key.indexOf('o__') > -1) {
oos.push({ hql: this.state.infos[kk].hql, x: fieldsValue[key].stringX });
} else if (key.indexOf('g__') > -1) {
ggs.push({ hql: this.state.infos[kk].hql });
}
}
if (this.props.voClass && ggs.length === 0) {
message.error('请至少选择一个聚合条件');
return;
}
if (this.state.targetKeys.length === 0) {
message.error('请至少选择一个导出字段');
return;
}
const names = [];
for (let i = 0; i < this.state.targetKeys.length; i++) {
names.push(this.state.infos[this.state.targetKeys[i]].name);
}
let divElement = document.getElementById('downloadDiv');
console.log(config.sqlFormsServer);
let downloadUrl = config.sqlFormsServer + '/DataObjApi/exportFormData?';
const token = getToken() != null && getToken() != 'null' ? getToken() : '0000';
downloadUrl = `${downloadUrl}token=${token}`;
let param = {
fields: this.state.targetKeys,
names: names,
beanName: this.props.beanName,
querys: JSON.stringify(qqs),
orders: JSON.stringify(oos),
groups: JSON.stringify(ggs),
voClass: this.props.voClass,
objId:this.props.objId,
modelClass: this.props.modelClass,
preHandleClass: this.props.preHandleClass,
hqlHandleClass: this.props.hqlHandleClass,
};
param = {...param, ...this.props.params || {}}
this.downloadFile(downloadUrl, param);
});
};
downloadFile(url, params) {
this.setState({ confirmLoading: true });
fetch(url, {
method: 'POST',
body: FormdataWrapper(params),
}).then(res => {
if (res.status != '200') {
return res.json();
} else {
return res.blob();
}
}).then(data => {
if (data instanceof Blob) {
let a = document.createElement('a');
let url = window.URL.createObjectURL(data);
let filename = (this.props.fileName ? this.props.fileName : '导出文件') + '.xlsx';
a.href = url;
a.download = filename;
a.click();
window.URL.revokeObjectURL(url);
a = null;
} else {
notification.error({
message: `文件导出错误`,
description: data.errMsg,
});
}
}).catch(err => {
notification.error({
message: `网络请求超时`,
});
}).finally(() => {
this.setState({ confirmLoading: false });
});
}
cancelGroup = () => {
this.setState({ currentGroupKey: null, groupVisiable: false });
};
cancelQuery = () => {
this.setState({ currentQueryKey: null, queryVisiable: false });
};
cancelOrder = () => {
this.setState({ currentOrderKey: null, orderVisiable: false });
};
selectOrder = (e) => {
this.setState({ currentOrderKey: e });
};
selectQuery = (e) => {
this.setState({ currentQueryKey: e });
};
selectGroup = (e) => {
this.setState({ currentGroupKey: e });
};
render() {
const { form } = this.props;
const {
visiable, targetKeys, sourceSelectedKeys, queryVisiable, querys, orders, groups, confirmLoading,
targetSelectedKeys, mockData, qs, os, gs, currentQueryKey, currentOrderKey, orderVisiable, currentGroupKey, groupVisiable,
} = this.state;
return (
<span>
<Button onClick={this.open}>自定义导出</Button>
<div id='downloadDiv' style={{ display: 'none' }}></div>
<Modal
width={670}
maskClosable={false}
destroyOnClose
title="自定义查询、排序、导出"
style={{ textAlign: 'center' }}
visible={visiable}
onOk={this.export}
onCancel={this.onCancle}
confirmLoading={confirmLoading}
>
<div style={{ overflowY: 'auto', maxHeight: '500px', height: '500px' }}>
<div style={{ textAlign: 'left' }}>
<Button type="primary">新增查询条件</Button>
<Select style={{ width: 200, paddingRight: '10px' }}
value={currentQueryKey}
onChange={this.selectQuery}>
{qs.map((r) => {
return <Option key={r.field}
value={r.field}>
{r.name}
</Option>;
},
)}
</Select>
{currentQueryKey ?
<span style={{ paddingLeft: '0' }}>
<Button type="primary" onClick={this.okQuery}>确定</Button>
</span>
: ''}
<div style={{ height: '12px' }}>
</div>
{querys.map((r, i) =>
<FormItem key={r.name + i}
labelCol={{ span: 4 }}
wrapperCol={{ span: 20 }}
colon={false}
label={r.name}>
{form.getFieldDecorator(i + 'q__' + r.field, {
initialValue: { stringX: '=' },
rules: [{
validator: (rule, value, callback) => {
var errors = [];
if (value == null) {
errors.push(new Error('请输入查询值!', rule.field));
} else {
if (value.stringX != 'IS NOT NULL' && value.stringX != 'IS NULL' && value.string == null) {
errors.push(new Error('请输入查询值!', rule.field));
}
}
callback(errors);
},
}],
})(
<QueryItem obj={r}
key={r.name + i}
deleteQuery={this.deleteQuery.bind(this, i)}/>)}
</FormItem>)
}
</div>
<div style={{ textAlign: 'left', paddingTop: '15px' }}>
<Button type="primary">新增排序条件</Button>
<Select style={{ width: 200, paddingRight: '10px' }}
value={currentOrderKey}
onChange={this.selectOrder}>
{os.map((r) => {
for (let j = 0; j < orders.length; j++) {
if (orders[j].field === r.field) return;
}
return <Option key={r.field} value={r.field}>{r.name}</Option>;
},
)}
</Select>
{currentOrderKey ?
<span style={{ paddingLeft: '0' }}>
<Button type="primary" onClick={this.okOrder}>确定</Button>
</span>
: ''}
<div style={{ height: '12px' }}>
</div>
{orders.map((r, i) =>
<FormItem key={r.name + i}
labelCol={{ span: 4 }}
wrapperCol={{ span: 20 }}
colon={false}
label={'按' + r.name}>
{form.getFieldDecorator(i + 'o__' + r.field, {
initialValue: { stringX: 'desc' },
})(
<OrderItem deleteOrder={this.deleteOrder.bind(this, i)}/>)}
</FormItem>)}
</div>
{this.props.voClass ?
<div style={{ textAlign: 'left', paddingTop: '15px' }}>
<span style={{ paddingRight: '10px' }}>聚合条件:</span>
{!groupVisiable ?
<Button type="primary" onClick={this.addGroup}>新增</Button>
:
<span>
<Select style={{ width: 100 }}
value={currentGroupKey}
onChange={this.selectGroup}>
{gs.map((r) => {
for (var j = 0; j < groups.length; j++) {
if (groups[j].field == r.field) return;
}
return <Option key={r.field}
value={r.field}>
{r.name}
</Option>;
},
)}
</Select>
{currentGroupKey ?
<Button type="primary" onClick={this.okGroup}>确定</Button>
: ''}
<Button type="primary" onClick={this.cancelGroup}>取消</Button>
</span>}
{groups.map((r, i) =>
<FormItem key={i + r.name}
labelCol={{ span: 5 }}
wrapperCol={{ span: 15 }}
label={'按' + r.name + '聚合'}>
{form.getFieldDecorator(i + 'g__' + r.field)(
<Input style={{ display: 'none' }}
value=""/>)}
<Button type="danger" onClick={this.deleteGroup.bind(this, i)}>删除</Button>
</FormItem>)}
</div> : ''}
<Row>
<Col span={24}
style={{ textAlign: 'left', paddingTop: '15px' }}>
<span style={{ paddingRight: '10px' }}>导出项:</span>
{/*<Select>*/}
{/*{*/}
{/*}*/}
{/*</Select>*/}
</Col>
<Col span={18}>
<Transfer key={keyX}
style={{ textAlign: 'left' }}
dataSource={mockData}
listStyle={{
width: 200,
height: 300,
}}
onSelectChange={this.onSelectChange}
selectedKeys={[...sourceSelectedKeys, ...targetSelectedKeys]}
rowKey={record => record.key}
targetKeys={targetKeys}
onChange={this.handleChange}
render={this.renderItem}
/>
</Col>
<Col span={2}>
<div style={{ marginTop: 100 }}>
<Button size="small"
disabled={targetSelectedKeys.length === 0}
onClick={this.top}>
批量置顶
</Button>
<Button size="small"
style={{ marginTop: 10 }}
disabled={targetSelectedKeys.length !== 1}
onClick={this.up}>
单项上移
</Button>
<Button size="small"
style={{ marginTop: 10 }}
disabled={targetSelectedKeys.length !== 1}
onClick={this.down}>
单项下移
</Button>
<Button size="small"
style={{ marginTop: 10 }}
disabled={targetSelectedKeys.length === 0}
onClick={this.bottom}>
批量置底
</Button>
</div>
</Col>
</Row>
</div>
</Modal>
</span>
);
}
}
import React, { Fragment } from 'react';
import {
Button,
Modal,
Steps,
Upload,
Icon,
message,
Tabs,
Table,
} from 'antd';
import styles from './ImportUtil.less';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import { exportExcel } from 'xlsx-oc'
import config from '@/config/config';
import { connect } from 'dva';
const Step = Steps.Step;
const TabPane = Tabs.TabPane;
@connect(({ DataObj, loading }) => ({
DataObj,
loading: loading.models.DataObj,
}))
export default class ImportUtil extends React.PureComponent {
constructor(props) {
super(props);
const exportTemplateUrl= encodeURI(`${config.sqlFormsServer}/DataObjApi/importTemplateDownload?objId=${this.props.objId}&name=${props.fileName}`);
this.state = {
ch:false,
currentKey:"1",
visible: false,
current: 0,
isShow: true,
filekey: '',
sucData: [],
errData: [],
column: [],
exportTemplateUrl,
isNextDisabled:false,
};
}
showModal = () => {
this.setState({
visible: true,
});
};
handleOk = (e) => {
this.setState({
visible: false,
});
};
handleCancel = (e) => {
this.setState({
visible: false,
});
};
next() {
const current = this.state.current + 1;
if (current === 2) {
this.setState({
current: current,
isShow: false,
});
if (this.state.errData.lenth > 0) {
message.error('请检查数据');
return;
} else {
this.import();
}
}
if (current === 3) {
this.setState({
current: current,
isShow: true,
});
if (this.props.callback) {
this.props.callback();
}
}
}
prev() {
const current = this.state.current - 1;
this.setState({ current });
}
import() {
const { dispatch ,importParams } = this.props;
dispatch({
type: 'DataObj/importExecute',
payload: {
...(importParams||{}),
cacheKey:this.state.filekey,
objId: this.props.objId,
},
callback: (res) => {
this.next();
message.success('导入成功');
this.setState({
current: 3,
isShow: true,
visible: false,
});
if(this.props.callback){
this.props.callback();
}
}
})
}
getCachKey = (filePath) => {
const { dispatch ,importParams } = this.props;
dispatch({
type: 'DataObj/importAnalyse',
payload: {
...(importParams||{}),
isLocal:false,
filePath,
objId: this.props.objId,
},
callback: (res) => {
this.setState({
filekey: res.cacheKey,
});
this.queryFile(res.cacheKey);
}
})
};
queryFile = (cacheKey) => {
const { dispatch ,importParams } = this.props;
dispatch({
type: 'DataObj/importDataQuery',
payload: {
...(importParams||{}),
cacheKey,
objId: this.props.objId,
},
callback: (res) => {
this.setState({
current: 1,
isShow: false,
sucData: res.pass,
errData: res.noPass,
column: res.column
});
if(res.noPass&&res.noPass.length==0){
if (res.pass.length==0) {
message.error('当前没有验证成功的数据,无法导入。');
this.setState({
currentKey:"1",
ch:!this.state.ch,
isNextDisabled: true
});
} else {
message.success('所有数据验证通过,请确认后点击下一步。');
this.setState({
currentKey:"2",
ch:!this.state.ch,
isNextDisabled: false
});
}
}else{
message.error('当前存在未验证通过的数据,请按错误提示检测更正导入文件');
this.setState({
currentKey:"1",
ch:!this.state.ch,
isNextDisabled: true
});
}
}
})
};
changePane=(activeKey)=>{
this.setState({currentKey:activeKey})
}
exportError=(column,dataSource)=>{
var _headers = []
for(var i=0;i<column.length;i++){
_headers.push({k:column[i].dataIndex,v:column[i].title})
}
for(var j=0;j<dataSource.length;j++){
dataSource[j].index=j+1
}
exportExcel(_headers, dataSource);
}
render() {
const props = {
name: 'file',
action: config.uploadUrl,
headers: {
authorization: 'authorization-text',
},
accept:'.xlsx',
showUploadList: false,
onChange: (info) => {
if (info.file.status !== 'uploading') {
}
if (info.file.status === 'done') {
message.success(`${info.file.name} 上传成功`);
let x = info.file.response;
this.getCachKey(x);
} else if (info.file.status === 'error') {
message.error(`${info.file.name} file upload failed.`);
}
},
};
const steps = [{
title: '上传Excel',
}, {
title: '验证数据',
}, {
title: '数据导入',
},
{
title: '导入完成',
}];
const { current } = this.state;
const {name, loading} = this.props
const column1=this.state.column?[{title:"序号",dataIndex:"index",fixed:"left",width:50, render:(v,r,i)=>i+1},...this.state.column]:[]
var column2=this.state.column?[...this.state.column]:[]
if(column1.length>1) column1[1].render=(val)=><span style={{color:"red"}}>{val}</span>
column2.splice(0,1)
column2=[{title:"序号",fixed:"left",width:50, render:(v,r,i)=>i+1},...column2]
return (
<span>
<ButtonDiy name={name||'批量导入'}
type='default'
className='defaultBlue'
handleClick={this.showModal}/>
<Modal
visible={this.state.visible}
onOk={this.handleOk}
maskClosable={false}
destroyOnClose
onCancel={this.handleCancel}
title={null}
footer={null}
width={"80%"}
>
<div className={styles.nomal}>
<p className={styles.import}>
EXCEL导入向导
</p>
<div style={{ margin: 'auto 23px' }}>
<Steps current={current}>
{steps.map(item =>
<Step key={item.title}
title={item.title}/>)}
</Steps>
<div className="steps-content">
{steps[this.state.current].content}
</div>
<div className={styles.button}>
{
(this.state.current < steps.length - 1 && this.state.current !== 0)
&&
<ButtonDiy name={this.state.current==3?"确认导入":"下一步"} type="primary" disabled={this.state.current!=3 && this.state.isNextDisabled} className='primaryBlue' handleClick={() => this.next()}/>
}
{
this.state.current > 0
&&
<ButtonDiy style={{ marginLeft: 8 }} name="上一步" className='defaultBlue' handleClick={() => this.prev()}/>
}
</div>
</div>
<div className={styles.tip}>
<p className={styles.tipContent}>
<span>欢迎使用EXCEL导入向导,首先请您上传需要导入的EXCEL文件。</span>
<span>点击“选择文件”选择您要导入的EXCEL文件,点击“开始上传”将其上传到服务器上,点击“清空队列”清空当前上传文件队列。</span>
</p>
</div>
{
this.state.isShow ?
<div className={styles.buttonDown}>
<Upload {...props}>
<Button>
<Icon type="upload"/>点击上传
</Button>
</Upload>
<Button href={this.state.exportTemplateUrl }
target="_blank"
type="danger">
下载模板
</Button>
</div> :
<Upload {...props}>
<Button>
<Icon type="upload"/>
重新上传
</Button>
</Upload>
}
{
this.state.isShow ? <div className={styles.attentionItem}>
<p>导入事项</p>
<p>1. 导入操作一次只能上传 1 EXCEL文件。</p>
<p>2. 导入文件最大文件大小上传 1 GB</p>
<p>3. 只能上传EXCEL文件(XLS, XLSX) 默认支持EXCEL 2003EXCEL 2007</p>
<p>4. 请将EXCEL文件的所有单元格格式设置为“文本”格式</p>
</div> :
<div className={styles.error} style={{marginTop:20}}>
<Tabs activeKey={this.state.currentKey} key={this.state.ch} onChange={this.changePane} type="card">
{this.state.errData&&this.state.errData.length==0?"":<TabPane tab={<span style={{color:"red"}}>验证错误列表</span>} key="1">
<Button style={{marginTop:5,marginBottom:5}} type="danger" onClick={this.exportError.bind(this,column1,this.state.errData)}>导出错误信息</Button>
<Table columns={column1} size="small"
style={{overflow: 'auto'}}
dataSource={this.state.errData}
bordered={true}/></TabPane>}
<TabPane tab={<span style={{color:"green"}}>验证成功列表</span>} key="2">
<Button style={{marginTop:5,marginBottom:5}} type="primary" onClick={this.exportError.bind(this,column2,this.state.sucData)}>导出正确信息</Button>
<Table columns={column2} size="small"
style={{overflow: 'auto'}}
dataSource={this.state.sucData}
bordered={true}/></TabPane>
</Tabs>
</div>
}
</div>
</Modal>
</span>
);
}
}
.nomal{
background: #fff;
padding: 10px;
}
.title{
display: flex;
margin-bottom: 20px;
}
.info{
text-align: center;
font-weight: bold;
font-size: 18px;
}
.detail{
text-align: center;
margin:30px auto;
}
.detail img{
margin: auto 10px;
}
.button{
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: -moz-flex;
display: flex;
-moz-box-pack: center; /*Firefox*/
-webkit-box-pack: center; /*Safari,Opera,Chrome*/
box-pack: center;
-moz-justify-content: center;
-webkit-justify-content: center;
justify-content: center;
}
.operation{
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: -moz-flex;
display: flex;
-moz-box-pack: center; /*Firefox*/
-webkit-box-pack: center; /*Safari,Opera,Chrome*/
box-pack: center;
-moz-justify-content: center;
-webkit-justify-content: center;
justify-content: center;
}
.button Button{
margin: auto 10px;
}
.titleInfo p span{
font-weight: bold;
}
.import{
color: #6ca3c9;
font-size: 16px;
}
.button{
// background: #eff3f8;
text-align: center;
padding:20px;
margin-top: 20px;
}
.tip{
margin:20px auto;
padding:10px;
border-top: 1px solid #ccc;
}
.tip span{
display: block;
margin:10px;
font-size: 16px;
}
.tip::after{
content: '';
position: absolute;
width: 5px;
height: 57px;
background: #e5eaf1;
margin-top: -141px;
margin-left: -13px;
}
.select button{
color: #fff;
padding:10px;
background: #abbac3;
border: none;
margin: 10px;
}
.attentionItem{
background: #f4f5f4;
padding: 10px;
box-shadow: 1px 1px 1px #ccc;
}
.attentionItem p:nth-child(1){
font-size: 16px;
margin-left: 0;
}
.attentionItem p{
font-size: 14px;
margin-left: 45px;
}
.submitButtons{
margin-left: 34px;
}
.contentTable{
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: -moz-flex;
display: flex;
-moz-box-pack: justify; /*Firefox*/
-webkit-box-pack:justify; /*Safari,Opera,Chrome*/
box-pack: justify;
-moz-justify-content: space-between;
-webkit-justify-content: space-between;
justify-content: space-between;
margin-top: 20px;
}
.left{
width: 50%;
}
.right{
width: 50%;
border-left: 1px solid #317ecc;
}
.error p{
color: #fff;
background: #317ecc;
// margin: 10px auto;
text-align: left;
font-size: 18px;
}
.download{
background: #f5f5f5;
padding: 5px;
margin-top: -16px;
}
.download img{
margin-top: -2px;
margin-right: 5px;
}
.download button{
border: none;
background: #f5f5f5
}
.download button:nth-child(1){
border-right: 1px solid #ccc;
}
.download button:nth-child(2){
border-right: 1px solid #ccc;
}
.buttonDown{
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: -moz-flex;
display: flex;
-moz-box-pack: start; /*Firefox*/
-webkit-box-pack: start; /*Safari,Opera,Chrome*/
box-pack: start;
-moz-justify-content: flex-start;
-webkit-justify-content: flex-start;
justify-content: flex-start;
margin-bottom: 20px;
}
.buttonDown>button{
margin-left: 10px;
background: #abbac3;
border: none;
color: #fff;
padding: 5px 12px;
border-radius: 5px;
}
\ No newline at end of file
import React, { Fragment } from 'react';
import { Divider, message, Modal, Popconfirm } from 'antd';
import moment from 'moment';
import router from 'umi/router';
import ExportInfo from '../Export/index';
import { text, number, date, getFormArrayConfig } from '../config/index';
import ButtonDiy from '@/baseComponent/ButtonDiy';
import Shell from '../Shell';
import FormArray from '../AffairPage/component/FormArray';
import Edit from '../Edit/index';
import ImportUtil from '../ImportUtil/ImportUtil';
import SearchDom from '@/highOrderComponent/SearchDom';
import StandardTable from '@/components/StandardTable';
import { getHead, fetchData, deleteItem, add } from './services';
const getValue = obj =>
Object.keys(obj)
.map(key => obj[key])
.join(',');
const CreateForm = props => {
const {
modalVisible,
handleAdd,
formData,
isAdd,
handleModalVisible,
formItem,
changeFormData,
} = props;
// 通过回调
const okHandle = () => {
handleAdd({}, isAdd);
};
// 需要获取动态表单
return (
<Modal
width="1000px"
maskClosable={false}
destroyOnClose
title={isAdd ? '新增' : '编辑'}
visible={modalVisible}
onOk={okHandle}
onCancel={() => handleModalVisible()}
>
<FormArray
config={getFormArrayConfig(formItem)}
value={formData}
fileSpan={{ big: 2, small: 2 }}
changeValue={changeFormData}
/>
<div style={{ clear: 'both' }} />
</Modal>
);
};
class FormList extends React.Component {
constructor(props) {
super(props);
this.state = {
modalVisible: false,
formData: null,
formItem: [],
searchConfig: [],
formValues: {},
isAdd: false,
selectedRows: [],
primaryKey: null,
showEdit: false,
pageData: {
list: [],
pagination: {},
},
};
this.columns = [];
}
// 渲染值
componentDidMount() {
const { objId } = this.props;
getHead({ dataObjId: objId }, datas => {
if (!datas) return;
this.setState({ formItem: datas });
let i = 0;
for (let t in datas) {
if (i < 10) {
let column = {};
column.title = datas[t].title;
column.dataIndex = datas[t].name;
if (date.includes(datas[t].type)) {
column.render = val => val && moment(val).format('YYYY-MM-DD HH:mm:ss');
}
this.columns.push(column);
i++;
}
if (datas[t].isPrimaryKey) {
this.setState({
primaryKey: datas[t].name,
});
}
}
let searchConfig = [];
for (let item of datas) {
if (item.isShowQuery) {
let sear = getFormArrayConfig([item]);
if (!Array.isArray(sear)) {
return false;
}
delete sear[0].required;
delete sear[0].placeHolder;
searchConfig.push(sear[0]);
}
}
this.setState({
searchConfig,
});
let opt = {
title: '操作',
render: (text, record) => (
<Fragment>
<div>
<a onClick={this.modify.bind(this, record)}>编辑</a>
<Divider type="vertical" />
<Popconfirm
title="确定删除该数据?"
onConfirm={this.delete.bind(this, record)}
okText="确定"
cancelText="取消"
>
<a>删除</a>
</Popconfirm>
</div>
</Fragment>
),
};
this.columns.push(opt);
this.getPage();
});
}
modify = record => {
const { formItem } = this.state;
if (formItem.length < 10) {
this.setState({
formData: { ...record },
modalVisible: true,
isAdd: false,
});
} else {
this.setState({
formData: { ...record },
showEdit: true,
});
}
};
delete = record => {
const { objId } = this.props;
// 找出主键
const { primaryKey } = this.state;
const Keys = {};
Keys[primaryKey] = record[primaryKey];
deleteItem({ keys: JSON.stringify(Keys), objId }, () => {
this.getPage();
});
};
changeFormData = (value, key) => {
this.setState(({ formData }) => ({ formData: { ...formData, [key]: value } }));
};
getPage = (params, values) => {
const { objId } = this.props;
const { formValues, pageData: pagination } = this.state;
if (params == null) {
params = {
pageNo: pagination.current ? pagination.current : 1,
pageSize: pagination.pageSize ? pagination.pageSize : 10,
...values,
};
}
params = {
...params,
...formValues,
};
fetchData({ ...params, dataObjId: objId }, res => {
if (!res.rows) {
console.log('分页接口rows返回null报错');
}
this.setState({
pageData: {
list: res.rows,
pagination: {
current: res.pageNo,
pageSize: res.pageSize,
total: Number(res.total),
},
},
});
});
};
handleStandardTableChange = (pagination, filtersArg, sorter) => {
const filters = Object.keys(filtersArg).reduce((obj, key) => {
const newObj = { ...obj };
newObj[key] = getValue(filtersArg[key]);
return newObj;
}, {});
const params = {
pageNo: pagination.current,
pageSize: pagination.pageSize,
...filters,
};
if (sorter.field) {
params.sorter = `${sorter.field}_${sorter.order}`;
}
this.getPage(params);
};
handleAdd = (fields, isAdd) => {
const { formData } = this.state;
const { objId } = this.props;
add({ params: formData, objId, isAdd }, () => {
message.success('操作成功');
this.setState({
modalVisible: false,
});
this.getPage();
});
};
handleModalVisible = () => {
this.setState({
modalVisible: this.state.modalVisible ? false : true,
formData: {},
});
};
add = () => {
const { formItem } = this.state;
if (formItem.length < 10) {
this.setState({
modalVisible: true,
formData: {},
isAdd: true,
});
} else {
this.setState({
formData: {},
showEdit: true,
isAdd: true,
});
}
};
handleSelectRows = rows => {
this.setState({
selectedRows: rows,
});
};
batchDelete = e => {
const { selectedRows, formItem, objId } = this.state;
if (!selectedRows) return;
const Keys = formItem.filter(i => i.isPrimaryKey).reduce((acc, i) => {
return { ...acc, [i.name]: selectedRows.map(row => row[i.name]).join(',') };
});
deleteItem({ keys: JSON.stringify(Keys), objId }, () => {
this.setState({
selectedRows: [],
});
this.getPage();
});
};
goBack = () => {
router.goBack();
};
formStateChange = (value, key) => {
this.setState(({ formValues }) => ({ formValues: { ...formValues, [key]: value } }));
};
resetFormValues = () => {
this.setState({
formValues: {},
});
};
render() {
const {
modalVisible,
selectedRows,
formItem,
isAdd,
objId,
pageData,
showEdit,
formData,
primaryKey,
formValues,
searchConfig,
} = this.state;
const parentMethods = {
handleAdd: this.handleAdd,
handleModalVisible: this.handleModalVisible,
formData,
formItem,
isAdd,
changeFormData: this.changeFormData,
};
return (
<>
{showEdit ? (
<Edit
id={objId}
recordId={formData[primaryKey]}
recordKey={primaryKey}
returnThis={() => {
this.setState({
showEdit: false,
});
this.getPage();
}}
/>
) : (
<Fragment>
{searchConfig.length > 0 ? (
<SearchDom
formStateChange={this.formStateChange}
formValues={formValues}
getPage={this.getPage}
resetFormValues={this.resetFormValues}
config={{ condition: searchConfig, fromTab: true }}
/>
) : null}
<Shell>
<div style={{ paddingLeft: '10px', marginTop: '20px' }}>
<ButtonDiy icon="plus" className="primaryBlue" handleClick={this.add} name="新建" />
<ImportUtil objId={objId} />
<span>&nbsp;&nbsp;</span>
<ExportInfo objId={objId} />
<span>&nbsp;&nbsp;</span>
{selectedRows.length > 0 && (
<ButtonDiy
handleClick={this.batchDelete}
name="批量删除"
className="primaryRed"
/>
)}
</div>
<StandardTable
rowKey="row_id"
data={pageData}
columns={this.columns}
selectedRows={selectedRows}
onSelectRow={this.handleSelectRows}
onChange={this.handleStandardTableChange}
/>
</Shell>
</Fragment>
)}
<CreateForm {...parentMethods} modalVisible={modalVisible} />
</>
);
}
}
export default FormList;
import { uaaRequest } from '@/webPublic/one_stop_public/utils/request';
export const getHead = (payload, callback) => {
uaaRequest('/DataColumnApi/getHeaderList', payload).then(res => {
if (!res) return;
if (callback) callback(res);
});
};
export const fetchData = (payload, callback) => {
uaaRequest('/DataObjApi/getFormDataPage', payload).then(res => {
if (!res) return;
if (callback) callback(res);
});
};
export const deleteItem = (payload, callback) => {
uaaRequest('/DataObjApi/deleteFormData', payload).then(res => {
if (callback) callback(res);
});
};
export const getDetail = (payload, callback) => {
uaaRequest('/DataObjApi/getFormData', payload).then(res => {
if (callback) callback(res);
});
};
export const add = (payload, callback) => {
uaaRequest('/DataObjApi/addFormData', {
data: JSON.stringify(payload.params),
isAdd: payload.isAdd,
objId: payload.objId,
}).then(res => {
if (callback) callback(res);
});
};
import React, { Component } from 'react';
import { Table } from 'antd';
import styles from './index.less';
import PropTypes from 'prop-types';
const giveNewColumns = (columns, tableId) => {
let scrollX = 0;
for (let item of columns) {
if (item != null) {
scrollX = typeof item.width !== 'undefined' ? scrollX + item.width : scrollX + 100;
}
}
const width = document.getElementById(tableId).offsetWidth;
if (width < scrollX) {
if(columns.length){
let lastItem = columns[columns.length -1];
if( (lastItem.title === '操作' || lastItem.title === '详情') &&
typeof lastItem.fixed === 'undefined' &&
typeof lastItem.noNeedFixed === 'undefined'){
columns[columns.length -1].fixed = 'right'; // 操作/ 详情列 增加 浮动
}
}
return {
scrollX,
columns,
}
}else{
return null;
}
};
export default class NormalTable extends Component {
constructor(props) {
super(props);
this.state = {
tableId: Math.random().toString(36).substr(2),
scrollX: 0,
columns: props.columns,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
if(JSON.stringify(nextProps.columns) === JSON.stringify(prevState.columns)){
return null
}else{
const columns = nextProps.columns;
let newState = giveNewColumns(columns, prevState.tableId);
if(newState){
return {
scrollX: newState.scrollX,
columns: newState.columns,
}
}else{
return {
columns,
}
}
}
}
/**
* <Table> dom 占得的宽度offsetWidth与计算所得的列宽scrollX
* 两者进行比较确定Table scroll的值
*/
componentDidMount() {
const {tableId,columns } = this.state;
let state = giveNewColumns(columns, tableId);
if(state){
this.setState({
scrollX: state.scrollX,
},()=>{
this.setState({
columns: state.columns,
})
})
}
}
render(){
const { dataSource, rowKey,
handleSelectRow, pagination, components,
loading,onChange, bordered,scroll,showHeader
} = this.props;
const { columns } = this.state;
/**
* 没有传rowSelection 传了handleSelectRow 时 使用 handleSelectRow 并封装rowSelection
* 传了rowSelection 直接使用
* */
const rowSelection = handleSelectRow === false ? null : {
columnWidth: 30,
fixed: true,
hideDefaultSelections: false,
onChange: (selectedRowKeys, selectedRows) => {
handleSelectRow(selectedRowKeys, selectedRows);
},
};
const { scrollX } = this.state;
if(pagination && pagination.total){
pagination.showTotal=(total, range) => `共${total}条  `;
}
return (
<Table dataSource={dataSource}
showHeader={showHeader}
columns={columns}
components={components}
rowKey={rowKey || 'key'}
loading={loading}
bordered={bordered}
id={this.state.tableId}
className={styles.NormalTable}
pagination={pagination ? pagination : false}
onChange={onChange}
scroll={ scrollX > 0 ? { x: scrollX } : scroll}
rowSelection={ this.props.rowSelection !== 'undefined' ? this.props.rowSelection : rowSelection }
/>
);
}
}
NormalTable.propTypes = {
dataSource: PropTypes.array.isRequired, // 表格数据源 To Antd Table
bordered: PropTypes.bool, // 是否显示border,
columns: PropTypes.array.isRequired, // 字段 To Antd Table
rowKey: PropTypes.string, // rowKey To Antd Table
handleSelectRow: PropTypes.oneOfType([
PropTypes.func,
PropTypes.bool,
]), // 行选择的事件,传false 表示不开放行选择 To Antd Table
pagination: PropTypes.oneOfType([ // 多种类型的数据
PropTypes.object,
PropTypes.bool,
]),
components: PropTypes.object, // 默认覆盖的 Table元素 基本没用
loading: PropTypes.bool,
onChange: PropTypes.func, // 分页、排序、筛选变化时触发
};
NormalTable.defaultProps = {
rowKey: 'id',
handleSelectRow: (selectedRowKeys, selectedRows) => {
//console.log(selectedRowKeys, selectedRows);
}, // false,
pagination: {
defaultCurrent: 1,
total: 20,
pageSize: 5,
showQuickJumper: true,
onChange: (current, size) => {
//console.log(current, size);
},
},
loading: false,
bordered: false,
components: undefined,
onChange: () => {
//console.log('NormalTable.onChange');
},
dataSource: [],
columns:
[
{
dataIndex: 'id',
title: 'id',
},
{
dataIndex: 'name',
title: '名称',
},
{
dataIndex: 'code',
title: '编码',
width: 200,
},
{
dataIndex: 'level',
title: '优先级',
},
{
dataIndex: 'desc',
title: '描述',
},
{
dataIndex: 'name1',
title: '名称',
},
{
dataIndex: 'code1',
title: '编码',
width: 100,
},
{
dataIndex: 'level1',
title: '优先级',
},
{
dataIndex: 'desc1',
title: '描述',
},
{
dataIndex: 'name2',
title: '名称',
},
{
dataIndex: 'code2',
title: '编码',
},
{
dataIndex: 'level2',
title: '优先级',
},
{
dataIndex: 'desc2',
title: '描述',
},
{
dataIndex: 'name3',
title: '名称',
},
{
dataIndex: 'code3',
title: '编码',
},
{
dataIndex: 'level3',
title: '优先级',
},
{
dataIndex: 'desc3',
title: '描述',
},
{
dataIndex: 'name4',
title: '名称',
},
{
dataIndex: 'code4',
title: '编码',
},
{
dataIndex: 'level4',
title: '优先级',
},
{
dataIndex: 'desc4',
title: '描述',
},
{
dataIndex: 'operation',
title: '操作',
fixed: 'right',
width: 120,
render: (text, record) => {
return <span><a>编辑 </a>|<a> 删除</a></span>;
},
},
],
};
.FormArray {
padding: 18px 12px 0 12px;
:global {
.ant-form-item {
margin-bottom: 12px;
}
}
.textDecoration {
:global {
.ant-input-number-input {
text-decoration: line-through;
}
}
}
.colDom {
:global {
}
}
}
.spd {
padding: 0;
:global {
.ant-form-item {
margin-bottom: 6px;
}
.ant-tag, .ant-tag a, .ant-tag a:hover {
color: #84d945;
}
}
}
.FieldList {
@height: 30px;
padding-right: 10px;
padding-left: 10px;
.colOut {
padding: 10px;
.group {
border: 1px solid #eee;
height: 30px;
}
.name {
background-color: #eee;
text-align: center;
font-size: 14px;
color: #3a3a3a;
height: 100%;
line-height: @height;
}
.discrib {
padding-left: 5px;
font-size: 12px;
letter-spacing: .1px;
color: #3a3a3a;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 100%;
line-height: @height;
}
}
}
.FieldListWithoutBg {
padding-top: 15px;
padding-right: 10px;
padding-left: 10px;
@height: 15px;
.withoutBgcolOut {
padding: 10px;
.withoutBgGroup {
height: @height;
}
.withoutBgName {
font-size: 14px;
color: #666;
height: 100%;
line-height: @height;
div {
text-align: right;
}
div:after {
content: " ";
display: inline-block;
width: 100%;
}
}
.withoutBgDiscrib {
padding-left: 12px;
font-size: 14px;
letter-spacing: .1px;
color: #555;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
height: 100%;
line-height: @height;
}
}
}
.shell {
margin-top: 20px;
.row {
background-color: rgba(255, 255, 255, 1);;
}
}
.blockTitle {
border-bottom: 1px solid #ccc;
height: 48px;
display: flex;
align-items: center;
padding: 0 40px;
font-size: 18px;
color: #333;
font-weight: bold;
cursor: default;
position: relative;
&.isSmall {
font-size: 14px;
height: 36px;
padding: 0 30px;
border-bottom: 1px solid #eee;
}
}
.CardDiy {
:global {
.ant-card-head {
min-height: 40px;
height: 40px;
font-size: 14px;
padding: 0;
// padding: 13px 0px 12px 14px;
color: rgba(51, 51, 51, 1);
}
.ant-card-head-wrapper {
display: flex;
line-height: 40px;
height: 40px;
padding-left: 12px;
align-items: center;
}
.ant-card-extra {
padding-right: 12px;
}
.ant-card-body {
padding: 0;
span {
height: 40px;
p {
padding-left: 24px;
border-bottom: 1px solid #e8e8e8;
line-height: 40px;
margin-bottom: 0;
}
}
}
}
.handMouse {
cursor: pointer;
}
}
.NormalTable {
@TableThemeColor: #5e9ede;
@TableThemeBgColor: #e6f7ff;
padding: 6px 12px 0 12px;
:global {
.ant-table-thead > tr > th {
padding: 0 12px;
height: 50px;
color: rgba(0, 0, 0, .65);
background-color: #e9f2fb;
}
.ant-table-content {
// min-height: 500px;
}
p {
margin-bottom: 0 !important;
}
a {
color: @TableThemeColor;
}
.ant-table-thead > tr > th, .ant-table-tbody > tr > td {
padding: 10px 16px;
}
.ant-pagination-item-active, .ant-pagination-item:focus, .ant-pagination-item:hover {
border-color: @TableThemeColor;
}
.ant-pagination-options-quick-jumper input:focus {
border-color: @TableThemeColor;
box-shadow: 0 0 0 2px @TableThemeBgColor;
}
.ant-pagination-options-quick-jumper input:hover {
border-color: @TableThemeColor;
}
.ant-pagination-item:focus a, .ant-pagination-item:hover a {
color: @TableThemeColor;
}
.ant-pagination-item-active:focus a, .ant-pagination-item-active:hover a {
color: @TableThemeColor;
}
.ant-checkbox-checked .ant-checkbox-inner {
background-color: @TableThemeColor;
border-color: @TableThemeColor;
}
.ant-checkbox-wrapper:hover .ant-checkbox-inner, .ant-checkbox:hover .ant-checkbox-inner, .ant-checkbox-input:focus + .ant-checkbox-inner {
border-color: @TableThemeColor;
}
::selection {
background: @TableThemeColor;
}
.ant-checkbox-indeterminate .ant-checkbox-inner:after {
background: @TableThemeColor;
}
tbody > tr.ant-table-row-hover:not(.ant-table-expanded-row) > td, .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td {
background: @TableThemeBgColor;
}
.ant-pagination {
width: 100%;
text-align: center;
padding-top: 20px;
}
}
}
.ButtonDiy {
@blue: rgba(25, 152, 240, 1);
@white: rgba(255, 255, 255, 1);
@red: #F14B5A;
padding-right: 12px;
button {
height: 30px;
}
.primaryBlue {
font-size: 14px;
font-weight: 400;
color: @white;
height: 30px;
background: @blue;
border-radius: 2px;
border-color: @blue;
&:hover, &:active, &:focus {
background: @blue;
color: @white;
border-color: @white;
}
&:disabled {
color: rgba(0, 0, 0, 0.25);
background-color: #f5f5f5;
border-color: #d9d9d9;
}
}
.primaryRed {
font-size: 14px;
font-weight: 400;
color: @white;
height: 30px;
background: @red;
border-radius: 2px;
border-color: @red;
&:hover, &:active, &:focus {
background: @red;
color: @white;
border-color: @white;
}
}
.defaultBlue {
font-size: 14px;
font-weight: 400;
color: @blue;
height: 30px;
background: @white;
border-radius: 2px;
border-color: @blue;
&:hover, &:active, &:focus {
background: @white;
color: @blue;
border-color: @blue;
}
}
.defaultRed {
font-size: 14px;
font-weight: 400;
color: @red;
height: 30px;
background: @white;
border-radius: 2px;
border-color: @red;
&:hover, &:active, &:focus {
background: @white;
color: @red;
border-color: @red;
}
}
}
.collegeTitle {
color: #333;
font-size: 18px;
text-align: center;
padding-bottom: 74px;
font-weight: 600;
}
.collegeStyle {
// width: 100%;
:global {
.ant-col-2 {
width: 10%;
text-align: center
}
}
}
.colStyle {
color: #4992DF
}
.colStyle:hover {
background: green
}
.picName {
padding-left: 57px;
padding-top: 10px;
}
.modalDiy {
:global {
.ant-modal-title {
text-align: center;
font-size: 16px;
font-family: MicrosoftYaHei-Bold;
font-weight: bold;
color: rgba(51, 51, 51, 1);
}
}
}
/*:global{
.cls-2{
cursor: pointer !important;
}
}*/
.searchChangeMaintain {
margin-bottom: 0;
padding-top: 15px;
:global {
.ant-form-item-control {
line-height: 20px;
}
}
}
.exportModal {
:global {
.ant-modal-body {
padding: 12px;
}
.ant-form-item {
margin-bottom: 0;
}
.ant-form-item-label {
text-align: left;
}
}
}
.DescriptionContext {
width: 98%;
overflow-y: auto;
overflow-x: hidden;
word-break: break-word;
height: 500px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 14px;
color: black;
background-color: white;
}
.Editable {
box-sizing: border-box;
margin: 0;
list-style: none;
position: relative;
display: inline-block;
padding: 4px 11px;
width: 100%;
font-size: 14px;
line-height: 1.5;
color: rgba(0, 0, 0, 0.65);
background-color: #fff;
background-image: none;
border: 1px solid #d9d9d9;
border-radius: 4px;
transition: all .3s;
&:hover {
border-color: #29a6ff;
border-right-width: 1px !important;
}
}
.editorLayout {
line-height: normal;
:global {
.ql-container {
height: 400px;
}
}
}
.editorLayoutMin {
line-height: normal;
:global {
.ql-container {
height: 200px;
}
}
}
// 新闻列表
.horizonWrap {
margin-top: 20px;
.item {
margin-bottom: 20px;
cursor: pointer;
.itemInner {
transition: all .3s linear;
background-color: #fff;
height: 110px;
padding: 20px;
overflow: hidden;
display: flex;
&:hover {
box-shadow: 0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 20px 4px rgba(0, 0, 0, 0.12) !important;
}
.left {
flex: 0 0 70px;
height: 70px;
background-color: rgb(132, 192, 240);
position: relative;
font-size: 26px;
color: #fff;
font-weight: 600;
span {
display: inline-block;
position: absolute;
top: 0px;
left: 5px;
&:last-child {
top: auto;
right: 5px;
bottom: 0;
left: auto;
}
}
&::before {
content: '';
width: 70px;
height: 1px;
background-color: #fff;
transform: rotateZ(-45deg);
display: block;
position: absolute;
top: 34px;
left: 0px;
}
}
.right {
padding-left: 20px;
flex: 1;
overflow: hidden;
.title {
font-weight: 600;
color: #333;
font-size: 22px;
line-height: 1;
margin-bottom: 10px;
}
.content {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
font-size: 14px;
line-height: 20px;
/* autoprefixer: off*/
-webkit-box-orient: vertical;
/* autoprefixer: on*/
}
}
}
}
}
.PieChart {
:global {
.pie-stat {
padding-top: 10px;
}
}
}
.ListTab {
:global {
.ant-tabs-bar {
margin-bottom: 0px;
}
}
}
.customMultiple {
.multipleBox {
width: 100%;
height: 150px;
border: 1px solid rgba(210, 210, 210, 1);
border-radius: 6px;
overflow: auto;
background: white;
.multipleItem {
padding: 5px 10px;
cursor: pointer;
line-height: 1.5;
&:hover {
transition: all .3s linear;
background: #E9F2FB;
}
&.active {
background: #008DFF;
color: white;
}
}
}
.operationBtnBox {
display: flex;
flex-direction: column;
justify-content: center;
> span {
margin-bottom: 10px;
line-height: 1;
&:last-child {
margin-bottom: 0;
}
}
}
}
.specForm {
:global {
.ant-radio-wrapper {
margin-right: 0;
}
}
}
/**
* 钟是志
* 2019年1月10日
* 一个方块就是一个Shell用于组件外层
*/
import React, { Component } from 'react';
import { Row, Col} from 'antd';
import styles from '../NormalTable/index.less';
export default class Index extends Component {
render(){
const {children,styleShell = {} } = this.props;
return (
<div className={styles.shell}
style={styleShell}
>
<Row className={styles.row}>
{children}
</Row>
</div>
);
}
}
import React, { Component, Fragment } from 'react';
import NormalTable from '../NormalTable';
import Index from '../Shell';
function initTotalList(columns) {
const totalList = [];
columns.forEach(column => {
if (column.needTotal) {
totalList.push({ ...column, total: 0 });
}
});
return totalList;
}
class StandardTable extends Component {
constructor(props) {
super(props);
const { columns } = props;
const needTotalList = initTotalList(columns);
this.state = {
selectedRowKeys: [],
needTotalList,
};
}
static getDerivedStateFromProps(nextProps) {
// clean state
if (nextProps.selectedRows && nextProps.selectedRows.length === 0) {
const needTotalList = initTotalList(nextProps.columns);
return {
selectedRowKeys: [],
needTotalList,
};
}
return null;
}
handleRowSelectChange = (selectedRowKeys, selectedRows) => {
let { needTotalList } = this.state;
needTotalList = needTotalList.map(item => ({
...item,
total: selectedRows.reduce((sum, val) => sum + parseFloat(val[item.dataIndex], 10), 0),
}));
const { onSelectRow } = this.props;
if (onSelectRow) {
onSelectRow(selectedRows, selectedRowKeys);
}
this.setState({ selectedRowKeys, needTotalList });
};
handleTableChange = (pagination, filters, sorter) => {
const { onChange } = this.props;
if (onChange) {
onChange(pagination, filters, sorter);
}
};
cleanSelectedKeys = () => {
this.handleRowSelectChange([], []);
};
render() {
const { selectedRowKeys, needTotalList } = this.state;
const {
data: { list, pagination },
loading,
columns,
rowKey,
components,
scroll,
noSelectRow,
bordered,
showHeader,
} = this.props;
const paginationProps = {
showSizeChanger: true,
showQuickJumper: true,
...pagination,
};
const rowSelection = {
selectedRowKeys,
onChange: this.handleRowSelectChange,
type: this.props.selectType || 'checkbox ',
getCheckboxProps: record => ({
disabled: record.disabled,
}),
};
return (
<div>
<Index>
{!noSelectRow ?
<span style={{ paddingLeft: '12px', paddingTop: '8px' }}>
已选择{selectedRowKeys.length}
{needTotalList.map(item => (
<span style={{ marginLeft: 8 }} key={item.dataIndex}>
{item.title}
总计&nbsp;
<span style={{ fontWeight: 600 }}>
{item.render ? item.render(item.total) : item.total}
</span>
</span>
))}
<a onClick={this.cleanSelectedKeys} style={{ marginLeft: 24 }}>
清空
</a>
</span>
: <div style={{ height: '1px' }}></div>}
</Index>
<NormalTable components={components}
loading={loading}
rowKey={rowKey || 'key'}
rowSelection={typeof noSelectRow !== 'undefined' && noSelectRow ? null : rowSelection}
dataSource={list}
bordered={bordered}
columns={columns}
size="small"
scroll={scroll}
showHeader={showHeader}
pagination={pagination === null ? null : paginationProps}
onChange={this.handleTableChange}
/>
</div>
);
}
}
export default StandardTable;
@import '~antd/lib/style/themes/default.less';
.standardTable {
:global {
.ant-table-pagination {
margin-top: 24px;
}
}
.tableAlert {
margin-bottom: 16px;
}
}
/**
* 徐立
* 2019年9月2日
* 用于封装轻提示
*/
import { Toast } from 'antd-mobile';
/**
*
* Toast.success(content, duration, onClose, mask)
* content 提示内容
* duration 自动关闭的延时,单位秒
* onClose 关闭后回调
* mask 是否显示透明蒙层,防止触摸穿透
*/
/**
* 不带icon图标提示
*/
export function showToast(value, time = 1, fn = () => {}, mask = true) {
Toast.info(value, time, fn, mask);
}
/**
* 不带蒙尘提示
*/
export function showToastNoMask(value, time = 1, fn = () => {}, mask = false) {
Toast.info(value, time, fn, mask);
}
/**
* 成功提示
*/
export function successToast(value, time = 1, fn = () => {}, mask = true) {
Toast.success(value, time, fn, mask);
}
/***
* 失败提示
*/
export function failToast(value, time = 1, fn = () => {}, mask = true) {
Toast.fail(value, time, fn, mask);
}
/***
* 错误提示
*/
export function offline(value, time = 1, fn = () => {}, mask = true) {
Toast.offline(value, time, fn, mask);
}
/***
* 带进度提示信息的提示
* duration = 0 时,onClose 无效,toast 不会消失;隐藏 toast 需要手动调用 hide
* Toast.hide()
*/
export function loadingToast(value, time = 1, fn = () => {}, mask = true) {
Toast.loading(value, time, fn, mask);
}
import * as service from '../AffairPage/publicApiService';
import moment from 'moment';
import { isJSON } from '@/baseComponent/utils';
import { getDefaultValues } from '../AffairPage/destruction';
import { message } from 'antd';
const text = [
'BINARY',
'BIT',
'BLOB',
'CHAR',
'GEOMETRY',
'GEOMETRYCOLLECTION',
'JSON',
'LINESTRING',
'LONGBLOB',
'LONGTEXT',
'MEDIUMBLOB',
'MEDIUMINT',
'MEDIUMTEXT',
'MULTILINESTRING',
'MULTIPOINT',
'MULTIPOLYGON',
'POINT',
'POLYGON',
'REAL',
'DECIMAL',
'ENUM',
'SET',
'TEXT',
'TINYBLOB',
'TIBYTEXT',
'VARBINARY',
'VARCHAR',
];
const number = ['BIGINT', 'DOUBLE', 'FLOAT', 'INT', 'INTEGER', 'NUMERIC', 'SMALLINT', 'TINYINT'];
const date = ['DATE', 'DATETIME', 'TIME', 'TIMESTAMP', 'YEAR'];
const format = {
//欢哥那边定义好的 时间格式类型
DATE: 'YYYY-MM-DD HH:mm',
DATETIME: 'YYYY-MM-DD HH:mm:ss',
TIME: 'HH:mm:ss',
TIMESTAMP: 'HH:mm:ss',
YEAR: 'YYYY',
};
/**
* 将时间格式转化为unix时间戳
* */
const transLateTimeTOUnix = (value, dataType) => {
if (date.indexOf(dataType) > -1 && value) {
return moment(value).format('x');
} else {
return value;
}
};
const getFormArrayConfig = header => {
let config = [];
for (let item of header) {
if (item.isPrimaryKey) {
// 主键
continue;
/* config.push(
{
key: item.name,
name: item.title,
type: 'input',
placeHolder: `请输入${item.name}`,
required: !item.isNull,
}
);*/
} else if (text.indexOf(item.type) > -1) {
config.push({
key: item.name,
name: item.title,
type: 'input',
placeHolder: `请输入${item.name}`,
required: !item.isNull,
});
} else if (number.indexOf(item.type) > -1) {
config.push({
key: item.name,
name: item.title,
type: 'inputNumber',
placeHolder: `请输入${item.name}`,
required: !item.isNull,
min: 0,
});
} else if (date.indexOf(item.type) > -1) {
config.push({
key: item.name,
name: item.title,
type: 'datePicker',
placeHolder: `请输入${item.name}`,
required: !item.isNull,
format: format[item.type],
});
} else {
config.push({
key: item.name,
name: item.title,
type: 'input',
placeHolder: `请输入${item.name}`,
required: !item.isNull,
});
}
}
return config;
};
const transLate = {
TextArea: 'textarea',
Radio: 'radioGroup',
Label: 'text',
Checkbox: 'checkBoxMutiple',
Select: 'select',
Switch: 'switch',
DatePicker: 'datePicker',
RangePicker: 'rangePicker',
UploadCom: 'buttonUpload',
ImgUploadCom: 'upload',
Input: 'input',
TableSelect: 'tableSelect', // 表格选择
ChildForm: 'childForm', // 最终保存的数据还有问题
InputNumber: 'inputNumber',
PartForm: 'partForm', // 还未开发 相当于选了一个选项 表单字段变更
Echart: 'echart', // 不做
Description: 'input', // 'description', // 还未开发
Table: 'table', // 表格 未开发
};
const getOpts = async item => {
let options = [];
if (item.optionType === 'reference') {
options = await service.getOptions(
item.dataId,
item.filterSql,
item.referenceCodeName,
item.referenceNameName
);
} else if (item.optionType === 'sql') {
options = await service.getSqlOptions(item.dataId, item.sqlKey, item.valueName, item.labelName);
} else {
options = item.options;
}
return options;
};
const translateAddFields = async (data, tableInfo) => {
let key = [];
let res = [];
for (let item of data) {
if (key.indexOf(item.key) > -1) {
continue;
} else {
key.push(item.key);
}
item.type = transLate[item.comName] || 'input';
if (typeof item.key === 'undefined' || !item.key) {
item.key = item.c1;
}
switch (item.comName) {
case 'Input':
if (number.indexOf(item.dataType) > -1) {
item.type = 'inputNumber';
}
break;
case 'DatePicker':
item.format = item.format || format[item.dataType];
if (item.format.indexOf('HH') > -1) {
item.showTime = true;
}
break;
case 'RangePicker':
item.name = item.name || '起止时间';
item.endKey = item.c2;
item.format = item.format || format[item.dataType];
if (item.format.indexOf('HH') > -1) {
item.showTime = true;
}
break;
case 'ChildForm':
item.componentProps.thisFields = await translateAddFields(
item.componentProps.thisFields,
tableInfo
);
break;
case 'Radio':
item.options = await getOpts(item);
break;
case 'Select':
item.options = await getOpts(item);
break;
case 'Checkbox':
item.options = await getOpts(item);
item.options = item.options.map(x => {
return {
label: x.name,
value: x.key,
};
});
break;
case 'TableSelect':
let info = await service.handleSqlfind(item.componentProps.sqlKey);
if (isJSON(info.cols)) {
info.cols = JSON.parse(info.cols);
}
item.componentProps.columnsData = info;
item.componentProps.allValues = JSON.stringify(getDefaultValues(data, tableInfo));
break;
default:
break;
}
res.push(item);
}
return res;
};
const mustHaveValue = (configFields, data) => {
for (let item of configFields) {
if (item.required && !data[item.key] && data[item.key] !== false && data[item.key] !== 0) {
message.warning(`${item.name}是必填项请填写`);
return false;
}
if (item.required && typeof data[item.key] === 'object') {
if (data[item.key].selects && JSON.stringify(data[item.key].selects) === '{}') {
message.warning(`${item.name}是必填项请填写`);
return false;
}
}
}
return true;
};
export {
text,
number,
date,
getFormArrayConfig,
translateAddFields,
transLateTimeTOUnix,
format,
mustHaveValue,
};
@import '~antd/lib/style/themes/default.less';
@import './utils.less';
.clearfix{
width:110px;
height:90px;
}
.headBox{
position: absolute;
top:55px;
right: 100px;
}
.infoBox label{
width: 100px;
text-align: right
}
.pagBox{
position: relative;
width: 100%;
}
.infoBox{
position: relative;
width: 100%;
}
.boxTitle{
font-size: 18px;
border-bottom: 1px solid #F0F0F0;
color:#333;
padding-bottom:10px;
}
.tableList {
.tableListOperator {
margin-bottom: 16px;
button {
margin-right: 8px;
}
}
}
.tableListForm {
:global {
.ant-form-item {
margin-bottom: 24px;
margin-right: 0;
display: flex;
> .ant-form-item-label {
width: auto;
line-height: 32px;
padding-right: 8px;
}
.ant-form-item-control {
line-height: 32px;
}
}
.ant-form-item-control-wrapper {
flex: 1;
}
}
.submitButtons {
display: block;
white-space: nowrap;
margin-bottom: 24px;
}
}
@media screen and (max-width: @screen-lg) {
.tableListForm :global(.ant-form-item) {
margin-right: 24px;
}
}
@media screen and (max-width: @screen-md) {
.tableListForm :global(.ant-form-item) {
margin-right: 8px;
}
}
.textOverflow() {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
word-break: break-all;
}
.textOverflowMulti(@line: 3, @bg: #fff) {
position: relative;
max-height: @line * 1.5em;
margin-right: -1em;
padding-right: 1em;
overflow: hidden;
line-height: 1.5em;
text-align: justify;
&::before {
position: absolute;
right: 14px;
bottom: 0;
padding: 0 1px;
background: @bg;
content: '...';
}
&::after {
position: absolute;
right: 14px;
width: 1em;
height: 1em;
margin-top: 0.2em;
background: white;
content: '';
}
}
// mixins for clearfix
// ------------------------
.clearfix() {
zoom: 1;
&::before,
&::after {
display: table;
content: ' ';
}
&::after {
clear: both;
height: 0;
font-size: 0;
visibility: hidden;
}
}
import { apiRequest } from '../request';
const api="/DataObjApi";
export default {
namespace: 'DataObj',
state: {
list: [],
data:{
list: [],
pagination: {},
},
code:{
list: [],
pagination: {},
}
},
effects: {
*getExportInfo({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/getExportInfo" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*changeCatalogue({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/changeCatalogue" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*find({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/find" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*add({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/add" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},*fetch({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/getPage" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'page',
payload: {...response,isMain:payload.isMain},
});
},*remove({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/remove" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if(callback){
callback()
}
},*open({ payload, callback }, { call, put }) {
const response = yield call(apiRequest,api+"/open" ,payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if(callback){
callback()
}
},
*createTabel({payload,callback},{call,put}){
const response = yield call(apiRequest,api+"/createTable",payload);
if(!response){yield put({type: 'nom'});return }
yield put({
type: 'nom',
payload: response,
});
if(callback){
callback()
}
}
},
reducers: {
list(state, action) {
return {
...state,
list: action.payload,
};
},
page(state, { payload }) {
if(payload.isMain){
return {
...state,
data:{
list: payload.rows,
pagination: {
current:payload.pageNo,
pageSize:payload.pageSize,
total:payload.total,
},
}
};
}else{
return {
...state,
code:{
list: payload.rows,
pagination: {
current:payload.pageNo,
pageSize:payload.pageSize,
total:payload.total,
},
}
};
}
},
nom(state, action) {
return {...state };
},
},
};
import { uaaRequest } from '../../one_stop_public/utils/request';
const api = '/DataObjApi';
export default {
namespace: 'formList',
state: {
list: [],
data: {
list: [],
pagination: {},
},
},
effects: {
* clear({ payload, callback }, { call, put }) {
yield put({
type: 'clearAll',
payload: {},
});
},
* getHead({ payload, callback }, { call, put }) {
console.log('getHead',);
const response = yield call(uaaRequest, '/DataColumnApi/getHeaderList', payload);
console.log(' header response', response);
if (!response) {
yield put({ type: 'nom' });
return;
}
if (callback) callback(response);
},
* fetch({ payload, callback }, { call, put }) {
const response = yield call(uaaRequest, '/DataObjApi/getFormDataPage', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
/* yield put({
type: 'page',
payload: {
...response,
},
});*/
if (callback) callback(response);
},
* add({ payload, callback }, { call, put }) {
const response = yield call(apiRequest, api + '/addFormData',
{
data: JSON.stringify(payload.params),
isAdd: payload.isAdd,
objId: payload.objId,
});
if (!response) {
yield put({ type: 'nom' });
return;
}
if (callback) callback(response);
},
* delete({ payload, callback }, { call, put }) {
const response = yield call(apiRequest, api + '/deleteFormData', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
if (callback) callback(response);
},
* getDetail({ payload, callback }, { call, put }) {
const response = yield call(apiRequest, api + '/getFormData', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
if (callback) callback(response);
},
},
reducers: {
clearAll(state, action) {
return {
...state,
data: {
list: [],
pagination: {},
},
};
},
list(state, action) {
return {
...state,
list: action.payload,
};
},
page(state, { payload }) {
return {
...state,
data: {
list: payload.rows,
pagination: {
current: payload.pageNo,
pageSize: payload.pageSize,
total: Number(payload.total),
},
},
};
},
nom(state, action) {
return { ...state };
},
},
};
/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import {extend} from 'umi-request';
import {notification} from 'antd';
import FormdataWrapper from "@/utils/object-to-formdata-custom";
import { getHuanGeToken } from '@/utils/authority';
import { offline } from './Toast';
import systemConfig from '@/config/config';
const codeMessage = {
200: '服务器成功返回请求的数据。',
201: '新建或修改数据成功。',
202: '一个请求已经进入后台排队(异步任务)。',
204: '删除数据成功。',
400: '发出的请求有错误,服务器没有进行新建或修改数据的操作。',
401: '用户没有权限(令牌、用户名、密码错误)。',
403: '用户得到授权,但是访问是被禁止的。',
404: '发出的请求针对的是不存在的记录,服务器没有进行操作。',
406: '请求的格式不可得。',
410: '请求的资源被永久删除,且不会再得到的。',
422: '当创建一个对象时,发生一个验证错误。',
500: '服务器发生错误,请检查服务器。',
502: '网关错误。',
503: '服务不可用,服务器暂时过载或维护。',
504: '网关超时。',
};
/**
* 异常处理程序
*/
var canReportError =true;
const errorHandler = error => {
const {response} = error;
if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText;
notification.error({
message: `请求错误`,
description: errorText,
});
if (response.status === 401) {
// @HACK
/* eslint-disable no-underscore-dangle */
return window.g_app._store.dispatch({
type: 'login/loginout',
});
}
}else{
if(canReportError){
notification.error({
message: `网络故障`,
description: "请检查网络链接或联系管理员",
});
canReportError=false;
}
}
};
/**
* 配置request请求时的默认参数
*/
const umiRequest = extend({
errorHandler, // 默认错误处理
credentials: 'omit', // 默认请求是否带上cookie
mode: 'cors',
});
export const request = (url, data, options = {}) => {
const pp = {...data,token: getHuanGeToken()}
const requestParams = FormdataWrapper(pp)
// 由于自动添加前缀 这里暂时修改getUrl(url)
return umiRequest(url, {
data:requestParams,
method: "POST",
requestType: "form",
...options,
}).then(response => {
if(window.location.pathname.slice(0,15)==='/onestop/mobile'){
if(response.errCode||response.errMsg){
offline(response.errMsg,2)
if(data.callback) data.callback(response)
return
}
}
if (!response) return;
if(url.indexOf('UserApi/loginByCount') > -1){
if(response.errMsg === '用户不存在'){
console.error('在一站式服务大厅中无该用户');
return {token: ''};
}
}
if (response.errCode||response.errMsg) {
notification.error({
message: `请求错误`,
description: response.errMsg,
});
return;
}
if (response.errcode) {
notification.error({
message: `请求错误`,
description: response.errmsg,
});
return;
}
canReportError=true
return response;
})
};
const setRequestConfig = (config) => {
return (url, data, options = {}) => {
if (Array.isArray(url)) {
return Promise.all(url.map((ags) => {
return request(ags[0], ags[1], Object.assign({}, ags[2], config));
}))
}
return request(url, data, {...options, ...config})
}
};
const createServerRequest = (config = {}) => {
return setRequestConfig(config)
};
export const apiRequest = createServerRequest({
method: "POST",
prefix: systemConfig.sqlFormsServer || 'http://scjoyedu.eicp.net:18888/onestop/',
});
export default request;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论