mirror of
https://gitee.com/freshday/radar.git
synced 2026-03-22 04:37:16 +08:00
增加vip权限字段,限制构建模型,节省资源。
feihu wang
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>风控引擎管理平台</title> <link rel="shortcut icon" href="/images/anquan.png"> <!--[if lt IE 10]>
|
||||
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.5.7/es5-shim.min.js,es5-shim/4.5.7/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]--> <link href="./index.ab367878-1.css" rel="stylesheet"><link href="./index.ab367878-2.css" rel="stylesheet"><link href="./index.ab367878-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.ab367878.js"></script></body> </html>
|
||||
<![endif]--> <link href="./index.262169ad-1.css" rel="stylesheet"><link href="./index.262169ad-2.css" rel="stylesheet"><link href="./index.262169ad-3.css" rel="stylesheet"></head> <body> <div id="react-content"></div> <script type="text/javascript" src="./main.262169ad.js"></script></body> </html>
|
||||
File diff suppressed because one or more lines are too long
@@ -1,8 +0,0 @@
|
||||
{
|
||||
presets: ['@babel/env', '@babel/preset-react'],
|
||||
plugins: [
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
]
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
/build/
|
||||
/dist/
|
||||
/*.js
|
||||
/node_modules/
|
||||
/.vscode/
|
||||
@@ -1,8 +0,0 @@
|
||||
module.exports = {
|
||||
parser: 'babel-eslint',
|
||||
env: {
|
||||
browser: true,
|
||||
jest: true,
|
||||
node: true,
|
||||
}
|
||||
};
|
||||
16
webapp/.gitignore
vendored
16
webapp/.gitignore
vendored
@@ -1,16 +0,0 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
/dist/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
/sync.sh
|
||||
.idea
|
||||
.vscode
|
||||
.history
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
@@ -1,2 +0,0 @@
|
||||
sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
//项目前后端分离,此目录用于存放前端代码
|
||||
@@ -1,79 +0,0 @@
|
||||
{
|
||||
"name": "radar",
|
||||
"version": "5.0.0",
|
||||
"description": "",
|
||||
"main": "src/index.jsx",
|
||||
"scripts": {
|
||||
"start": "webpack-dev-server --inline --config webpack.config.dev.js --open",
|
||||
"build": "webpack --config webpack.config.prod.js --mode production"
|
||||
},
|
||||
"dependencies": {
|
||||
"antd": "^2.1.0",
|
||||
"babel-runtime": "^6.9.2",
|
||||
"console-polyfill": "^0.2.2",
|
||||
"echarts": "^3.2.3",
|
||||
"history": "^2.1.1",
|
||||
"moment": "^2.15.1",
|
||||
"react": "^15.0.0",
|
||||
"react-dom": "^15.0.0",
|
||||
"react-router": "^2.4.0",
|
||||
"whatwg-fetch": "^1.0.0",
|
||||
"animate.css": "^3.5.1",
|
||||
"fetch-ie8": "^1.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"copy-webpack-plugin": "2.x",
|
||||
"less": "2.7.3",
|
||||
"less-loader": "^4.1.0",
|
||||
"@babel/cli": "^7.2.3",
|
||||
"@babel/core": "^7.4.0",
|
||||
"@babel/plugin-proposal-class-properties": "^7.4.0",
|
||||
"@babel/plugin-proposal-decorators": "^7.4.0",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.2.0",
|
||||
"@babel/polyfill": "^7.4.0",
|
||||
"@babel/preset-env": "^7.4.1",
|
||||
"@babel/preset-react": "^7.0.0",
|
||||
"autoprefixer": "^8.6.5",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-jest": "^24.5.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"clean-webpack-plugin": "^0.1.19",
|
||||
"css-loader": "^0.28.11",
|
||||
"css-split-webpack-plugin": "^0.2.6",
|
||||
"es3ify-webpack-plugin": "0.0.1",
|
||||
"eslint": "^5.1.0",
|
||||
"eslint-friendly-formatter": "^4.0.1",
|
||||
"eslint-loader": "^2.0.0",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^3.0.1",
|
||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||
"fs-extra": "^7.0.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^24.5.0",
|
||||
"mini-css-extract-plugin": "^0.4.0",
|
||||
"moment": "2.22.2",
|
||||
"node-notifier": "^5.2.1",
|
||||
"node-sass": "^4.9.0",
|
||||
"optimize-css-assets-webpack-plugin": "^4.0.2",
|
||||
"ora": "^3.0.0",
|
||||
"portfinder": "^1.0.17",
|
||||
"postcss-flexbugs-fixes": "^3.3.1",
|
||||
"postcss-loader": "^2.1.6",
|
||||
"sass-loader": "^7.0.3",
|
||||
"style-loader": "^0.21.0",
|
||||
"uglifyjs-webpack-plugin": "^1.2.7",
|
||||
"url-loader": "^1.0.1",
|
||||
"webpack": "^4.12.1",
|
||||
"webpack-bundle-analyzer": "^3.0.2",
|
||||
"webpack-cli": "^3.0.8",
|
||||
"webpack-dev-server": "^3.1.4",
|
||||
"webpack-merge": "^4.1.4"
|
||||
},
|
||||
"keywords": [
|
||||
"es6",
|
||||
"react"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import React, { Component } from 'react';
|
||||
|
||||
export default class App extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Link} from 'react-router';
|
||||
|
||||
import {Menu,Breadcrumb,Icon,Tooltip} from 'antd';
|
||||
const SubMenu = Menu.SubMenu;
|
||||
import './Index.less';
|
||||
import {FetchUtil} from './utils/fetchUtil';
|
||||
|
||||
export default class Index extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
}
|
||||
handleLogout=()=>{
|
||||
FetchUtil('/merchant/logout','GET','',
|
||||
(data) => {
|
||||
window.location.href="#/login";
|
||||
localStorage.setItem('x-auth-token','')
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
return (
|
||||
|
||||
|
||||
<div className="ant-layout-ceiling-demo">
|
||||
<div className="ant-layout-header">
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-logo">
|
||||
<Tooltip title="回到首页"><Link to="/modelList"><Icon type="home" /></Link></Tooltip>
|
||||
</div>
|
||||
<div className="ant-layout-logo">
|
||||
<Tooltip title="统计报表"><Link to="/report"><Icon type="line-chart" /></Link></Tooltip>
|
||||
</div>
|
||||
<div className="ant-layout-logo">
|
||||
<Tooltip title="配置中心"><Link to="/config"><Icon type="setting" /></Link></Tooltip>
|
||||
</div>
|
||||
|
||||
<div className="ant-layout-logo" style={{float:"right",marginRight:0}}>
|
||||
<Tooltip title="退出登录"><a onClick={this.handleLogout}><Icon type="logout" /></a></Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ant-layout-main">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
.ant-layout-ceiling-demo {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling {
|
||||
font-size: 12px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
background-color: #242736;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling .right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling ul li {
|
||||
display: inline-block;
|
||||
margin: 0 4px;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling-demo .ant-layout-wrapper {
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling-demo .ant-layout-header {
|
||||
background: #fff;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.ant-layout-ceiling-demo .ant-layout-logo {
|
||||
width:36px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
margin: 16px 28px 16px 0;
|
||||
float: left;
|
||||
font-size: 26px;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
.ant-layout-wrapper {
|
||||
padding: 0 50px;
|
||||
}
|
||||
|
||||
.ant-layout-breadcrumb {
|
||||
margin: 7px 0 -17px 24px;
|
||||
}
|
||||
|
||||
.ant-layout-container {
|
||||
background: #fff;
|
||||
margin: 24px 0;
|
||||
position: relative;
|
||||
padding-top: 24px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.ant-layout-content {
|
||||
background: #fff;
|
||||
padding:0 24px 24px;
|
||||
}
|
||||
|
||||
.ant-divider {
|
||||
margin: 0 4px;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
height: 8px;
|
||||
width: 1px;
|
||||
background: #ccc;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Card,Form,Input,Button,Icon,Alert,Col,message} from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
|
||||
import './Login.less';
|
||||
import {fetchVersion} from './utils/fetchUtil';
|
||||
import {trim} from './utils/validateUtil';
|
||||
import Register from './register';
|
||||
export default class Login extends React.Component{
|
||||
|
||||
state={
|
||||
username:'',
|
||||
password:'',
|
||||
captcha:'',
|
||||
rd:Math.random(),
|
||||
|
||||
showMsg:false,
|
||||
msg:''
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleLogin=()=>{
|
||||
if(!this.state.username){
|
||||
this.setState({
|
||||
showMsg:true,
|
||||
msg:'请输入用户名'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if(!this.state.password){
|
||||
this.setState({
|
||||
showMsg:true,
|
||||
msg:'请输入密码'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if(!this.state.captcha){
|
||||
this.setState({
|
||||
showMsg:true,
|
||||
msg:'请输入验证码'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
let formData = new FormData();
|
||||
formData.append("loginName",this.state.username);
|
||||
formData.append("passwd",this.state.password);
|
||||
formData.append("captcha",this.state.captcha);
|
||||
const hide = message.loading('正在执行中...', 0);
|
||||
fetch(fetchVersion+'/merchant/login',{credentials: 'include',method: 'POST',
|
||||
body:formData})
|
||||
.then((res) => {
|
||||
hide();
|
||||
if(res.ok){
|
||||
return res.json();
|
||||
}
|
||||
else{
|
||||
Modal.error({
|
||||
title: '系统错误',
|
||||
content: '请检查是否有参数配置错误',
|
||||
});
|
||||
}
|
||||
})
|
||||
.then((data)=>{
|
||||
if(data.success){
|
||||
localStorage.setItem('x-auth-token',data.data['x-auth-token'])
|
||||
window.location.href="#/modelList";
|
||||
}
|
||||
else{
|
||||
this.refs.captcha.click();
|
||||
this.setState({
|
||||
msg:data.msg,
|
||||
showMsg:true
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e.message);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
handleClick=(event)=>{
|
||||
this.setState({
|
||||
rd:Math.random()
|
||||
})
|
||||
}
|
||||
|
||||
handleKeyDown=(event)=>{
|
||||
if(event.keyCode==13){
|
||||
this.handleLogin();
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 7 },
|
||||
wrapperCol: { span: 13 },
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="middleBox" onKeyDown={this.handleKeyDown}>
|
||||
<Card>
|
||||
<h2 style={{textAlign:"center",paddingBottom:10,borderBottom:"1px dashed #ececec"}}><Icon type="lock" /> 风控引擎管理平台</h2>
|
||||
<Form layout={'horizontal'} style={{marginTop:30}}>
|
||||
<FormItem {...formItemLayout} label="用户名">
|
||||
<Input size="large" type="text" name="username" value={this.state.username} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="密码">
|
||||
<Input type="password" name="password" value={this.state.password} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="验证码" style={{marginBottom:12}}>
|
||||
<Col span="8">
|
||||
<Input style={{width:60}} size="large" type="text" name="captcha" value={this.state.captcha} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span="12">
|
||||
<span><img id="captcha" ref="captcha" src={fetchVersion+"/common/getCaptcha?"+this.state.rd} onClick={this.handleClick}/> </span>
|
||||
</Col>
|
||||
</FormItem>
|
||||
|
||||
<FormItem wrapperCol={{ span: 13, offset: 7 }}>
|
||||
<div style={this.state.showMsg?{display:"block"}:{display:"none"}}><Alert message={this.state.msg} type="error" /></div>
|
||||
<Button type="primary" onClick={this.handleLogin}>登录</Button> <Register/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
.middleBox{
|
||||
width:440px;
|
||||
margin:0 auto;
|
||||
padding-top:200px;
|
||||
}
|
||||
|
||||
#captcha{
|
||||
cursor:pointer;
|
||||
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import {Form,Input,Breadcrumb,Row,Col,Icon,Card,Select,Button,Cascader,Tooltip,message,Modal} from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const OptGroup = Select.OptGroup;
|
||||
|
||||
import './Abstraction.less';
|
||||
|
||||
import ComplexCondition from './ComplexCondition';
|
||||
|
||||
import {generateScript,validateRules} from '../utils/groovyUtil';
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class Abstraction extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
if(props.abstraction!=undefined){
|
||||
const abstraction=props.abstraction;
|
||||
|
||||
this.state={
|
||||
name:abstraction.name,
|
||||
label:abstraction.label,
|
||||
aggregateType:abstraction.aggregateType+'',
|
||||
searchField:abstraction.searchField,
|
||||
searchIntervalType:abstraction.searchIntervalType+'',
|
||||
searchIntervalValue:abstraction.searchIntervalValue,
|
||||
functionField:abstraction.functionField,
|
||||
comment:abstraction.comment,
|
||||
ruleDefinition:abstraction.ruleDefinition==undefined?null:abstraction.ruleDefinition,
|
||||
ruleScript:abstraction.ruleScript
|
||||
}
|
||||
}
|
||||
else{
|
||||
this.state={
|
||||
name:'',
|
||||
label:'',
|
||||
aggregateType:'',
|
||||
searchField:'',
|
||||
searchIntervalType:'',
|
||||
searchIntervalValue:'',
|
||||
functionField:'',
|
||||
comment:'',
|
||||
ruleDefinition:null,
|
||||
ruleScript:''
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
if(this.props.abstraction.id!=0){
|
||||
param.id=this.props.abstraction.id;
|
||||
}
|
||||
if(!this.state.ruleDefinition){
|
||||
let fieldList=this.props.fieldList;
|
||||
let fieldArr=this.state.searchField.split('.');
|
||||
let fieldType='STRING';
|
||||
for(let i=0;i<fieldList.length;i++){
|
||||
if(fieldList[i].value==fieldArr[0]){
|
||||
for(let j=0;j<fieldList[i].children.length;j++){
|
||||
if(fieldList[i].children[j].value==fieldArr[1]){
|
||||
if(fieldArr.length==2){
|
||||
fieldType=fieldList[i].children[j].type;
|
||||
}
|
||||
else{
|
||||
for(let k=0;k<fieldList[i].children[j].children.length;k++){
|
||||
if(fieldList[i].children[j].children[k].value==fieldArr[2]){
|
||||
fieldType=fieldList[i].children[j].children[k].type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.state.ruleDefinition={
|
||||
"linking":"All",
|
||||
"conditions":[
|
||||
{
|
||||
"class":"SMPL",
|
||||
"expressions":[
|
||||
{
|
||||
"column":this.state.searchField,
|
||||
"type":fieldType,
|
||||
"class":"ENTATTR"
|
||||
}],
|
||||
"enabled":true,
|
||||
"operator":"IsNotNull"
|
||||
}],
|
||||
"class":"PDCT",
|
||||
"enabled":true
|
||||
}
|
||||
}
|
||||
if(!validateRules(this.state.ruleDefinition)){
|
||||
Modal.error({
|
||||
title:'请检查过滤条件是否配置完整'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
param.modelId=this.props.modelId;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
param.aggregateType=this.state.aggregateType;
|
||||
param.searchField=this.state.searchField;
|
||||
param.searchIntervalType=this.state.searchIntervalType;
|
||||
param.searchIntervalValue=this.state.searchIntervalValue;
|
||||
param.functionField=this.state.functionField;
|
||||
param.comment=this.state.comment;
|
||||
param.ruleDefinition=this.state.ruleDefinition;
|
||||
param.ruleScript=generateScript(this.state.ruleDefinition,"Abstraction");
|
||||
param.status=1;
|
||||
|
||||
FetchUtil('/abstraction/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success==true){
|
||||
message.success('保存成功!');
|
||||
}
|
||||
else{
|
||||
message.error('保存失败!');
|
||||
}
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
displayRender = (labels, selectedOptions) => labels.map((label, i) => {
|
||||
const option = selectedOptions[i];
|
||||
if (i === labels.length - 1) {
|
||||
return (
|
||||
<span key={option.value+i}>
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span key={option.value+i}>{label} / </span>;
|
||||
});
|
||||
|
||||
handleCascader=(name,value,selectedOptions)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value.join('.'));
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleChangeCondition=(condition,index)=>{
|
||||
let ruleDefinition=this.state.ruleDefinition;
|
||||
|
||||
if(condition==null){
|
||||
ruleDefinition=null;
|
||||
}
|
||||
else{
|
||||
ruleDefinition=condition;
|
||||
}
|
||||
this.setState({
|
||||
ruleDefinition:ruleDefinition
|
||||
})
|
||||
}
|
||||
|
||||
handleAddCondition=()=>{
|
||||
let ruleDefinition=this.state.ruleDefinition;
|
||||
|
||||
if(ruleDefinition==null){
|
||||
ruleDefinition={
|
||||
"class": "PDCT",
|
||||
"enabled": true,
|
||||
"linking": "All",
|
||||
"conditions": [
|
||||
{
|
||||
"class": "SMPL",
|
||||
"enabled": true,
|
||||
"operator": "",
|
||||
"expressions": [
|
||||
{
|
||||
"class": "ENTATTR",
|
||||
"type": "",
|
||||
"column": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
else{
|
||||
ruleDefinition.conditions.push(
|
||||
{
|
||||
"class": "SMPL",
|
||||
"enabled": true,
|
||||
"operator": "",
|
||||
"expressions": [
|
||||
{
|
||||
"class": "ENTATTR",
|
||||
"type": "",
|
||||
"column": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
this.setState({
|
||||
ruleDefinition:ruleDefinition
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 18 },
|
||||
};
|
||||
|
||||
let ruleDefinition=this.state.ruleDefinition;
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
aggregateType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
searchField:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
searchInterval:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入指标名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的指标名';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.aggregateType){
|
||||
validate.aggregateType.help='请选择聚合条件';
|
||||
validate.aggregateType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.searchField){
|
||||
validate.searchField.help='请输入搜索字段';
|
||||
validate.searchField.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.searchIntervalValue){
|
||||
validate.searchInterval.help='请输入时间片';
|
||||
validate.searchInterval.status='warning';
|
||||
isValidated=false;
|
||||
}else if(!/^[0-9]+$/.test(this.state.searchIntervalValue)){
|
||||
validate.searchInterval.help='时间片必须为数字';
|
||||
validate.searchInterval.status='error';
|
||||
isValidated=false;
|
||||
}else if(!this.state.searchIntervalType){
|
||||
validate.searchInterval.help='请选择时间单位';
|
||||
validate.searchInterval.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{width:750}}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="指标名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'指标显示名称,一般为中文,如"100秒内设备注册数"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="聚合条件:" help={validate.aggregateType.help} validateStatus={validate.aggregateType.status}>
|
||||
<Select value={this.state.aggregateType} onChange={this.handleSelect.bind(this,'aggregateType')}>
|
||||
<Option value="">请选择</Option>
|
||||
<Option value="1">求总数</Option>
|
||||
<Option value="2">求不同项总数</Option>
|
||||
<Option value="3">求和</Option>
|
||||
<Option value="4">求平均值</Option>
|
||||
<Option value="5">求最大值</Option>
|
||||
<Option value="6">求最小值</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="搜索字段:" help={validate.searchField.help} validateStatus={validate.searchField.status}>
|
||||
<Cascader
|
||||
title={this.state.searchField.split(".")}
|
||||
options={this.props.fieldList}
|
||||
allowClear={false}
|
||||
value={this.state.searchField.split(".")}
|
||||
displayRender={this.displayRender}
|
||||
onChange={this.handleCascader.bind(this,'searchField')}
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="统计字段:">
|
||||
<Cascader
|
||||
title={this.state.functionField.split(".")}
|
||||
options={this.props.fieldList}
|
||||
allowClear={false}
|
||||
value={this.state.functionField.split(".")}
|
||||
displayRender={this.displayRender}
|
||||
onChange={this.handleCascader.bind(this,'functionField')}
|
||||
/>
|
||||
|
||||
<Button style={{marginTop:10}} onClick={()=>{this.setState({functionField:''})}}>清空统计字段</Button>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="时间片:" help={validate.searchInterval.help} validateStatus={validate.searchInterval.status}>
|
||||
<Row>
|
||||
<Col span={4} style={{marginTop:1}}>
|
||||
<Input type="text" name="searchIntervalValue" value={this.state.searchIntervalValue} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={4} offset={1}>
|
||||
<Select value={this.state.searchIntervalType} onChange={this.handleSelect.bind(this,'searchIntervalType')}>
|
||||
<Option value="">请选择</Option>
|
||||
<Option value="1">年</Option>
|
||||
<Option value="2">月</Option>
|
||||
<Option value="5">日</Option>
|
||||
<Option value="11">时</Option>
|
||||
<Option value="12">分</Option>
|
||||
<Option value="13">秒</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'搜索某段时间的数据,数值为正数,代表范围区间,如 3 ,再配合后面的时间单位,如 月,就表示3个月内的数据'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="备注:">
|
||||
<Input type="textarea" name="comment" value={this.state.comment} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<Row>
|
||||
<Col span={4} offset={4}>
|
||||
<Tooltip title="添加过滤条件" onClick={this.handleAddCondition}><span className="addRule"><Icon type="plus" /> 添加过滤条件</span></Tooltip>
|
||||
<br/>
|
||||
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<ComplexCondition fieldList={this.props.fieldList} dataList={this.props.dataList} condition={this.state.ruleDefinition} changeParentCondition={this.handleChangeCondition} index={0}/>
|
||||
|
||||
<div className="separate"></div>
|
||||
<Row>
|
||||
<Col span={4} offset={4}>
|
||||
<Button type="primary" onClick={this.handleSubmit.bind(this,isValidated)}>保存</Button>{' '}
|
||||
<Button type="primary" onClick={this.props.delete}>删除</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
.addRule{
|
||||
color:rgb(102, 102, 102);
|
||||
cursor:pointer;
|
||||
font-size:16px;
|
||||
}
|
||||
|
||||
.addRule:hover{
|
||||
color:black;
|
||||
}
|
||||
|
||||
.separate{
|
||||
width:100%;
|
||||
height:0;
|
||||
border-bottom:rgb(102, 102, 102) 1px dashed;
|
||||
margin-top:5px;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.condition-row{
|
||||
height:26px;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
import React,{Component} from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Spin} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import CollapseGroup from '../common/CollapseGroup';
|
||||
import Collapse from '../common/Collapse';
|
||||
|
||||
import Abstraction from './Abstraction';
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class AbstractionList extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
name:'',
|
||||
label:'',
|
||||
status:"1",
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null,
|
||||
fieldList:[],
|
||||
dataList:[],
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.params.id;
|
||||
param.aggregateType=this.state.aggregateType;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/abstraction','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = value;
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleAdd=()=>{
|
||||
let tData=this.state.tData;
|
||||
|
||||
tData.push({
|
||||
id:0,
|
||||
name:'',
|
||||
label:'',
|
||||
aggregateType:'',
|
||||
searchField:'',
|
||||
searchIntervalType:'',
|
||||
searchIntervalValue:'',
|
||||
functionField:'',
|
||||
comment:'',
|
||||
ruleDefinition:null,
|
||||
ruleScript:''
|
||||
});
|
||||
|
||||
this.setState({
|
||||
tData:tData
|
||||
})
|
||||
}
|
||||
|
||||
handleDelete=(index)=>{
|
||||
let tData=this.state.tData;
|
||||
let id=tData[index].id;
|
||||
if(id!=0){
|
||||
FetchUtil('/abstraction/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
if(data.success==true){
|
||||
message.success('删除成功!');
|
||||
}
|
||||
else{
|
||||
message.error('删除失败!');
|
||||
}
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
else{
|
||||
tData.splice(index,1);
|
||||
this.setState({
|
||||
tData:tData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
|
||||
FetchUtil('/abstraction/datacolumns/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldList:data.data.list
|
||||
});
|
||||
});
|
||||
FetchUtil('/datalist/list/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
dataList:data.data.list
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="指标名:">
|
||||
<Input value={this.state.name} name="name" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<Button type="primary" onClick={this.handleAdd}>新增</Button>
|
||||
</Form>
|
||||
</div>
|
||||
<Spin size="large" spinning={this.state.loading}>
|
||||
<CollapseGroup>
|
||||
{this.state.tData.filter((info,index)=>{
|
||||
if(this.state.name){
|
||||
var reg = new RegExp('('+ this.state.name+')','gi');
|
||||
return reg.test(info.label);
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}).map((info,index)=>{
|
||||
return (<Collapse key={info.id+""+index} title={info.label?info.label:'新增(请保存)'}>
|
||||
<Abstraction abstraction={info} modelId={this.props.params.id} fieldList={this.state.fieldList} dataList={this.state.dataList} reload={this.fetchTableData} delete={this.handleDelete.bind(this,index)}/>
|
||||
</Collapse>);
|
||||
})
|
||||
}
|
||||
|
||||
</CollapseGroup>
|
||||
</Spin>
|
||||
|
||||
<div>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import {Form,Input,Row,Col,Card,Select,Button,Cascader,Tooltip,Icon} from 'antd';
|
||||
|
||||
const Option = Select.Option;
|
||||
|
||||
import SimpleCondition from './SimpleCondition';
|
||||
|
||||
export default class ComplexCondition extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
condition.linking=value;
|
||||
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleChangeCondition=(childCondition,childIndex)=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
|
||||
if(childCondition==null){
|
||||
condition.conditions.splice(childIndex,1);
|
||||
}
|
||||
else{
|
||||
condition.conditions[childIndex]=childCondition;
|
||||
}
|
||||
|
||||
if(condition.conditions.length==0){
|
||||
this.props.changeParentCondition(null,index);
|
||||
}
|
||||
else{
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
}
|
||||
|
||||
handleSimpleCondition=()=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
|
||||
condition.conditions.push(
|
||||
{
|
||||
"class": "SMPL",
|
||||
"enabled": true,
|
||||
"operator": "",
|
||||
"expressions": [
|
||||
{
|
||||
"class": "ENTATTR",
|
||||
"type": "STRING",
|
||||
"column": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleComplexCondition=()=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
|
||||
condition.conditions.push(
|
||||
{
|
||||
"class": "PDCT",
|
||||
"enabled": true,
|
||||
"linking": "All",
|
||||
"conditions": [
|
||||
{
|
||||
"class": "SMPL",
|
||||
"enabled": true,
|
||||
"operator": "",
|
||||
"expressions": [
|
||||
{
|
||||
"class": "ENTATTR",
|
||||
"type": "STRING",
|
||||
"column": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
render(){
|
||||
if(this.props.condition==null){
|
||||
return (<div/>);
|
||||
}
|
||||
else{
|
||||
return (
|
||||
<div style={{marginLeft:20}}>
|
||||
<div className="condition-row">
|
||||
<Select style={{width:100}} readOnly={this.props.readOnly} value={this.props.condition.linking} defaultValue={'All'} onChange={this.handleSelect.bind(this,'linking')}>
|
||||
<Option value="All">All</Option>
|
||||
<Option value="Any">Any</Option>
|
||||
<Option value="NotAll">NotAll</Option>
|
||||
<Option value="None">None</Option>
|
||||
</Select>条件成立
|
||||
{this.props.readOnly!=true?<Tooltip title="添加简单条件" onClick={this.handleSimpleCondition}><span style={{cursor:"pointer",marginRight:"10px"}}><Icon type="plus" />简单</span></Tooltip>:''}
|
||||
{this.props.readOnly!=true?<Tooltip title="添加复杂条件" onClick={this.handleComplexCondition}><span style={{cursor:"pointer"}}><Icon type="plus" />复杂</span></Tooltip>:''}
|
||||
</div>
|
||||
{this.props.condition.conditions.map((info,index)=>{
|
||||
if(info.class=='SMPL'){
|
||||
return (
|
||||
<SimpleCondition key={index} readOnly={this.props.readOnly} fieldList={this.props.fieldList} dataList={this.props.dataList} condition={info} changeParentCondition={this.handleChangeCondition} index={index} />
|
||||
);
|
||||
}
|
||||
else{
|
||||
return (
|
||||
<ComplexCondition key={index} readOnly={this.props.readOnly} fieldList={this.props.fieldList} dataList={this.props.dataList} condition={info} changeParentCondition={this.handleChangeCondition} index={index}/>
|
||||
);
|
||||
}
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import {Form,Input,Row,Col,Card,Select,Button,Cascader,Tooltip,Icon} from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const OptGroup = Select.OptGroup;
|
||||
|
||||
import {Operator,operatorMap} from '../utils/operatorUtil';
|
||||
|
||||
export default class SimpleCondition extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
}
|
||||
|
||||
handleConditionColumn=(name,value,selectedOptions)=>{
|
||||
let type=selectedOptions[selectedOptions.length-1].type;
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
if(name=='expression'){
|
||||
condition.operator='';
|
||||
condition.expressions=condition.expressions.slice(0,1);
|
||||
condition.expressions[0]={
|
||||
class: "ENTATTR",
|
||||
type: type,
|
||||
column: value.join('.')
|
||||
}
|
||||
}
|
||||
else if(name=='expressionOption'){
|
||||
if(condition.expressions.length<=1){
|
||||
condition.expressions.push({
|
||||
class: "ENTATTR",
|
||||
type: type,
|
||||
column: value.join('.')
|
||||
})
|
||||
}
|
||||
else{
|
||||
condition.expressions[1]={
|
||||
class: "ENTATTR",
|
||||
type: type,
|
||||
column: value.join('.')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleOperator=(value)=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
|
||||
condition.operator=value;
|
||||
condition.expressions=condition.expressions.slice(0,1);
|
||||
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleDataList=(value)=>{
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
|
||||
if(condition.expressions.length<=1){
|
||||
condition.expressions.push({
|
||||
class: "CONST",
|
||||
type: "LIST",
|
||||
value: value
|
||||
})
|
||||
}
|
||||
else{
|
||||
condition.expressions[1]={
|
||||
class: "CONST",
|
||||
type: "LIST",
|
||||
value: value
|
||||
}
|
||||
}
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleInput=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
|
||||
let condition=this.props.condition;
|
||||
let index=this.props.index;
|
||||
const type=condition.expressions[0].type;
|
||||
if(condition.expressions.length<=1){
|
||||
condition.expressions.push({
|
||||
class: "CONST",
|
||||
type: type,
|
||||
value: value
|
||||
})
|
||||
}
|
||||
else{
|
||||
condition.expressions[1]={
|
||||
class: "CONST",
|
||||
type: type,
|
||||
value: value
|
||||
}
|
||||
}
|
||||
this.props.changeParentCondition(condition,index);
|
||||
}
|
||||
|
||||
handleDelete=()=>{
|
||||
this.props.changeParentCondition(null,this.props.index);
|
||||
}
|
||||
|
||||
displayRender = (labels, selectedOptions) => labels.map((label, i) => {
|
||||
const option = selectedOptions[i];
|
||||
if (i === labels.length - 1) {
|
||||
return (
|
||||
<span key={option.value+i}>
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span key={option.value+i}>{label} / </span>;
|
||||
})
|
||||
|
||||
render(){
|
||||
let condition=this.props.condition;
|
||||
let expression=condition.expressions[0];
|
||||
let expressionOption=condition.expressions[1];
|
||||
return (
|
||||
<div className="condition-row" style={{marginLeft:20}}>
|
||||
<Cascader
|
||||
options={this.props.fieldList}
|
||||
allowClear={false}
|
||||
value={expression.column.split('.')}
|
||||
displayRender={this.displayRender}
|
||||
onChange={this.handleConditionColumn.bind(this,'expression')}
|
||||
readOnly={this.props.readOnly}
|
||||
|
||||
/>
|
||||
<Select dropdownMatchSelectWidth={false} readOnly={this.props.readOnly} value={condition.operator} onChange={this.handleOperator}>
|
||||
{operatorMap[expression.type].map(op=>
|
||||
<Option key={op.value} value={op.value}>{op.label}</Option>
|
||||
)}
|
||||
</Select>
|
||||
{condition.operator==''?'':
|
||||
Operator[condition.operator].nextType=='input'?(
|
||||
<Input style={{width:200}} type="text" readOnly={this.props.readOnly} value={expressionOption==undefined?'':expressionOption.value} onChange={this.handleInput}/>):
|
||||
Operator[condition.operator].nextType=='list'?(
|
||||
<Select dropdownMatchSelectWidth={false} readOnly={this.props.readOnly} value={expressionOption==undefined?'':expressionOption.value} onChange={this.handleDataList}>
|
||||
{this.props.dataList.map(op=>
|
||||
<Option key={op.id} value={op.name}>{op.label}</Option>
|
||||
)}
|
||||
</Select>
|
||||
):
|
||||
Operator[condition.operator].nextType=='field'?(
|
||||
<Cascader
|
||||
options={this.props.fieldList}
|
||||
allowClear={false}
|
||||
value={expressionOption==undefined?'':expressionOption.column.split('.')}
|
||||
displayRender={this.displayRender}
|
||||
onChange={this.handleConditionColumn.bind(this,'expressionOption')}
|
||||
readOnly={this.props.readOnly}
|
||||
/>
|
||||
):''
|
||||
}
|
||||
{this.props.readOnly!=true?<Tooltip title="删除" onClick={this.handleDelete}><Icon type="delete" style={{fontSize:16,lineHeight:"22px"}}/></Tooltip>:''}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import AddActivation from './modal/AddActivation';
|
||||
import EditActivation from './modal/EditActivation';
|
||||
|
||||
export default class Activation extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
name:'',
|
||||
label:'',
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.params.id;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
|
||||
FetchUtil('/activation','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deleteActivation=(id)=>{
|
||||
FetchUtil('/activation/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
message.info('删除成功!');
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '策略名',
|
||||
dataIndex: 'label'
|
||||
},{
|
||||
title: '备注',
|
||||
dataIndex: 'comment'
|
||||
},{
|
||||
title: '警戒值',
|
||||
dataIndex: 'median'
|
||||
},{
|
||||
title: '拒绝值',
|
||||
dataIndex: 'high'
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
<EditActivation modelId={this.props.params.id} row={r} reload={this.fetchTableData}/>
|
||||
<span className="ant-divider"></span>
|
||||
<Tooltip title="管理规则"><Link to={"/ruleList/"+r.modelId+"/"+r.id}>管理规则</Link></Tooltip>
|
||||
<span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该字段吗?'} onConfirm={this.deleteActivation.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="策略名:">
|
||||
<Input value={this.state.name} name="name" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<AddActivation modelId={this.props.params.id} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData.filter((item,index,array)=>{
|
||||
var reg = new RegExp('('+ this.state.name+')','gi');
|
||||
if(this.state.name){
|
||||
return (reg.test(item.label));
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
})}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import {Form,Input,InputNumber,Breadcrumb,Row,Col,Icon,Card,Select,Button,Cascader,Tooltip,message,Modal} from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import ComplexCondition from '../abstraction/ComplexCondition';
|
||||
|
||||
export default class HistoryRecord extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
height:40
|
||||
}
|
||||
}
|
||||
|
||||
slideDown=()=>{
|
||||
if(this.state.height=="auto"){
|
||||
return;
|
||||
}
|
||||
let height = this.refs.content1.offsetHeight+this.refs.content2.offsetHeight+40;
|
||||
if(this.state.height<height){
|
||||
this.setState({
|
||||
height:this.state.height+15
|
||||
},()=>{
|
||||
setTimeout(this.slideDown,1);
|
||||
})
|
||||
}else{
|
||||
this.setState({
|
||||
height:"auto"
|
||||
})
|
||||
this.refs.content.className = 'up'
|
||||
}
|
||||
}
|
||||
|
||||
slideUp=()=>{
|
||||
let height = this.refs.content1.offsetHeight+this.refs.content2.offsetHeight+40;
|
||||
if(this.state.height=="auto"){
|
||||
this.state.height=height;
|
||||
}
|
||||
if(this.state.height>55){
|
||||
this.setState({
|
||||
height:this.state.height-15
|
||||
},()=>{
|
||||
setTimeout(this.slideUp,1);
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:40
|
||||
})
|
||||
this.refs.content.className = 'down'
|
||||
}
|
||||
}
|
||||
|
||||
handleClick=()=>{
|
||||
if(this.refs.content.className === 'down'){
|
||||
this.slideDown();
|
||||
}
|
||||
if(this.refs.content.className === 'up'){
|
||||
this.slideUp();
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 18 },
|
||||
};
|
||||
|
||||
let abstractionList=[];
|
||||
if(this.props.fieldList.length>0){
|
||||
abstractionList=this.props.fieldList.filter(x=>x.value=='abstractions')[0].children;
|
||||
}
|
||||
|
||||
const ruleHistory=this.props.ruleHistory;
|
||||
|
||||
return (
|
||||
<div ref="content" className="down" style={{border:'1px solid #d9d9d9',borderRadius:'5px',padding:'10px',height:this.state.height,overflow:'hidden'}}>
|
||||
<div style={{padding:'0 0 20px 20px',cursor:'pointer'}} onClick={this.handleClick}>用户{ruleHistory.merchantCode}修改</div>
|
||||
<div ref="content1" style={{width:750}}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="显示名称:">
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={ruleHistory.label} readOnly/>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="命中初始得分:">
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="initScore" value={ruleHistory.initScore} readOnly/>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="命中基数:">
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="baseNum" value={ruleHistory.baseNum} readOnly/>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="操作符:">
|
||||
<Select value={ruleHistory.operator} readOnly>
|
||||
<Option value="NONE">无</Option>
|
||||
<Option value="ADD">加</Option>
|
||||
<Option value="DEC">减</Option>
|
||||
<Option value="MUL">乘</Option>
|
||||
<Option value="DIV">除</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="指标字段:">
|
||||
<Select value={ruleHistory.abstractionName} readOnly>
|
||||
{abstractionList==undefined?null:abstractionList.map((x,index)=><Option key={x.value+index} value={x.value}>{x.label}</Option>)}
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="比率:">
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="rate" value={ruleHistory.rate} readOnly/>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div ref="content2">
|
||||
<div>
|
||||
<Tooltip title="添加过滤条件" onClick={this.handleAddCondition}><span className="addRule"><Icon type="plus" /> 添加过滤条件</span></Tooltip>
|
||||
</div>
|
||||
<ComplexCondition readOnly fieldList={this.props.fieldList} dataList={this.props.dataList} condition={ruleHistory.ruleDefinition==undefined?null:JSON.parse(ruleHistory.ruleDefinition)} changeParentCondition={()=>{}} index={0}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import React,{Component} from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Timeline,Icon} from 'antd';
|
||||
import CollapseGroup from '../common/CollapseGroup';
|
||||
import Collapse from '../common/Collapse';
|
||||
import { Link } from 'react-router';
|
||||
import moment from 'moment';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import HistoryRecord from './HistoryRecord';
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class HistoryRecordList extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
label:'',
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null,
|
||||
fieldList:[],
|
||||
dataList:[]
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.ruleId=this.props.params.ruleId;
|
||||
|
||||
//此处为单条策略历史记录接口的获取,参数中应该有本条策略的id,否则无法区分
|
||||
FetchUtil('/rule/ruleHistory','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
label:data.data.page.list[0].label,
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
componentWillMount() {
|
||||
this.fetchTableData();
|
||||
FetchUtil('/activation/datacolumns/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldList:data.data.list
|
||||
});
|
||||
});
|
||||
FetchUtil('/datalist/list/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
dataList:data.data.list
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header" style={{fontSize:'16px',marginBottom:'20px'}}>
|
||||
<Link to={"/ruleList/"+this.props.params.id+"/"+this.props.params.activationId}><Icon type="left-circle" style={{marginRight:'10px'}} />{this.state.label}</Link><span style={{marginLeft:'20px'}}>历史记录</span>
|
||||
</div>
|
||||
|
||||
<Timeline style={{marginLeft:'150px'}}>
|
||||
{this.state.tData.map((info,index)=>{
|
||||
return (
|
||||
<Timeline.Item key={index}>
|
||||
<span style={{position:'absolute',left:'-120px'}}>{moment(info.updateTime).format('YYYY-MM-DD HH:mm:ss')}</span>
|
||||
<HistoryRecord ruleHistory={info} modelId={this.props.params.id} activationId={this.props.params.activationId} fieldList={this.state.fieldList} dataList={this.state.dataList} reload={this.fetchTableData}/>
|
||||
</Timeline.Item>
|
||||
);
|
||||
})
|
||||
}
|
||||
</Timeline>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,341 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import {Form,Input,InputNumber,Breadcrumb,Row,Col,Icon,Card,Select,Button,Cascader,Tooltip,message,Modal} from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import ComplexCondition from '../abstraction/ComplexCondition';
|
||||
|
||||
import {generateScript,validateRules} from '../utils/groovyUtil';
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class Rule extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
if(props.rule!=undefined){
|
||||
const rule=props.rule;
|
||||
|
||||
this.state={
|
||||
label:rule.label,
|
||||
initScore:rule.initScore,
|
||||
baseNum:rule.baseNum,
|
||||
operator:rule.operator,
|
||||
abstractionName:rule.abstractionName,
|
||||
rate:rule.rate,
|
||||
ruleDefinition:rule.ruleDefinition==undefined?null:rule.ruleDefinition,
|
||||
scripts:rule.scripts
|
||||
}
|
||||
}
|
||||
else{
|
||||
this.state={
|
||||
label:'',
|
||||
initScore:'0',
|
||||
baseNum:'0',
|
||||
operator:'NONE',
|
||||
abstractionName:'',
|
||||
rate:'100',
|
||||
ruleDefinition:null,
|
||||
scripts:''
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
//state[name] = trim(value);
|
||||
state[name] = value;
|
||||
|
||||
if(name=='operator'&&value=='NONE'){
|
||||
state['abstractionName']='';
|
||||
}
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleChangeCondition=(condition,index)=>{
|
||||
let ruleDefinition=this.state.ruleDefinition;
|
||||
|
||||
if(condition==null){
|
||||
ruleDefinition=null;
|
||||
}
|
||||
else{
|
||||
ruleDefinition=condition;
|
||||
}
|
||||
this.setState({
|
||||
ruleDefinition:ruleDefinition
|
||||
})
|
||||
}
|
||||
|
||||
handleAddCondition=()=>{
|
||||
let ruleDefinition=this.state.ruleDefinition;
|
||||
|
||||
if(ruleDefinition==null){
|
||||
ruleDefinition={
|
||||
"class": "PDCT",
|
||||
"enabled": true,
|
||||
"linking": "All",
|
||||
"conditions": [
|
||||
{
|
||||
"class": "SMPL",
|
||||
"enabled": true,
|
||||
"operator": "",
|
||||
"expressions": [
|
||||
{
|
||||
"class": "ENTATTR",
|
||||
"type": "",
|
||||
"column": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
ruleDefinition:ruleDefinition
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
if(!this.state.ruleDefinition){
|
||||
Modal.error({
|
||||
title:'请至少配置一条过滤规则'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if(!validateRules(this.state.ruleDefinition)){
|
||||
Modal.error({
|
||||
title:'请检查过滤条件是否配置完整'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
var param={};
|
||||
if(this.props.rule.id!=0){
|
||||
param.id=this.props.rule.id;
|
||||
}
|
||||
param.modelId=this.props.modelId;
|
||||
param.activationId=this.props.activationId;
|
||||
param.label=this.state.label;
|
||||
param.initScore=this.state.initScore,
|
||||
param.baseNum=this.state.baseNum,
|
||||
param.operator=this.state.operator,
|
||||
param.abstractionName=this.state.abstractionName,
|
||||
param.rate=this.state.rate,
|
||||
param.ruleDefinition=this.state.ruleDefinition;
|
||||
param.scripts=generateScript(this.state.ruleDefinition,"Activation");
|
||||
param.status=1;
|
||||
|
||||
FetchUtil('/rule/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success==true){
|
||||
if(this.props.rule.id==0){
|
||||
message.success('添加成功!');
|
||||
}
|
||||
else{
|
||||
message.success('修改成功!');
|
||||
}
|
||||
}
|
||||
else{
|
||||
message.error('修改失败!');
|
||||
}
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 4 },
|
||||
wrapperCol: { span: 18 },
|
||||
};
|
||||
|
||||
let abstractionList=[];
|
||||
if(this.props.fieldList.length>0){
|
||||
abstractionList=this.props.fieldList.filter(x=>x.value=='abstractions')[0].children;
|
||||
}
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
initScore:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
baseNum:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
abstractionName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
rate:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入显示名称';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.initScore){
|
||||
validate.initScore.help='请输入初始得分';
|
||||
validate.initScore.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(this.state.baseNum < 0){
|
||||
validate.baseNum.help='请输入基数';
|
||||
validate.baseNum.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(this.state.operator!='NONE'&&!this.state.abstractionName){
|
||||
validate.abstractionName.help='请选择抽象字段';
|
||||
validate.abstractionName.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(this.state.rate < 0 ){
|
||||
validate.rate.help='请输入rate';
|
||||
validate.rate.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
// if(!/^[0-9]+$/.test(this.state.initScore)){
|
||||
// validate.initScore.help='initScore必须为数字';
|
||||
// validate.initScore.status='error';
|
||||
// isValidated=false;
|
||||
// }
|
||||
// if(!/^[0-9]+$/.test(this.state.baseNum)){
|
||||
// validate.baseNum.help='baseNum必须为数字';
|
||||
// validate.baseNum.status='error';
|
||||
// isValidated=false;
|
||||
// }
|
||||
// if(!/^[0-9]+$/.test(this.state.rate)){
|
||||
// validate.rate.help='rate必须为数字';
|
||||
// validate.rate.status='error';
|
||||
// isValidated=false;
|
||||
// }
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={{width:750}}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="显示名称:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'规则名称,一般为中文,如"1天内设备注册次数过多或注册时间间隔过短"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="命中初始得分:" help={validate.initScore.help} validateStatus={validate.initScore.status}>
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="initScore" value={this.state.initScore} onChange={this.handleSelect.bind(this,'initScore')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'初始得分,在此基础上进行累加计算'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="命中基数:" help={validate.baseNum.help} validateStatus={validate.baseNum.status}>
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="baseNum" value={this.state.baseNum} onChange={this.handleSelect.bind(this,'baseNum')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'配合操作符,与指标字段进行运算'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="操作符:">
|
||||
<Select value={this.state.operator} onChange={this.handleSelect.bind(this,'operator')}>
|
||||
<Option value="NONE">无</Option>
|
||||
<Option value="ADD">加</Option>
|
||||
<Option value="DEC">减</Option>
|
||||
<Option value="MUL">乘</Option>
|
||||
<Option value="DIV">除</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="指标字段:" help={validate.abstractionName.help} validateStatus={validate.abstractionName.status}>
|
||||
<Select disabled={this.state.operator=='NONE'} value={this.state.abstractionName} onChange={this.handleSelect.bind(this,'abstractionName')}>
|
||||
{abstractionList==undefined?null:abstractionList.map((x,index)=><Option key={x.value+index} value={x.value}>{x.label}</Option>)}
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="比率:" help={validate.rate.help} validateStatus={validate.rate.status}>
|
||||
<Row>
|
||||
<Col span={4}>
|
||||
<InputNumber name="rate" value={this.state.rate} onChange={this.handleSelect.bind(this,'rate')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'当指标字段值过大或者过小时,对指标字段进行放大或者缩小,使命中分数更加合理'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<Tooltip title="添加过滤条件" onClick={this.handleAddCondition}><span className="addRule"><Icon type="plus" /> 添加过滤条件</span></Tooltip>
|
||||
</div>
|
||||
<ComplexCondition fieldList={this.props.fieldList} dataList={this.props.dataList} condition={this.state.ruleDefinition} changeParentCondition={this.handleChangeCondition} index={0}/>
|
||||
|
||||
<div className="separate"></div>
|
||||
<Row>
|
||||
<Col span={4} offset={4}>
|
||||
<Button type="primary" onClick={this.handleSubmit.bind(this,isValidated)}>保存</Button>{' '}
|
||||
<Button type="primary" onClick={this.props.delete}>删除</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,304 +0,0 @@
|
||||
import React,{Component} from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Icon,Spin} from 'antd';
|
||||
import CollapseGroup from '../common/CollapseGroup';
|
||||
import Collapse from '../common/Collapse';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import Rule from './Rule';
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
import {fetchVersion} from '../utils/fetchUtil';
|
||||
|
||||
export default class RuleList extends Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
label:'',
|
||||
status:"1",
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null,
|
||||
fieldList:[],
|
||||
dataList:[],
|
||||
|
||||
activation:null,
|
||||
ruleOrder:[]
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.activationId=this.props.params.activationId;
|
||||
param.label=this.state.label;
|
||||
|
||||
FetchUtil('/rule','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
let ruleOrder=data.data.ruleOrder?data.data.ruleOrder.split(','):[];
|
||||
let ruleList=this.getOrderedRules(ruleOrder,data.data.page.list);
|
||||
if(data.data.page.list.length>0||ruleOrder.length>ruleList.length){
|
||||
let unOrderedList=data.data.page.list;
|
||||
ruleList=ruleList.concat(unOrderedList);
|
||||
ruleOrder=ruleList.map(x=>x.id+'');
|
||||
this.handleReOrder(ruleOrder);
|
||||
}
|
||||
this.setState({
|
||||
tData:ruleList,
|
||||
ruleOrder:ruleOrder
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleAdd=()=>{
|
||||
let tData=this.state.tData;
|
||||
|
||||
tData.push({
|
||||
id:0,
|
||||
label:'',
|
||||
initScore:'0',
|
||||
baseNum:'0',
|
||||
operator:'NONE',
|
||||
abstractionName:'',
|
||||
rate:'100',
|
||||
ruleDefinition:null,
|
||||
scripts:''
|
||||
});
|
||||
|
||||
this.setState({
|
||||
tData:tData
|
||||
})
|
||||
}
|
||||
|
||||
handleDelete=(index)=>{
|
||||
let tData=this.state.tData;
|
||||
let id=tData[index].id;
|
||||
if(id!=0){
|
||||
FetchUtil('/rule/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
if(data.success==true){
|
||||
message.success('删除成功!');
|
||||
}
|
||||
else{
|
||||
message.error('删除失败!');
|
||||
}
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
else{
|
||||
tData.splice(index,1);
|
||||
this.setState({
|
||||
tData:tData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleSwitch=(rule)=>{
|
||||
rule.status=(rule.status==0?1:0);
|
||||
|
||||
FetchUtil('/rule/','PUT',JSON.stringify(rule),
|
||||
(data) => {
|
||||
if(data.success==true){
|
||||
if(rule.status==1){
|
||||
message.success('启用成功!');
|
||||
}
|
||||
else{
|
||||
message.success('禁用成功!');
|
||||
}
|
||||
}
|
||||
else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({});
|
||||
});
|
||||
}
|
||||
|
||||
handleReOrder=(ruleOrder=this.state.ruleOrder,showMessage=false)=>{
|
||||
let formData = new FormData();
|
||||
formData.append("activationId",this.props.params.activationId);
|
||||
formData.append("ruleOrder",ruleOrder.join(','));
|
||||
fetch(fetchVersion+'/activation/updateOrder',{credentials: 'include',method: 'POST',
|
||||
body:formData})
|
||||
.then((res) => {
|
||||
if(res.ok){
|
||||
return res.json();
|
||||
}
|
||||
else{
|
||||
Modal.error({
|
||||
title: '系统错误',
|
||||
content: '请检查是否有参数配置错误',
|
||||
});
|
||||
}
|
||||
})
|
||||
.then((data)=>{
|
||||
if(showMessage){
|
||||
message.success('排序成功!');
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
|
||||
getOrderedRules=(ruleOrder,ruleData)=>{
|
||||
let resultList=[];
|
||||
for(let i=0;i<ruleOrder.length;i++){
|
||||
for(let j=0;j<ruleData.length;j++){
|
||||
if(ruleOrder[i]==ruleData[j].id){
|
||||
resultList.push(ruleData.splice(j,1)[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
handleDrag=(ruleId,pos)=>{
|
||||
let ruleOrder=this.state.ruleOrder;
|
||||
let ruleList=this.state.tData;
|
||||
|
||||
let index=ruleOrder.indexOf(ruleId+'');
|
||||
if(index==pos){
|
||||
return;
|
||||
}
|
||||
let order=ruleOrder.splice(index,1);
|
||||
let rule=ruleList.splice(index,1);
|
||||
ruleOrder.splice(pos,0,order[0]);
|
||||
ruleList.splice(pos,0,rule[0]);
|
||||
this.state.ruleOrder=ruleOrder;
|
||||
this.state.tData=ruleList;
|
||||
|
||||
this.setState({
|
||||
});
|
||||
|
||||
// let moveY=0;
|
||||
// if(distance>=0){
|
||||
// moveY=Math.floor(distance/48);
|
||||
// }
|
||||
// else{
|
||||
// moveY=Math.ceil(distance/48);
|
||||
// }
|
||||
// if(moveY==0){return;}
|
||||
// if(moveY<0){
|
||||
// let order=ruleOrder.splice(index,1);
|
||||
// let rule=ruleList.splice(index,1);
|
||||
// ruleOrder.splice(index+moveY,0,order[0]);
|
||||
// ruleList.splice(index+moveY,0,rule[0]);
|
||||
// this.setState({
|
||||
// ruleOrder:ruleOrder,
|
||||
// tData:ruleList
|
||||
// });
|
||||
// }
|
||||
// else{
|
||||
// let order=ruleOrder.splice(index,1);
|
||||
// let rule=ruleList.splice(index,1);
|
||||
// ruleOrder.splice(index+moveY,0,order[0]);
|
||||
// ruleList.splice(index+moveY,0,rule[0]);
|
||||
// this.setState({
|
||||
// ruleOrder:ruleOrder,
|
||||
// tData:ruleList
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
FetchUtil('/activation/datacolumns/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldList:data.data.list
|
||||
});
|
||||
});
|
||||
FetchUtil('/datalist/list/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
dataList:data.data.list
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="显示名称:">
|
||||
<Input value={this.state.label} name="label" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<Button type="primary" onClick={this.handleAdd}>新增</Button>
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<Spin size="large" spinning={this.state.loading}>
|
||||
<CollapseGroup handleDrag={this.handleDrag} handleReOrder={this.handleReOrder} draggable={!this.state.label}>
|
||||
{this.state.tData.filter((info,index)=>{
|
||||
if(this.state.label){
|
||||
var reg = new RegExp('('+ this.state.label+')','gi');
|
||||
return reg.test(info.label);
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
}).map((info,index)=>{
|
||||
return (<Collapse ruleId={info.id} ruleOrder={this.state.ruleOrder} switcher={info.status=='1'} modelId={this.props.params.id} activationId={this.props.params.activationId} type="calendar" onSwitch={this.handleSwitch.bind(this,info)} key={info.id?info.id:index} title={info.label?info.label:'新增(请保存)'}>
|
||||
<Rule rule={info} modelId={this.props.params.id} activationId={this.props.params.activationId} fieldList={this.state.fieldList} dataList={this.state.dataList} reload={this.fetchTableData} delete={this.handleDelete.bind(this,index)}/>
|
||||
</Collapse>);
|
||||
})
|
||||
}
|
||||
|
||||
</CollapseGroup>
|
||||
</Spin>
|
||||
|
||||
{/*
|
||||
<div>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddActivation extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
activationName:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
bottom:'',
|
||||
median:'',
|
||||
high:'',
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = value;
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
activationName:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
bottom:'',
|
||||
median:'',
|
||||
high:'',
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.modelId=this.props.modelId;
|
||||
param.activationName=this.state.activationName;
|
||||
param.label=this.state.label;
|
||||
param.comment=this.state.comment;
|
||||
param.bottom=this.state.bottom;
|
||||
param.median=this.state.median;
|
||||
param.high=this.state.high;
|
||||
param.status=1;
|
||||
|
||||
FetchUtil('/activation/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
median:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
high:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入策略名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的策略名';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.median){
|
||||
validate.median.help='请输入警戒值';
|
||||
validate.median.status='warning';
|
||||
isValidated=false;
|
||||
}else if(!/^\d{1,3}/.test(this.state.median)){
|
||||
validate.median.help='警戒值必须为数字';
|
||||
validate.median.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.high){
|
||||
validate.high.help='请输入拒绝值';
|
||||
validate.high.status='warning';
|
||||
isValidated=false;
|
||||
}else if(!/^\d{1,3}/.test(this.state.high)){
|
||||
validate.high.help='拒绝值必须为数字';
|
||||
validate.high.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
<Modal title="新增字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="策略名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'显示名称,一般为中文,如"异常注册"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="备注:">
|
||||
<Input type="text" name="comment" value={this.state.comment} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="警戒值:" help={validate.median.help} validateStatus={validate.median.status}>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<InputNumber min={1} max={100} name="median" value={this.state.median} onChange={this.handleSelect.bind(this,'median')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果实际风险分数大于此数字,此交易则需要人工审核'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="拒绝值:" help={validate.high.help} validateStatus={validate.high.status}>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<InputNumber min={1} max={100} name="high" value={this.state.high} onChange={this.handleSelect.bind(this,'high')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果实际风险分数大于此数字,此交易则直接拒绝'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditActivation extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
activationName:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
bottom:'0',
|
||||
median:'',
|
||||
high:'',
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/activation/'+this.props.row.id,'GET','',
|
||||
(data) => {
|
||||
const activation=data.data.activation;
|
||||
this.setState({
|
||||
activationName:activation.activationName,
|
||||
label:activation.label,
|
||||
comment:activation.comment,
|
||||
bottom:activation.bottom,
|
||||
median:activation.median,
|
||||
high:activation.high,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = value;
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.modelId=this.props.modelId;
|
||||
param.activationName=this.state.activationName;
|
||||
param.label=this.state.label;
|
||||
param.comment=this.state.comment;
|
||||
param.bottom='0';
|
||||
param.median=this.state.median;
|
||||
param.high=this.state.high;
|
||||
param.status=1;
|
||||
|
||||
FetchUtil('/activation/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('修改成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
activationName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
median:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
high:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.activationName){
|
||||
validate.activationName.help='请输入策略名';
|
||||
validate.activationName.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let activationName = this.state.activationName;
|
||||
if(!reg.test(activationName)){
|
||||
validate.activationName.help='按照提示输入正确的策略名';
|
||||
validate.activationName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入显示名称';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.median){
|
||||
validate.median.help='请输入警戒值';
|
||||
validate.median.status='warning';
|
||||
isValidated=false;
|
||||
}else if(!/^\d{1,3}/.test(this.state.median)){
|
||||
validate.median.help='警戒值必须为数字';
|
||||
validate.median.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.high){
|
||||
validate.high.help='请输入拒绝值';
|
||||
validate.high.status='warning';
|
||||
isValidated=false;
|
||||
}else if(!/^\d{1,3}/.test(this.state.high)){
|
||||
validate.high.help='拒绝值必须为数字';
|
||||
validate.high.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="策略名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'显示名称,一般为中文,如"异常注册"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="备注:">
|
||||
<Input type="text" name="comment" value={this.state.comment} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="警戒值:" help={validate.median.help} validateStatus={validate.median.status}>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<InputNumber min={1} max={100} name="median" value={this.state.median} onChange={this.handleSelect.bind(this,'median')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果实际风险分数大于此数字,此交易则需要人工审核'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="拒绝值:" help={validate.high.help} validateStatus={validate.high.status}>
|
||||
<Row>
|
||||
<Col span={6}>
|
||||
<InputNumber min={1} max={100} name="high" value={this.state.high} onChange={this.handleSelect.bind(this,'high')}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果实际风险分数大于此数字,此交易则直接拒绝'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Switch,Icon} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import './Collapse.less';
|
||||
|
||||
export default class Collapse extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
height:0,
|
||||
|
||||
index:-1,
|
||||
pos:-1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
slideDown=()=>{
|
||||
if(this.state.height=="auto"){
|
||||
return;
|
||||
}
|
||||
if(this.state.height<this.refs.pChild.offsetHeight){
|
||||
this.setState({
|
||||
height:this.state.height+15
|
||||
},()=>{
|
||||
setTimeout(this.slideDown,1);
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:"auto"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
slideUp=()=>{
|
||||
if(this.state.height=="auto"){
|
||||
this.state.height=this.refs.pChild.offsetHeight;
|
||||
}
|
||||
if(this.state.height>0){
|
||||
this.setState({
|
||||
height:this.state.height-15
|
||||
},()=>{
|
||||
setTimeout(this.slideUp,1);
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleClick=()=>{
|
||||
this.props.handleClick();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.slide){
|
||||
this.slideDown();
|
||||
}
|
||||
else{
|
||||
this.slideUp();
|
||||
}
|
||||
}
|
||||
|
||||
handleDragEnd=(e)=>{
|
||||
this.setState({
|
||||
index:-1,
|
||||
pos:-1
|
||||
})
|
||||
this.props.handleReOrder();
|
||||
}
|
||||
|
||||
handleDrag=(e)=>{
|
||||
if(!this.props.draggable){return;}
|
||||
if(e.pageY==0){return;}
|
||||
let pos=Math.floor((e.pageY-300)/48);
|
||||
let index=this.props.ruleOrder.indexOf(this.props.ruleId+'');
|
||||
if(index==pos){
|
||||
return;
|
||||
}
|
||||
if(index==this.state.index&&pos==this.state.pos){
|
||||
return;
|
||||
}
|
||||
this.state.index=index;
|
||||
this.state.pos=pos;
|
||||
this.props.handleDrag(this.props.ruleId,pos);
|
||||
}
|
||||
|
||||
switchClick=(e)=>{
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div style={this.state.index!=-1?{"visibility":"hidden"}:{}} className="p-block" draggable={this.props.draggable} onDragEnd={this.handleDragEnd} onDrag={this.handleDrag}>
|
||||
<div className={'p-block-titles'+(this.props.slide?' p-block-title-select':'')} onClick={this.handleClick}>
|
||||
<div className='p-block-title-left'>{this.props.title}</div>
|
||||
{this.props.switcher!=undefined?
|
||||
<div className='p-block-title-right' onClick={this.switchClick}><Switch checked={this.props.switcher} onChange={this.props.onSwitch}/></div>
|
||||
:''}
|
||||
{
|
||||
this.props.type!=undefined?
|
||||
<div className='p-block-title-right'><Link to={"/historyRecordList/"+this.props.modelId+"/" + this.props.activationId+"/"+this.props.ruleId}><Icon type="calendar" style={{fontSize:'24px',lineHeight:1.5}}/></Link></div>
|
||||
:''
|
||||
}
|
||||
|
||||
</div>
|
||||
<div className={'p-block-contents'+(this.props.slide?' p-block-content-select':'')} style={{height:this.state.height}} ref="pContent">
|
||||
<div ref="pChild" className="p-block-main">
|
||||
{this.props?this.props.children:''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
.p-block{
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
.p-block-titles{
|
||||
height: 40px;
|
||||
border:1px solid #d9d9d9;
|
||||
padding-left: 30px;
|
||||
cursor:pointer;
|
||||
border-radius: 7px;
|
||||
|
||||
&:hover{
|
||||
background-color:#FAFAFA;
|
||||
}
|
||||
}
|
||||
|
||||
.p-block-title-left{
|
||||
float:left;
|
||||
line-height:38px;
|
||||
}
|
||||
|
||||
.p-block-title-right{
|
||||
float:right;
|
||||
line-height:34px;
|
||||
margin-right:20px;
|
||||
}
|
||||
|
||||
.p-block-title-select{
|
||||
background-color:#f7f7f7;
|
||||
border-bottom-right-radius:0;
|
||||
border-bottom-left-radius:0;
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.p-block-contents{
|
||||
clear:both;
|
||||
background-color:white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-block-content-select{
|
||||
border:1px solid #d9d9d9;
|
||||
border-top:none;
|
||||
}
|
||||
|
||||
.p-block-main{
|
||||
padding:20px
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class CollapseGroup extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
activeKey:'',
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
getItems=()=>{
|
||||
if(!this.props){
|
||||
return '';
|
||||
}
|
||||
|
||||
return this.props.children.map((child,index)=>{
|
||||
const key=child.key;
|
||||
const props={
|
||||
slide:child.key==this.state.activeKey?true:false,
|
||||
index:index,
|
||||
draggable:this.props.draggable&&this.state.activeKey=='',
|
||||
|
||||
handleDrag:(ruleId,pos)=>{
|
||||
this.props.handleDrag(ruleId,pos);
|
||||
},
|
||||
handleReOrder:()=>{
|
||||
this.props.handleReOrder();
|
||||
},
|
||||
handleClick:()=>{
|
||||
if(this.state.activeKey==key){
|
||||
this.setState({
|
||||
activeKey:''
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
activeKey:key
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return React.cloneElement(child,props);
|
||||
})
|
||||
}
|
||||
|
||||
allowDrop=(e)=>{
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div style={{position:"relative"}} onDragOver={(this.props.draggable&&this.state.activeKey=='')?this.allowDrop:null}>
|
||||
{this.getItems()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Menu,Icon,Form,Select, Card, Row, Col} from 'antd';
|
||||
import {Link} from 'react-router';
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class ConfigCenter extends React.Component{
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>配置中心</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
<Row gutter={8}>
|
||||
|
||||
<Col span={6}>
|
||||
<Card size="small" title="数据列表配置" extra={<a >More</a>} style={{ width: 300 }}>
|
||||
<p>全局黑白名单数据的配置。。。</p>
|
||||
<p> </p>
|
||||
<Link >进入配置</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
<Card title="待开发" extra={<a >More</a>} style={{ width: 300 }}>
|
||||
<p>待开发。。。</p>
|
||||
<p> </p>
|
||||
<Link >进入配置</Link>
|
||||
</Card>
|
||||
</Col>
|
||||
<Col span={6} />
|
||||
|
||||
<Col span={6} />
|
||||
|
||||
</Row>
|
||||
<Row>
|
||||
|
||||
</Row>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,280 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb, Menu, Icon, Form, Upload, Input, Select, Card, Row, Col,Button, Tooltip, Tag} from 'antd';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class LearningConfig extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
destField:'',
|
||||
label:'',
|
||||
sourceField:'',
|
||||
sourceLabel:'',
|
||||
plugin:'Tensorflow',
|
||||
status:1,
|
||||
args:'',
|
||||
reqType:'GET',
|
||||
configJson:'',
|
||||
tags: ['x=1', 'y=2', 'z=3'],
|
||||
tags2: ['指标1', '指标2', '指标3'],
|
||||
inputVisible: false,
|
||||
inputVisible2: false,
|
||||
inputValue: '',
|
||||
inputValue2: '',
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleClose = (removedTag) => {
|
||||
const tags = this.state.tags.filter(tag => tag !== removedTag);
|
||||
console.log(tags);
|
||||
this.setState({ tags });
|
||||
}
|
||||
|
||||
showInput = () => {
|
||||
this.setState({ inputVisible: true }, () => this.input.focus());
|
||||
}
|
||||
|
||||
showInput2 = () => {
|
||||
this.setState({ inputVisible2: true }, () => this.input.focus());
|
||||
}
|
||||
|
||||
handleInputChange = (e) => {
|
||||
this.setState({ inputValue: e.target.value });
|
||||
}
|
||||
|
||||
handleInputChange2 = (e) => {
|
||||
this.setState({ inputValue2: e.target.value });
|
||||
}
|
||||
|
||||
handleInputConfirm = () => {
|
||||
const state = this.state;
|
||||
const inputValue = state.inputValue;
|
||||
let tags = state.tags;
|
||||
if (inputValue && tags.indexOf(inputValue) === -1) {
|
||||
tags = [...tags, inputValue];
|
||||
}
|
||||
console.log(tags);
|
||||
this.setState({
|
||||
tags,
|
||||
inputVisible: false,
|
||||
inputValue: '',
|
||||
});
|
||||
}
|
||||
|
||||
handleInputConfirm2 = () => {
|
||||
const state = this.state;
|
||||
const inputValue2 = state.inputValue2;
|
||||
let tags2 = state.tags2;
|
||||
if (inputValue2 && tags2.indexOf(inputValue2) === -1) {
|
||||
tags2 = [...tags2, inputValue2];
|
||||
}
|
||||
console.log(tags2);
|
||||
this.setState({
|
||||
tags2,
|
||||
inputVisible2: false,
|
||||
inputValue2: '',
|
||||
});
|
||||
}
|
||||
|
||||
saveInputRef = input => this.input = input
|
||||
|
||||
render() {
|
||||
const uploadProps = {
|
||||
name: 'file',
|
||||
data: {"dataListId": ""},
|
||||
action: '/services/v1/common/upload',
|
||||
headers: {
|
||||
"x-auth-token": localStorage.getItem('x-auth-token'),
|
||||
},
|
||||
onChange(info) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
},
|
||||
};
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
let validate={
|
||||
plugin:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
sourceField:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
args:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
const plugin=this.state.plugin;
|
||||
const { tags,tags2, inputVisible, inputValue, inputVisible2, inputValue2 } = this.state;
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>机器学习配置</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="模型名称:" >
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" placeholder="请输入模型名称"/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习模型名称'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="学习框架:" help={validate.plugin.help} validateStatus={validate.plugin.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select >
|
||||
<Option value="Tensorflow">Tensorflow</Option>
|
||||
<Option value="Caffe">Caffe</Option>
|
||||
<Option value="Neuroph">Neuroph</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'支持的机器学习框架类型'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="算法参数:" style={{display:"on"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<div>
|
||||
{tags.map((tag, index) => {
|
||||
const isLongTag = tag.length > 20;
|
||||
const tagElem = (
|
||||
<Tag key={tag} closable={index !== 0} afterClose={() => this.handleClose(tag)}>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</Tag>
|
||||
);
|
||||
return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
|
||||
})}
|
||||
{inputVisible && (
|
||||
<Input
|
||||
ref={this.saveInputRef}
|
||||
type="text"
|
||||
size="small"
|
||||
style={{ width: 78 }}
|
||||
value={inputValue}
|
||||
onChange={this.handleInputChange}
|
||||
onBlur={this.handleInputConfirm}
|
||||
onPressEnter={this.handleInputConfirm}
|
||||
/>
|
||||
)}
|
||||
{!inputVisible && <Button size="small" type="dashed" onClick={this.showInput}>+参数</Button>}
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习模型调用时需要的其它参数'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="特征指标:" style={{display:"on"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<div>
|
||||
{tags2.map((tag, index) => {
|
||||
const isLongTag = tag.length > 20;
|
||||
const tagElem = (
|
||||
<Tag key={tag} closable={index !== 0} afterClose={() => this.handleClose(tag)}>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</Tag>
|
||||
);
|
||||
return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
|
||||
})}
|
||||
{inputVisible2 && (
|
||||
<Input
|
||||
ref={this.saveInputRef}
|
||||
type="text"
|
||||
size="small"
|
||||
style={{ width: 78 }}
|
||||
value={inputValue2}
|
||||
onChange={this.handleInputChange2}
|
||||
onBlur={this.handleInputConfirm2}
|
||||
onPressEnter={this.handleInputConfirm2}
|
||||
/>
|
||||
)}
|
||||
{!inputVisible2 && <Button size="small" type="dashed" onClick={this.showInput2}>+特征</Button>}
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型需要的特征指标描叙,模型计算依赖的数据'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="模型文件">
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Upload accept={'.zip'}>
|
||||
<Button>
|
||||
<Icon type="upload" /> 点击上传
|
||||
</Button>
|
||||
</Upload>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习训练后的文件'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="描叙信息" style={{display:"on"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="configJson" rows={4} placeholder="模型描叙信息。" />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型描叙信息。'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import AddDataList from './modal/AddDataList';
|
||||
import EditDataList from './modal/EditDataList';
|
||||
import EditDataListMeta from './modal/EditDataListMeta';
|
||||
|
||||
export default class Datalist extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
name:'',
|
||||
label:'',
|
||||
listType:'',
|
||||
status:1,
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.params.id;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
param.listType=this.state.listType;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/datalist','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deleteModel=(id)=>{
|
||||
FetchUtil('/datalist/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
message.info('删除成功!');
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '列表名',
|
||||
dataIndex: 'label'
|
||||
}, {
|
||||
title: '备注',
|
||||
dataIndex: 'comment'
|
||||
},{
|
||||
title: '名单类型',
|
||||
dataIndex: 'listType'
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
<EditDataList modelId={this.props.params.id} row={r} reload={this.fetchTableData}/>
|
||||
<span className="ant-divider"></span>
|
||||
<EditDataListMeta modelId={this.props.params.id} row={r}/>
|
||||
<span className="ant-divider"></span>
|
||||
<Tooltip title="管理黑/白名单内容"><Link to={"/datalistRecord/"+this.props.params.id+"/"+r.id}>管理内容</Link></Tooltip>
|
||||
<span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该模型吗?'} onConfirm={this.deleteModel.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="列表名:">
|
||||
<Input value={this.state.name} name="name" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<AddDataList modelId={this.props.params.id} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData.filter((item,index,array)=>{
|
||||
var reg = new RegExp('('+ this.state.name+')','gi');
|
||||
if(this.state.name){
|
||||
return (reg.test(item.label));
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
})}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Modal} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
import AddDataListRecord from './modal/AddDataListRecord';
|
||||
import EditDataListRecord from './modal/EditDataListRecord';
|
||||
|
||||
export default class DatalistRecord extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
pageSize:30,
|
||||
|
||||
metaList:[],
|
||||
|
||||
loading:true,
|
||||
|
||||
}
|
||||
|
||||
FetchUtil('/datalistmeta/list/'+this.props.params.datalistId,'GET','',
|
||||
(data) => {
|
||||
if(data.data.list.length==0){
|
||||
Modal.warning({
|
||||
title: '警告',
|
||||
content: '黑/白名单字段未定义,请前往上级菜单点击管理字段按钮进行管理。点击按钮返回',
|
||||
maskClosable:false,
|
||||
onOk:this.handleRedirect
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
metaList:data.data.list
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=20;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.dataListId=this.props.params.datalistId;
|
||||
|
||||
FetchUtil('/datalistrecord','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({
|
||||
loading:false,
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum
|
||||
});
|
||||
if(data.data.page.rowCount > 9990){
|
||||
this.setState({
|
||||
rowCount:9990
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deleteModel=(id)=>{
|
||||
FetchUtil('/datalistrecord/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
message.info('删除成功!');
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
|
||||
handleRedirect=()=>{
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
render(){
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: 'No.',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: 'Data Record',
|
||||
dataIndex: 'dataRecord'
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
<EditDataListRecord metaList={this.state.metaList} dataListId={this.props.params.datalistId} row={r} reload={this.fetchTableData}/>
|
||||
<span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该模型吗?'} onConfirm={this.deleteModel.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<AddDataListRecord metaList={this.state.metaList} dataListId={this.props.params.datalistId} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} defaultPageSize={this.state.pageSize} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddDataList extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
name:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
listType:'',
|
||||
status:"1",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true,
|
||||
|
||||
name:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
listType:'',
|
||||
status:"1",
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.modelId=this.props.modelId;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
param.comment=this.state.comment;
|
||||
param.listType=this.state.listType;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/datalist/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
listType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入列表名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.listType){
|
||||
validate.listType.help='请选择名单类型';
|
||||
validate.listType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem {...formItemLayout} label="列表名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'列表显示名称,一般为中文,如"注册手机黑名单"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="备注:">
|
||||
<Input type="text" name="comment" value={this.state.comment} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="名单类型:" help={validate.listType.help} validateStatus={validate.listType.status}>
|
||||
<Select value={this.state.listType} style={{ width: 120 }} onChange={this.handleSelect.bind(this,'listType')}>
|
||||
<Option value="">请选择</Option>
|
||||
<Option value="BLACK">黑名单</Option>
|
||||
<Option value="WHITE">白名单</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,Upload, message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddDataListRecord extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
importVisible: false,
|
||||
dataRecord:'',
|
||||
fieldNum:this.props.metaList.length
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
console.log(this.props);
|
||||
}
|
||||
|
||||
handleChange=(index,e)=>{
|
||||
var value=e.target.value;
|
||||
var valueArr=this.state.dataRecord.split(',');
|
||||
if(valueArr.length<this.state.fieldNum){
|
||||
var newArr=new Array(this.state.fieldNum);
|
||||
for(var i=0;i<this.state.fieldNum;i++){
|
||||
newArr[i]=valueArr[i]!=undefined?valueArr[i]:'';
|
||||
}
|
||||
|
||||
valueArr=newArr;
|
||||
}
|
||||
|
||||
valueArr[index]=trim(value);
|
||||
this.setState({
|
||||
dataRecord:valueArr.join(',')
|
||||
});
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
dataRecord: '',
|
||||
visible: true
|
||||
})
|
||||
}
|
||||
|
||||
showModal2=()=>{
|
||||
this.setState({
|
||||
|
||||
importVisible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=()=>{
|
||||
var param={};
|
||||
param.dataListId=this.props.dataListId;
|
||||
param.dataRecord=this.state.dataRecord;
|
||||
|
||||
FetchUtil('/datalistrecord/','PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
handleCancel2=()=>{
|
||||
this.setState({
|
||||
importVisible:false
|
||||
})
|
||||
}
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
const uploadProps = {
|
||||
name: 'file',
|
||||
data: {"dataListId": this.props.dataListId},
|
||||
action: '/services/v1/datalistrecord/batchImportDataRecord',
|
||||
headers: {
|
||||
"x-auth-token": localStorage.getItem('x-auth-token'),
|
||||
},
|
||||
onChange(info) {
|
||||
if (info.file.status !== 'uploading') {
|
||||
console.log(info.file, info.fileList);
|
||||
}
|
||||
if (info.file.status === 'done') {
|
||||
message.success(`${info.file.name} file uploaded successfully`);
|
||||
} else if (info.file.status === 'error') {
|
||||
message.error(`${info.file.name} file upload failed.`);
|
||||
}
|
||||
},
|
||||
};
|
||||
let valueArr=this.state.dataRecord.split(',');
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
<Button onClick={this.showModal2} type="primary">导入数据</Button>
|
||||
<span> </span> <a href="/res/dataRecord_temp.xlsx">下载数据模板</a>
|
||||
<Modal title="新增记录" visible={this.state.visible} onOk={this.handleSubmit} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
{this.props.metaList.map(function(info,i){
|
||||
return (
|
||||
<FormItem {...formItemLayout} key={'meta'+info.id} label={info.label}>
|
||||
<Input type="text" value={valueArr[i]} onChange={this.handleChange.bind(this,i)}/>
|
||||
</FormItem>
|
||||
);
|
||||
}.bind(this))}
|
||||
</Form>
|
||||
</Modal>
|
||||
<Modal title="导入数据" visible={this.state.importVisible} onCancel={this.handleCancel2} onOk={this.handleCancel2}>
|
||||
<Upload {...uploadProps}>
|
||||
<Button>
|
||||
<Icon type="upload" /> Click to Upload
|
||||
</Button>
|
||||
</Upload>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditDataList extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
name:'',
|
||||
label:'',
|
||||
comment:'',
|
||||
listType:'',
|
||||
status:"1",
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/datalist/'+this.props.row.id,'GET','',
|
||||
(data) => {
|
||||
const datalist=data.data.datalist;
|
||||
this.setState({
|
||||
name:datalist.name,
|
||||
label:datalist.label,
|
||||
comment:datalist.comment,
|
||||
listType:datalist.listType,
|
||||
status:datalist.status+""
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.modelId=this.props.modelId;
|
||||
param.name=this.state.name;
|
||||
param.label=this.state.label;
|
||||
param.comment=this.state.comment;
|
||||
param.listType=this.state.listType;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/datalist/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('修改成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
listType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入列表名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.listType){
|
||||
validate.listType.help='请选择名单类型';
|
||||
validate.listType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem {...formItemLayout} label="列表名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'列表显示名称,一般为中文,如"注册手机黑名单"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="备注:">
|
||||
<Input type="text" name="comment" value={this.state.comment} onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="名单类型:" help={validate.listType.help} validateStatus={validate.listType.status}>
|
||||
<Select value={this.state.listType} style={{ width: 120 }} onChange={this.handleSelect.bind(this,'listType')}>
|
||||
<Option value="">请选择</Option>
|
||||
<Option value="BLACK">黑名单</Option>
|
||||
<Option value="WHITE">白名单</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="状态:">
|
||||
<Select value={this.state.status} name="status" style={{ width: 120 }} onChange={this.handleSelect.bind(this,'status')}>
|
||||
<Option value="1">正常</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,176 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
const OptGroup = Select.OptGroup;
|
||||
const InputGroup = Input.Group;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditDataListMeta extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
metaList:[],
|
||||
initialList:[]
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/datalistmeta/list/'+this.props.row.id,'GET','',
|
||||
(data) => {
|
||||
let initialData = data.data.list.map((item)=>{
|
||||
return item.label
|
||||
});
|
||||
this.setState({
|
||||
metaList:data.data.list,
|
||||
initialList:initialData
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(index,e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
|
||||
var metaList=this.state.metaList;
|
||||
metaList[index][name]=trim(value);
|
||||
this.setState({
|
||||
metaList:metaList
|
||||
});
|
||||
}
|
||||
|
||||
addField=()=>{
|
||||
let metaList=this.state.metaList;
|
||||
metaList.push({
|
||||
dataListId:this.props.row.id,
|
||||
fieldName:'',
|
||||
label:'',
|
||||
seqNum:1
|
||||
});
|
||||
this.setState({
|
||||
metaList:metaList
|
||||
})
|
||||
}
|
||||
|
||||
deleteField=(index)=>{
|
||||
let metaList=this.state.metaList;
|
||||
metaList.splice(index,1);
|
||||
this.setState({
|
||||
metaList:metaList
|
||||
})
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=()=>{
|
||||
let labelIsNull = this.state.metaList.some((item)=>{
|
||||
if(!item.label){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
let labelIsChange = this.state.metaList.some((item,index,array)=>{
|
||||
if( (array.length > this.state.initialList.length) || (item.label !== this.state.initialList[index]) ){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,10}$/;
|
||||
let labelReg = this.state.metaList.every((item,index,array)=>{
|
||||
if(reg.test(item.label)){
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if(this.state.metaList.length==0){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请添加至少一个字段'
|
||||
});
|
||||
return false;
|
||||
}else if(labelIsNull){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '字段名不能为空!'
|
||||
});
|
||||
return false;
|
||||
}else if(!labelReg){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '字段名含有特殊字符,或者字符长度不符合!'
|
||||
});
|
||||
return false;
|
||||
}else if(labelIsChange){
|
||||
FetchUtil('/datalistmeta/','PUT',JSON.stringify(this.state.metaList),
|
||||
(data) => {
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="管理黑/白名单字段" onClick={this.showModal}><a>管理字段</a></Tooltip>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit} onCancel={this.handleCancel}>
|
||||
<Row>
|
||||
{this.state.initialList.length ?'':<Col span={6} offset={10}>
|
||||
<span className="addRule" style={{display:"block",marginBottom:10}} onClick={this.addField}><Icon type="plus" /> 添加字段</span>
|
||||
</Col>
|
||||
}
|
||||
{this.state.initialList.length ?<Col span={25} offset={2} style={{fontSize:14,marginBottom:10,color:'#f00'}}><span >现有字段不能删除,若需要删除字段,则建议直接删除列表!</span></Col>:<Col span={1} offset={1}>
|
||||
<Tooltip placement="right" title={'现有字段不能删除,若需要删除字段,则建议直接删除列表!'}>
|
||||
<Icon style={{fontSize:16,marginBottom:10}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>}
|
||||
</Row>
|
||||
<Form horizontal form={this.props.form}>
|
||||
{this.state.metaList.map(function(info,i){
|
||||
return (
|
||||
<FormItem key={i+'meta'} label='字段名' labelCol={{span:10}}>
|
||||
<Col span={4} offset={1}>
|
||||
<Input name="label" value={info.label} placeholder={'字段名'} onChange={this.handleChange.bind(this,i)}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段名,一般为中文,如"手机号码",2-10位可由中文、英文字母、数字、下划线的组合'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
<Col span={1} offset={1}>
|
||||
<i onClick={this.deleteField.bind(this,i)} className="fa fa-trash" style={{fontSize:16}}/>
|
||||
</Col>
|
||||
</FormItem>
|
||||
);
|
||||
}.bind(this))}
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditDataListRecord extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
dataRecord:this.props.row.dataRecord,
|
||||
fieldNum:this.props.metaList.length
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(index,e)=>{
|
||||
var value=e.target.value;
|
||||
var valueArr=this.state.dataRecord.split(',');
|
||||
if(valueArr.length<this.state.fieldNum){
|
||||
var newArr=new Array(this.state.fieldNum);
|
||||
for(var i=0;i<this.state.fieldNum;i++){
|
||||
newArr[i]=valueArr[i]!=undefined?valueArr[i]:'';
|
||||
}
|
||||
|
||||
valueArr=newArr;
|
||||
}
|
||||
|
||||
valueArr[index]=trim(value);
|
||||
this.setState({
|
||||
dataRecord:valueArr.join(',')
|
||||
});
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=()=>{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.dataListId=this.props.dataListId;
|
||||
param.dataRecord=this.state.dataRecord;
|
||||
|
||||
FetchUtil('/datalistrecord/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
let valueArr=this.state.dataRecord.split(',');
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑记录" visible={this.state.visible} onOk={this.handleSubmit} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
{this.props.metaList.map(function(info,i){
|
||||
return (
|
||||
<FormItem {...formItemLayout} key={'meta'+info.id} label={info.label}>
|
||||
<Input type="text" value={valueArr[i]} onChange={this.handleChange.bind(this,i)}/>
|
||||
</FormItem>
|
||||
);
|
||||
}.bind(this))}
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Menu,Icon} from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const SubMenu = Menu.SubMenu;
|
||||
const MenuItemGroup = Menu.ItemGroup;
|
||||
|
||||
import AddField from './modal/AddField';
|
||||
import EditField from './modal/EditField';
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class Field extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
fieldName:'',
|
||||
label:'',
|
||||
fieldType:'',
|
||||
indexedState:'',
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.params.id;
|
||||
param.fieldName=this.state.fieldName;
|
||||
param.label=this.state.label;
|
||||
param.fieldType=this.state.fieldType;
|
||||
|
||||
FetchUtil('/field','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
let indexedAll = data.data.page.list;
|
||||
let num = 0;
|
||||
let sum = indexedAll.reduce((pre,cur,index,array)=>{
|
||||
let preNum =pre.indexed ? 1 : 0;
|
||||
num += preNum ;
|
||||
return (num += array[index].indexed);
|
||||
});
|
||||
//console.log(sum);
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount,
|
||||
indexedAll:sum
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deleteModel=(id)=>{
|
||||
FetchUtil('/field/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
message.info('删除成功!');
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '字段名',
|
||||
dataIndex: 'fieldName'
|
||||
},
|
||||
{
|
||||
title: '显示名称',
|
||||
dataIndex: 'label'
|
||||
},
|
||||
{
|
||||
title: '字段类型',
|
||||
dataIndex: 'fieldType',
|
||||
render:(t)=>{
|
||||
switch(t){
|
||||
case 'STRING': return '字符串';
|
||||
case 'INTEGER': return '整型';
|
||||
case 'LONG': return '长整型';
|
||||
case 'DOUBLE': return '浮点型';
|
||||
default: return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '是否索引',
|
||||
dataIndex: 'indexed',
|
||||
render:(t)=>{
|
||||
if(t){
|
||||
return '是';
|
||||
}else {
|
||||
return '否'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
<EditField modelId={this.props.params.id} indexedAll={this.state.indexedAll} row={r} reload={this.fetchTableData}/>
|
||||
<span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该字段吗?'} onConfirm={this.deleteModel.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="字段名:">
|
||||
<Input value={this.state.fieldName} name="fieldName" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<AddField modelId={this.props.params.id} indexedAll={this.state.indexedAll} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData.filter((item,index,array)=>{
|
||||
var reg = new RegExp('('+ this.state.fieldName+')','gi');
|
||||
if(this.state.fieldName){
|
||||
return (reg.test(item.label));
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
})}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddField extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
fieldName:'',
|
||||
label:'',
|
||||
fieldType:'',
|
||||
indexed:false,
|
||||
|
||||
fieldTypes:[]
|
||||
}
|
||||
|
||||
FetchUtil('/common/fieldtypes','GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldTypes:data.data.fields
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
onCheck=(e)=>{
|
||||
if(e.target.checked && this.props.indexedAll>=8){
|
||||
Modal.warning({
|
||||
title: '提示信息',
|
||||
content: '索引已超过8项!',
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
indexed:e.target.checked
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true,
|
||||
|
||||
fieldName:'',
|
||||
label:'',
|
||||
fieldType:''
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param = {};
|
||||
param.modelId = this.props.modelId;
|
||||
param.fieldName = this.state.fieldName;
|
||||
param.label = this.state.label;
|
||||
param.fieldType = this.state.fieldType;
|
||||
param.indexed = this.state.indexed;
|
||||
|
||||
FetchUtil('/field/', 'PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
if (data.success) {
|
||||
message.success('添加成功');
|
||||
} else {
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
fieldName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
fieldType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.fieldName){
|
||||
validate.fieldName.help='请输入字段名';
|
||||
validate.fieldName.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let fieldName = this.state.fieldName;
|
||||
if(!reg.test(fieldName)){
|
||||
validate.fieldName.help='按照提示输入正确的字段名';
|
||||
validate.fieldName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入显示名称';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.fieldType){
|
||||
validate.fieldType.help='请选择字段类型';
|
||||
validate.fieldType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
<Modal title="新建字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="字段名:" help={validate.fieldName.help} validateStatus={validate.fieldName.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="fieldName" value={this.state.fieldName} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'2-30位英文字母、数字、下划线的组合,以英文字母开头,如"deviceId"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="显示名称:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段显示名称,一般为中文,如"设备ID"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="字段类型:" help={validate.fieldType.help} validateStatus={validate.fieldType.status}>
|
||||
<Row>
|
||||
<Col span={10}>
|
||||
<Select value={this.state.fieldType} onChange={this.handleSelect.bind(this,'fieldType')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.state.fieldTypes.map(x=><Option key={x.name} value={x.name}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段类型,目前有四种类型,分别为字符串(如"你好","abc"等),整数(其范围为 -2147483648 到 2147483647 之间),长整数(其范围为 -9223372036854775808 到 9223372036854775807 之间),浮点数(如 3.14)。'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem {...formItemLayout} label="是否索引:">
|
||||
<Row>
|
||||
<Col span={1}>
|
||||
<Checkbox checked={this.state.indexed} onChange={this.onCheck}></Checkbox>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果勾选,则为该字段创建索引'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditField extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
fieldName:'',
|
||||
label:'',
|
||||
fieldType:'',
|
||||
|
||||
fieldTypes:[],
|
||||
indexed:false
|
||||
}
|
||||
|
||||
FetchUtil('/common/fieldtypes','GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldTypes:data.data.fields
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/field/'+this.props.row.id,'GET','',
|
||||
(data) => {
|
||||
const field=data.data.field;
|
||||
this.setState({
|
||||
fieldName:field.fieldName,
|
||||
label:field.label,
|
||||
fieldType:field.fieldType,
|
||||
indexed:field.indexed
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
onCheck=(e)=>{
|
||||
if(e.target.checked && this.props.indexedAll>=8){
|
||||
Modal.warning({
|
||||
title: '提示信息',
|
||||
content: '索引已超过8项!',
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
indexed:e.target.checked
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param = {};
|
||||
param.id = this.props.row.id;
|
||||
param.modelId = this.props.modelId;
|
||||
param.fieldName = this.state.fieldName;
|
||||
param.label = this.state.label;
|
||||
param.fieldType = this.state.fieldType;
|
||||
param.indexed = this.state.indexed;
|
||||
|
||||
FetchUtil('/field/', 'PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
if (data.success) {
|
||||
message.success('修改成功');
|
||||
} else {
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
fieldName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
fieldType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.fieldName){
|
||||
validate.fieldName.help='请输入字段名';
|
||||
validate.fieldName.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let fieldName = this.state.fieldName;
|
||||
if(!reg.test(fieldName)){
|
||||
validate.fieldName.help='按照提示输入正确的字段名';
|
||||
validate.fieldName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入显示名称';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.fieldType){
|
||||
validate.fieldType.help='请选择字段类型';
|
||||
validate.fieldType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="字段名:" help={validate.fieldName.help} validateStatus={validate.fieldName.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="fieldName" value={this.state.fieldName} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'2-30位英文字母、数字、下划线的组合,以英文字母开头,如"deviceId"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="显示名称:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段显示名称,一般为中文,如"设备ID"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="字段类型:" help={validate.fieldType.help} validateStatus={validate.fieldType.status}>
|
||||
<Row>
|
||||
<Col span={10}>
|
||||
<Select value={this.state.fieldType} onChange={this.handleSelect.bind(this,'fieldType')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.state.fieldTypes.map(x=><Option key={x.name} value={x.name}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段类型,目前有四种类型,分别为字符串(如"你好","abc"等),整数(其范围为 -2147483648 到 2147483647 之间),长整数(其范围为 -9223372036854775808 到 9223372036854775807 之间),浮点数(如 3.14)'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem {...formItemLayout} label="是否索引:">
|
||||
<Row>
|
||||
<Col span={1}>
|
||||
<Checkbox checked={this.state.indexed} onChange={this.onCheck}></Checkbox>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'如果勾选,则为该字段创建索引'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Switch,Modal,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Menu,Icon} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
import moment from 'moment';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
const SubMenu = Menu.SubMenu;
|
||||
const MenuItemGroup = Menu.ItemGroup;
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class Model extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
model:null,
|
||||
|
||||
current:'',
|
||||
disable: false,
|
||||
visible: false
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchData=()=>{
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data)=>{
|
||||
if(data.data.model.status === 1){
|
||||
this.setState({
|
||||
checked:true,
|
||||
disable:true
|
||||
});
|
||||
}else if(data.data.model.status === 2){
|
||||
this.setState({
|
||||
checked:false,
|
||||
disable:true
|
||||
});
|
||||
}else if(data.data.model.status === 0){
|
||||
this.setState({
|
||||
checked:false,
|
||||
disable:false
|
||||
});
|
||||
}
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
model:data.data.model
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
let key='';
|
||||
switch(this.props.location.pathname.split('/')[1]){
|
||||
case 'field':
|
||||
key='field';break;
|
||||
case 'preItem':
|
||||
key='preItem';break;
|
||||
case 'datalist':
|
||||
case 'datalistRecord':
|
||||
key='datalist';break;
|
||||
case 'abstractionList':
|
||||
key='abstractionList';break;
|
||||
case 'activation':
|
||||
case 'ruleList':
|
||||
case 'historyRecordList':
|
||||
key='activation';break;
|
||||
case 'modelConfig':
|
||||
key='modelConfig';break;
|
||||
}
|
||||
this.setState({
|
||||
current:key
|
||||
});
|
||||
this.fetchData();
|
||||
}
|
||||
|
||||
handleClick=(e)=>{
|
||||
window.location.href='/#/'+e.key+'/'+this.props.params.id;
|
||||
this.setState({
|
||||
current:e.key
|
||||
})
|
||||
};
|
||||
|
||||
handleBuild=()=>{
|
||||
this.setState({
|
||||
visible: true
|
||||
});
|
||||
var _self = this;
|
||||
let paramsId = this.props.params.id;
|
||||
//var success = false;
|
||||
confirm({
|
||||
title: '是否重新构建模型?',
|
||||
content: '确认重新构建模型将清空历史数据!',
|
||||
onOk() {
|
||||
FetchUtil('/model/build/'+paramsId,'POST','',
|
||||
(data)=>{
|
||||
console.log(data);
|
||||
if(!data.success){
|
||||
Modal.error({
|
||||
title: '构建状态',
|
||||
content: data.msg,
|
||||
});
|
||||
//alert(data.msg);
|
||||
}else {
|
||||
Modal.success({
|
||||
title: '构建状态',
|
||||
content: '构建成功!',
|
||||
});
|
||||
_self.setState({
|
||||
checked:true,
|
||||
disable:true
|
||||
});
|
||||
|
||||
console.log(_self);
|
||||
}
|
||||
});
|
||||
},
|
||||
onCancel() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
onChange=()=>{
|
||||
this.setState({
|
||||
checked: !this.state.checked,
|
||||
});
|
||||
|
||||
if(!this.state.checked){
|
||||
FetchUtil('/model/enable/'+this.props.params.id,'POST','',
|
||||
(data)=>{
|
||||
console.log(data);
|
||||
if(!data.success){
|
||||
alert(data.msg);
|
||||
}
|
||||
});
|
||||
}else {
|
||||
FetchUtil('/model/disable/'+this.props.params.id,'POST','',
|
||||
(data)=>{
|
||||
console.log(data);
|
||||
if(!data.success){
|
||||
alert(data.msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>{this.state.model==null?'':<Link to={"/model/"+this.state.model.id}>模型"{this.state.model.label}"</Link>}</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
<div style={{lineHeight:"46px",padding:"0 20px 0",margin:"0 24px",borderBottom:"1px solid #e9e9e9"}}>
|
||||
{this.state.model==null?'':<span style={{marginRight:20}}>模型:"{this.state.model.label}"</span>}
|
||||
{this.state.model==null?'':<span style={{marginRight:20}}>模型创建时间:{moment(this.state.model.createTime).format('YYYY-MM-DD HH:mm:ss')}</span>}
|
||||
{this.state.disable===false?'':<Switch checkedChildren={'开'} unCheckedChildren={'关'} defaultChecked={this.state.checked} checked={this.state.checked} disabled={this.state.disabled} onChange={this.onChange} />}
|
||||
<Button type="primary" onClick={this.handleBuild} style={{float:"right",marginTop:9}}>构建模型</Button>
|
||||
</div>
|
||||
<div className="ant-layout-header" style={{padding:"0 24px 24px"}}>
|
||||
|
||||
<Menu onClick={this.handleClick}
|
||||
selectedKeys={[this.state.current]}
|
||||
mode="horizontal"
|
||||
>
|
||||
<Menu.Item key="field">
|
||||
<Icon type="file-text" />字段管理
|
||||
</Menu.Item>
|
||||
<Menu.Item key="preItem">
|
||||
<Icon type="copy" />预处理管理
|
||||
</Menu.Item>
|
||||
<Menu.Item key="datalist">
|
||||
<Icon type="appstore" />黑/白名单管理
|
||||
</Menu.Item>
|
||||
<Menu.Item key="abstractionList">
|
||||
<Icon type="picture" />抽象处理
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="modelConfig">
|
||||
<Icon type="setting" />机器学习配置
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item key="activation">
|
||||
<Icon type="solution" />策略管理
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#header {
|
||||
margin-bottom: 10px;
|
||||
padding: 10px 0;
|
||||
padding-left: 20px;
|
||||
background: #ECECEC;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
i{
|
||||
cursor:pointer
|
||||
}
|
||||
@@ -1,225 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message,Modal,Icon} from 'antd';
|
||||
import { Link } from 'react-router';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import AddModel from './modal/AddModel';
|
||||
import EditModel from './modal/EditModel';
|
||||
import StaticField from './modal/StaticField';
|
||||
import CopyModel from './modal/CopyModel';
|
||||
|
||||
import './Model.less';
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class ModelList extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
modelName:'',
|
||||
status:"1",
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.label=this.state.modelName;
|
||||
//param.status=this.state.status; 默认查询不传递该参数,否则只有单一数据,不完整
|
||||
|
||||
FetchUtil('/model','POST',JSON.stringify(param),
|
||||
(data)=>{
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
copyModel=(r)=>{
|
||||
var param={};
|
||||
param.id=r.id;
|
||||
param.modelName=r.modelName;
|
||||
param.label=r.label;
|
||||
param.entityName=r.entityName;
|
||||
param.entryName=r.entryName;
|
||||
param.guid=r.guid;
|
||||
param.referenceDate=r.referenceDate;
|
||||
param.status=r.status;
|
||||
FetchUtil('/model/copy','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('复制成功!');
|
||||
}
|
||||
else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.fetchTableData();
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deleteModel=(id)=>{
|
||||
FetchUtil('/model/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('删除成功!');
|
||||
}
|
||||
else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.fetchTableData();
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
let showGuid=function(guid){
|
||||
Modal.info({
|
||||
title: '通过接口上传请携带此参数',
|
||||
content: 'guid:'+guid,
|
||||
});
|
||||
}
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '模型名',
|
||||
dataIndex: 'label'
|
||||
},
|
||||
{
|
||||
title: '实体名',
|
||||
dataIndex: 'entityName'
|
||||
}, {
|
||||
title: '事件ID',
|
||||
dataIndex: 'entryName'
|
||||
}, {
|
||||
title: '唯一标识',
|
||||
dataIndex: 'guid',
|
||||
render:(t,r,i)=>{
|
||||
return <a onClick={showGuid.bind(this,r.guid)}>查看</a>;
|
||||
}
|
||||
},{
|
||||
title: '事件时间',
|
||||
dataIndex: 'referenceDate'
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
{r.entityName?
|
||||
<Tooltip title="进入模型"><Link to={"/field/"+r.id}>进入模型</Link></Tooltip>
|
||||
:
|
||||
<StaticField row={r} reload={this.fetchTableData}/>
|
||||
}
|
||||
<span className="ant-divider"></span>
|
||||
{r.entityName?
|
||||
<CopyModel tData={this.state.tData} row={r} reload={this.fetchTableData}/>
|
||||
:
|
||||
''
|
||||
}
|
||||
{r.entityName?<span className="ant-divider"></span>:''}
|
||||
|
||||
<EditModel tData={this.state.tData} row={r} reload={this.fetchTableData}/><span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该模型吗?'} onConfirm={this.deleteModel.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>模型列表</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form layout="inline">
|
||||
<FormItem label="模型名:">
|
||||
<Input value={this.state.modelName} name="modelName" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<AddModel tData={this.state.tData} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData.filter((item,index,array)=>{
|
||||
let reg = new RegExp('('+ this.state.modelName+')','gi');
|
||||
if(this.state.modelName){
|
||||
return (reg.test(item.label));
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
})}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddModel extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
label:'',
|
||||
|
||||
templateList:[],
|
||||
templateId:''
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var tData = this.props.tData.some((item)=>{
|
||||
if(item.label===e.target.value){
|
||||
return true;
|
||||
};
|
||||
});
|
||||
if(tData){
|
||||
Modal.error({
|
||||
title: '信息提示',
|
||||
content: '模型名重复',
|
||||
});
|
||||
}
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true,
|
||||
label:'',
|
||||
});
|
||||
FetchUtil('/model/list/template','GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
templateList:data.data.modelList
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else if(this.state.templateId !="-999"){
|
||||
var param={};
|
||||
param.id=this.state.templateId;
|
||||
param.modelName='';
|
||||
param.label=this.state.label;
|
||||
param.entityName='';
|
||||
param.entryName='';
|
||||
param.referenceDate='';
|
||||
|
||||
FetchUtil('/model/copy','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.modelName='';
|
||||
param.label=this.state.label;
|
||||
param.entityName='';
|
||||
param.entryName='';
|
||||
param.referenceDate='';
|
||||
|
||||
FetchUtil('/model/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入模型名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的模型名';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新建模型</Button>
|
||||
<Modal title="编辑模型" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="模型名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型显示名称,一般为中文,如"注册模型"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="模板:">
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select value={this.state.templateId} onChange={this.handleSelect.bind(this,'templateId')}>
|
||||
|
||||
{
|
||||
this.state.templateList.map((info,index)=>{
|
||||
return <Option key={index} value={info.id+''}>{'[系统]'+info.label}</Option>
|
||||
})
|
||||
}
|
||||
<Option value="-999">新建模型</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'建议使用模板一键创建模型,熟悉后可自行创建模型'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,146 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class CopyModel extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
modelName:'',
|
||||
label:'',
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var tData = this.props.tData.some((item)=>{
|
||||
if(item.label===e.target.value){
|
||||
return true;
|
||||
};
|
||||
});
|
||||
if(tData){
|
||||
Modal.error({
|
||||
title: '信息提示',
|
||||
content: '模型名重复',
|
||||
});
|
||||
}
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true,
|
||||
|
||||
modelName:'',
|
||||
label:'',
|
||||
});
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.modelName='';
|
||||
param.label=this.state.label;
|
||||
|
||||
FetchUtil('/model/copy','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('复制成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入模型名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的模型名';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="复制模型" onClick={this.showModal}><a>复制</a></Tooltip>
|
||||
<Modal title="复制模型" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem {...formItemLayout} label="复制模型:">
|
||||
<label>{this.props.row.label}</label>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="新模型名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型显示名称,一般为中文,如"注册模型"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const createForm = Form.create;
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditModel extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
modelName:'',
|
||||
label:'',
|
||||
entityName:'',
|
||||
entryName:'',
|
||||
guid:'',
|
||||
referenceDate:'',
|
||||
status:'',
|
||||
}
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/model/'+this.props.row.id,'GET',null,
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
modelName:model.modelName,
|
||||
label:model.label,
|
||||
entityName:model.entityName,
|
||||
entryName:model.entryName,
|
||||
guid:model.guid,
|
||||
referenceDate:model.referenceDate,
|
||||
status:model.status+''
|
||||
});
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var tData = this.props.tData.some((item)=>{
|
||||
if(item.label===e.target.value){
|
||||
return true;
|
||||
};
|
||||
});
|
||||
if(tData){
|
||||
Modal.error({
|
||||
title: '信息提示',
|
||||
content: '模型名重复',
|
||||
});
|
||||
}
|
||||
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.modelName=this.state.modelName;
|
||||
param.label=this.state.label;
|
||||
param.entityName=this.state.entityName;
|
||||
param.entryName=this.state.entryName;
|
||||
param.guid=this.state.guid;
|
||||
param.referenceDate=this.state.referenceDate;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/model/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('修改成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入模型名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的模型名';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑模型" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="模型名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型显示名称,一般为中文,如"注册模型"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,402 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class StaticField extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
entityName:'',
|
||||
entityType:'',
|
||||
entityLabel:'',
|
||||
|
||||
entryName:'',
|
||||
entryType:'',
|
||||
entryLabel:'',
|
||||
|
||||
referenceDate:'',
|
||||
referenceDateType:'LONG',
|
||||
referenceDateLabel:'',
|
||||
|
||||
visible:false,
|
||||
fieldTypes:[]
|
||||
}
|
||||
|
||||
FetchUtil('/common/fieldtypes','GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldTypes:data.data.fields
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true,
|
||||
|
||||
entityName:'',
|
||||
entityType:'',
|
||||
entityLabel:'',
|
||||
entryName:'',
|
||||
entryType:'',
|
||||
entryLabel:'',
|
||||
referenceDate:'',
|
||||
referenceDateType:'LONG',
|
||||
referenceDateLabel:'',
|
||||
})
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
let model=this.props.row;
|
||||
model.entityName=this.state.entityName;
|
||||
model.entryName=this.state.entryName;
|
||||
model.referenceDate=this.state.referenceDate;
|
||||
|
||||
FetchUtil('/model/','PUT',JSON.stringify(model),
|
||||
(data) => {
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
|
||||
var entity={};
|
||||
entity.modelId=this.props.row.id;
|
||||
entity.fieldName=this.state.entityName;
|
||||
entity.label=this.state.entityLabel;
|
||||
entity.fieldType=this.state.entityType;
|
||||
entity.indexed=true;
|
||||
FetchUtil('/field/','PUT',JSON.stringify(entity),() => {});
|
||||
|
||||
var entry={};
|
||||
entry.modelId=this.props.row.id;
|
||||
entry.fieldName=this.state.entryName;
|
||||
entry.label=this.state.entryLabel;
|
||||
entry.fieldType=this.state.entryType;
|
||||
entry.indexed=true;
|
||||
FetchUtil('/field/','PUT',JSON.stringify(entry),() => {});
|
||||
|
||||
var referenceDate={};
|
||||
referenceDate.modelId=this.props.row.id;
|
||||
referenceDate.fieldName=this.state.referenceDate;
|
||||
referenceDate.label=this.state.referenceDateLabel;
|
||||
referenceDate.fieldType=this.state.referenceDateType;
|
||||
referenceDate.indexed=true;
|
||||
FetchUtil('/field/','PUT',JSON.stringify(referenceDate),() => {});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 5 },
|
||||
wrapperCol: { span: 19 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
entityName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
entityLabel:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
entityType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
entryName:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
entryLabel:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
entryType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
referenceDate:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
referenceDateLabel:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.entityName){
|
||||
validate.entityName.help='请输入实体名';
|
||||
validate.entityName.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let entityName = this.state.entityName;
|
||||
if(!reg.test(entityName)){
|
||||
validate.entityName.help='按照提示输入正确的实体名';
|
||||
validate.entityName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.entityLabel){
|
||||
validate.entityLabel.help='请输入实体显示名';
|
||||
validate.entityLabel.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let entityLabel = this.state.entityLabel;
|
||||
if(!reg.test(entityLabel)){
|
||||
validate.entityLabel.help='按照提示输入正确的实体显示名';
|
||||
validate.entityLabel.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.entityType){
|
||||
validate.entityType.help='请选择实体类型';
|
||||
validate.entityType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.entryName){
|
||||
validate.entryName.help='请输入事件ID';
|
||||
validate.entryName.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let entryName = this.state.entryName;
|
||||
if(!reg.test(entryName)){
|
||||
validate.entryName.help='按照提示输入正确的事件ID';
|
||||
validate.entryName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(this.state.entityName&&(this.state.entityName==this.state.entryName)){
|
||||
validate.entryName.help='事件ID不能与实体名相同!';
|
||||
validate.entryName.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.entryLabel){
|
||||
validate.entryLabel.help='请输入事件ID显示名';
|
||||
validate.entryLabel.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let entryLabel = this.state.entryLabel;
|
||||
if(!reg.test(entryLabel)){
|
||||
validate.entryLabel.help='按照提示输入正确的事件ID显示名';
|
||||
validate.entryLabel.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.entryType){
|
||||
validate.entryType.help='请选择事件ID类型';
|
||||
validate.entryType.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(this.state.entityName&&(this.state.entityName==this.state.referenceDate)){
|
||||
validate.referenceDate.help='事件时间不能与实体名相同!';
|
||||
validate.referenceDate.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
if(this.state.entryName&&(this.state.entryName==this.state.referenceDate)){
|
||||
validate.referenceDate.help='事件时间不能与事件ID相同!';
|
||||
validate.referenceDate.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.referenceDate){
|
||||
validate.referenceDate.help='请输入事件时间';
|
||||
validate.referenceDate.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let referenceDate = this.state.referenceDate;
|
||||
if(!reg.test(referenceDate)){
|
||||
validate.referenceDate.help='按照提示输入正确的事件时间';
|
||||
validate.referenceDate.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
if(!this.state.referenceDateLabel){
|
||||
validate.referenceDateLabel.help='请输入事件时间显示名';
|
||||
validate.referenceDateLabel.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let referenceDateLabel = this.state.referenceDateLabel;
|
||||
if(!reg.test(referenceDateLabel)){
|
||||
validate.referenceDateLabel.help='按照提示输入正确的事件时间显示名';
|
||||
validate.referenceDateLabel.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="创建必备字段"><a onClick={this.showModal}>创建必备字段</a></Tooltip>
|
||||
<Modal title="创建必备字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="实体名:" help={validate.entityName.help} validateStatus={validate.entityName.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="entityName" value={this.state.entityName} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型目标实体字段,如"deviceId"(2-30位英文字母、数字、下划线的组合,以英文字母开头)'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="实体显示名:" help={validate.entityLabel.help} validateStatus={validate.entityLabel.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="entityLabel" value={this.state.entityLabel} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型目标实体显示名称,可以输入中文'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="实体类型:" help={validate.entityType.help} validateStatus={validate.entityType.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select size="large" name="entityType" value={this.state.entityType} onChange={this.handleSelect.bind(this,'entityType')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.state.fieldTypes.map(x=><Option key={x.name} value={x.name}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型目标实体类型,请选择类型'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件ID:" help={validate.entryName.help} validateStatus={validate.entryName.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="entryName" value={this.state.entryName} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型时间ID字段,一般为模型主键,如"id"(2-30位英文字母、数字、下划线的组合,以英文字母开头)'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件ID显示:" help={validate.entryLabel.help} validateStatus={validate.entryLabel.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="entryLabel" value={this.state.entryLabel} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型目标实体显示名称,可以输入中文'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件ID类型:" help={validate.entryType.help} validateStatus={validate.entryType.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select size="large" name="entryType" value={this.state.entryType} onChange={this.handleSelect.bind(this,'entryType')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.state.fieldTypes.map(x=><Option key={x.name} value={x.name}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型目标实体类型,请选择类型'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件时间:" help={validate.referenceDate.help} validateStatus={validate.referenceDate.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="referenceDate" value={this.state.referenceDate} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型事件时间字段,如"accessTime"(2-30位英文字母、数字、下划线的组合,以英文字母开头)'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件时间显示:" help={validate.referenceDateLabel.help} validateStatus={validate.referenceDateLabel.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input size="large" style={{marginTop:2}} type="text" name="referenceDateLabel" value={this.state.referenceDateLabel} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型事件时间显示名称,可以输入中文'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="事件时间类型:">
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select disabled size="large" value={this.state.referenceDateType}>
|
||||
<Option value="LONG">长整数</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'事件时间类型,固定为长整数'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,486 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb, Menu, Icon, Form, Upload, Input, Select, Card, Row, Col,Button, Tooltip, Tag, Modal, message} from 'antd';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import EditModelConfParam from './modal/EditModelConfParam';
|
||||
|
||||
export default class ModelConfig extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
id : -1,
|
||||
status:1,
|
||||
args:'',
|
||||
tags: ['argx=1', 'argy=2', 'argz=3'],
|
||||
inputVisible: false,
|
||||
inputValue: '',
|
||||
model: null,
|
||||
modelConfig: null,
|
||||
name: "",
|
||||
type: "TENSOR_DNN",
|
||||
path: "",
|
||||
comment:"",
|
||||
tag: "",
|
||||
operation: "",
|
||||
absColumns: [],
|
||||
selectCols: [],
|
||||
fileList:[],
|
||||
paramsList:[],
|
||||
selectedKeys:[],
|
||||
feed: "",
|
||||
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
|
||||
FetchUtil('/modelConfig/list/' + this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const modelConfig=data.data.modelConfig;
|
||||
let paramVO = modelConfig.params[0];
|
||||
let selectCols = [];
|
||||
selectCols = paramVO.expressions.replace(/abstractions./g,"").split(",");
|
||||
this.setState({
|
||||
modelConfig: modelConfig,
|
||||
id: modelConfig.id,
|
||||
name: modelConfig.name,
|
||||
type: modelConfig.type,
|
||||
path: modelConfig.path,
|
||||
comment: modelConfig.comment,
|
||||
tag: modelConfig.tag,
|
||||
operation: modelConfig.operation,
|
||||
selectCols: selectCols,
|
||||
paramsList: modelConfig.params,
|
||||
fileList: [{
|
||||
uid: -1,
|
||||
name: modelConfig.path,
|
||||
status: 'done',
|
||||
}],
|
||||
feed: paramVO.feed,
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
FetchUtil('/activation/absColumns/' + this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
let absColumns =[];
|
||||
let absDS= data.data.columns;
|
||||
for (let i = 0; i < absDS.length; i++) {
|
||||
absColumns.push(<Option key={absDS[i].value}>{absDS[i].label}</Option>);
|
||||
}
|
||||
//console.log(absColumns);
|
||||
this.setState({
|
||||
absColumns: absColumns,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
handleClose = (removedTag) => {
|
||||
const tags = this.state.tags.filter(tag => tag !== removedTag);
|
||||
console.log(tags);
|
||||
this.setState({ tags });
|
||||
}
|
||||
|
||||
showInput = () => {
|
||||
this.setState({ inputVisible: true }, () => this.input.focus());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// handleInputChange = (e) => {
|
||||
// this.setState({ inputValue: e.target.value });
|
||||
// }
|
||||
|
||||
|
||||
|
||||
handleInputConfirm = () => {
|
||||
const state = this.state;
|
||||
const inputValue = state.inputValue;
|
||||
let tags = state.tags;
|
||||
if (inputValue && tags.indexOf(inputValue) === -1) {
|
||||
tags = [...tags, inputValue];
|
||||
}
|
||||
console.log(tags);
|
||||
this.setState({
|
||||
tags,
|
||||
inputVisible: false,
|
||||
inputValue: '',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
handleChange = (e) => {
|
||||
//console.log(`Selected: ${value}`);
|
||||
//var state = this.state;
|
||||
//state['selectedParams'] = trim(value);
|
||||
let selectedKeys = e;
|
||||
this.setState({selectedKeys});
|
||||
}
|
||||
|
||||
handlInputChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
uploadHandleChange = (info) => {
|
||||
let fileList = info.fileList;
|
||||
fileList = fileList.slice(-1);
|
||||
this.setState({ fileList });
|
||||
}
|
||||
|
||||
handleSubmit = (isValidated, e) => {
|
||||
e.preventDefault();
|
||||
//console.log(e, isValidated);
|
||||
if(!isValidated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
} else{
|
||||
var param={};
|
||||
var confParam = {};
|
||||
param.id= this.state.id;
|
||||
param.name= this.state.name;
|
||||
param.type= this.state.type;
|
||||
param.path= this.state.fileList.map(item => item.name).join();
|
||||
param.comment= this.state.comment;
|
||||
param.tag= this.state.tag;
|
||||
param.operation= this.state.operation;
|
||||
param.status= this.state.status;
|
||||
param.modelId = this.state.model.id;
|
||||
confParam.feed = this.state.feed;
|
||||
confParam.expressions= this.state.selectedKeys.map(item=> "abstractions." + item).join();
|
||||
param.confParam = confParam;
|
||||
|
||||
FetchUtil('/modelConfig/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('修改成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
//this.props.reload();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
saveInputRef = input => this.input = input
|
||||
|
||||
render() {
|
||||
const plugin=this.state.plugin;
|
||||
const { tags,path, inputVisible, inputValue, paramsList} = this.state;
|
||||
let isValidated = true;
|
||||
console.log("cols==", this.state.selectCols);
|
||||
console.log("path==", path);
|
||||
const uploadProps = {
|
||||
name: 'file',
|
||||
data: {"key": "machine"},
|
||||
action: '/services/v1/common/upload',
|
||||
headers: {
|
||||
"x-auth-token": localStorage.getItem('x-auth-token'),
|
||||
},
|
||||
onChange: this.uploadHandleChange,
|
||||
|
||||
};
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
let validate={
|
||||
name:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
tag:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
operation:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
feed:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
|
||||
if(!this.state.name){
|
||||
validate.name.help='请输入机器学习模型名称';
|
||||
validate.name.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let name = this.state.name;
|
||||
if(!reg.test(name)){
|
||||
validate.name.help='按照提示输入正确的名称';
|
||||
validate.name.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.state.feed){
|
||||
validate.feed.help='请输入参数名称';
|
||||
validate.feed.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let feed = this.state.feed;
|
||||
if(!reg.test(feed)){
|
||||
validate.feed.help='按照提示输入feed名称';
|
||||
validate.feed.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!this.state.tag){
|
||||
validate.tag.help='请输入tag名称';
|
||||
validate.tag.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}$/;
|
||||
let tag = this.state.tag;
|
||||
if(!reg.test(tag)){
|
||||
validate.tag.help='按照提示输入正确的名称';
|
||||
validate.tag.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!this.state.operation){
|
||||
validate.operation.help='请输入opration名称';
|
||||
validate.operation.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{1,29}\/?\w{1,29}$/;
|
||||
let operation = this.state.operation;
|
||||
if(!reg.test(operation)){
|
||||
validate.operation.help='按照提示输入正确的名称';
|
||||
validate.operation.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>机器学习配置</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
|
||||
<Form layout="horizontal" onSubmit={this.handleSubmit.bind(this, isValidated)}>
|
||||
<FormItem required={true} {...formItemLayout} label="模型名称:" help={validate.name.help} validateStatus={validate.name.status} >
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="name" value={this.state.name} placeholder="请输入模型名称" onChange={this.handlInputChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习模型名称'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="学习框架:" >
|
||||
<Row>
|
||||
<Col span={20} >
|
||||
<Select value={this.state.type}>
|
||||
<Option value="TENSOR_DNN">TENSOR_DNN</Option>
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'支持的机器学习框架类型'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="算法参数:" style={{display:"None"}} >
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<div>
|
||||
{tags.map((tag, index) => {
|
||||
const isLongTag = tag.length > 20;
|
||||
const tagElem = (
|
||||
<Tag key={tag} closable={index !== 0} afterClose={() => this.handleClose(tag)}>
|
||||
{isLongTag ? `${tag.slice(0, 20)}...` : tag}
|
||||
</Tag>
|
||||
);
|
||||
return isLongTag ? <Tooltip title={tag} key={tag}>{tagElem}</Tooltip> : tagElem;
|
||||
})}
|
||||
{inputVisible && (
|
||||
<Input
|
||||
ref={this.saveInputRef}
|
||||
type="text"
|
||||
size="small"
|
||||
style={{ width: 78 }}
|
||||
value={inputValue}
|
||||
onChange={this.handleInputChange}
|
||||
onBlur={this.handleInputConfirm}
|
||||
onPressEnter={this.handleInputConfirm}
|
||||
/>
|
||||
)}
|
||||
{!inputVisible && <Button size="small" type="dashed" onClick={this.showInput}>+参数</Button>}
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习模型调用时需要的其它参数'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="Tag:" help={validate.tag.help} validateStatus={validate.tag.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="tag" value={this.state.tag} placeholder="tag" onChange={this.handlInputChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'tag'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="Operation:" help={validate.operation.help} validateStatus={validate.operation.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="operation" value={this.state.operation} placeholder="operation" onChange={this.handlInputChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'Operation'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="模型文件">
|
||||
<Row>
|
||||
|
||||
<Col span={20}>
|
||||
<Upload {...uploadProps} accept={'.zip'} fileList={this.state.fileList}>
|
||||
<Button>
|
||||
<Icon type="upload" /> 点击上传
|
||||
</Button>
|
||||
</Upload>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'机器学习训练后的文件, 仅支持zip格式'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="描叙信息" style={{display:"on"}} >
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="comment" value={this.state.comment} rows={4} placeholder="模型描叙信息。" onChange={this.handlInputChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'模型描叙信息。'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="模型入参" help={validate.feed.help} validateStatus={validate.feed.status}>
|
||||
{
|
||||
paramsList.map((item,index) => {
|
||||
const selected = item.expressions.replace(/abstractions./g,"").split(",");
|
||||
console.log("selected:" ,selected);
|
||||
let rows = (<Row key={index} id={item.id}>
|
||||
<Col span={4}><Input type="text" name="feed" value={item.feed} placeholder="feed" /></Col>
|
||||
<Col span={15} offset={1}>
|
||||
<div>
|
||||
<Select
|
||||
mode="tags"
|
||||
size={'default'}
|
||||
placeholder="Please select"
|
||||
value={selected}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{this.state.absColumns}
|
||||
</Select>
|
||||
</div>
|
||||
</Col>
|
||||
<Col span={1} offset={1}>
|
||||
<EditModelConfParam paramId={item.id} abstractions={this.state.absColumns} />
|
||||
</Col>
|
||||
</Row>);
|
||||
return rows;
|
||||
})
|
||||
}
|
||||
{
|
||||
paramsList.length==0 ? (
|
||||
<Row key={-1}>
|
||||
<Col span={4}><Input type="text" name="feed" value={this.state.feed} placeholder="feed" onChange={this.handlInputChange}/></Col>
|
||||
<Col span={15} offset={1}>
|
||||
<div>
|
||||
<Select
|
||||
mode="tags"
|
||||
size={'default'}
|
||||
placeholder="Please select"
|
||||
onChange={this.handleChange}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{this.state.absColumns}
|
||||
</Select>
|
||||
</div>
|
||||
</Col>
|
||||
</Row>
|
||||
)
|
||||
|
||||
: ""
|
||||
}
|
||||
</FormItem>
|
||||
<FormItem>
|
||||
<Row>
|
||||
|
||||
<Col span={20} offset={18}>
|
||||
<Button type="primary" htmlType="submit">
|
||||
更新配置
|
||||
</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</FormItem>
|
||||
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditModelConfParam extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
id :-1,
|
||||
feed:'',
|
||||
selectList:[],
|
||||
indexed:false
|
||||
}
|
||||
|
||||
FetchUtil('/modelConfigParam/' + this.props.paramId,'GET','',
|
||||
(data) => {
|
||||
let param = data.data.param;
|
||||
this.setState({
|
||||
id:param.id,
|
||||
feed: param.feed,
|
||||
selectList: param.expressions.replace(/abstractions./g,"").split(","),
|
||||
})
|
||||
});
|
||||
|
||||
// FetchUtil('/activation/absColumns/' + this.props.params.id,'GET','',
|
||||
// (data) => {
|
||||
// let absColumns =[];
|
||||
// let absDS= data.data.columns;
|
||||
// for (let i = 0; i < absDS.length; i++) {
|
||||
// absColumns.push(<Option key={absDS[i].value}>{absDS[i].label}</Option>);
|
||||
// }
|
||||
// //console.log(absColumns);
|
||||
// this.setState({
|
||||
// absColumns: absColumns,
|
||||
// });
|
||||
// });
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
// fetchData=()=>{
|
||||
// FetchUtil('/modelConfigParam/'+ this.state.id,'GET',null,
|
||||
// (data) => {
|
||||
// const param=data.data.param;
|
||||
// this.setState({
|
||||
// id:param.id,
|
||||
// feed: param.feed,
|
||||
// expressions: param.expressions,
|
||||
// });
|
||||
// }
|
||||
// )
|
||||
// }
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(value)=>{
|
||||
this.setState({selectList: value});
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
//this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
onCheck=(e)=>{
|
||||
if(e.target.checked && this.props.indexedAll>=8){
|
||||
Modal.warning({
|
||||
title: '提示信息',
|
||||
content: '索引已超过8项!',
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
indexed:e.target.checked
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param = {};
|
||||
param.id = this.state.id;
|
||||
param.feed = this.state.feed;
|
||||
param.expressions = this.state.selectList.map(item => 'abstractions.' + item).join();
|
||||
|
||||
FetchUtil('/modelConfigParam/', 'PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
if (data.success) {
|
||||
message.success('修改成功');
|
||||
} else {
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
feed:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
fieldType:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.feed){
|
||||
validate.feed.help='请输入参数名称';
|
||||
validate.feed.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[a-zA-z]\w{2,29}$/;
|
||||
let feed = this.state.feed;
|
||||
if(!reg.test(feed)){
|
||||
validate.feed.help='按照提示输入正确的名称';
|
||||
validate.feed.status='error';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑参数" visible={this.state.visible} onOk={this.handleSubmit.bind(this, isValidated)} onCancel={this.handleCancel}>
|
||||
<Form layout="horizontal" form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="feed:" help={validate.feed.help} validateStatus={validate.feed.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="feed" value={this.state.feed} onChange={this.handleChange} />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'2-30位英文字母、数字、下划线的组合,以英文字母开头:xyz001'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="特征指标:">
|
||||
<Row>
|
||||
<Col span={10}>
|
||||
|
||||
<Select
|
||||
mode="tags"
|
||||
size={'default'}
|
||||
placeholder="Please select"
|
||||
value={this.state.selectList}
|
||||
onChange={this.handleSelect}
|
||||
style={{ width: '100%' }}
|
||||
>
|
||||
{this.props.abstractions}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'选择模型需要的特征指标'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Form,Row,Col,Input,Button,Table,Tooltip,Pagination,Select,Popconfirm,message} from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import AddPreItem from './modal/AddPreItem';
|
||||
import EditPreItem from './modal/EditPreItem';
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class PreItem extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
destField:'',
|
||||
label:'',
|
||||
plugin:"",
|
||||
status:1,
|
||||
|
||||
tData:[],
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
loading:true,
|
||||
|
||||
model:null,
|
||||
filedList:[],
|
||||
plugins:[]
|
||||
}
|
||||
|
||||
FetchUtil('/model/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
const model=data.data.model;
|
||||
this.setState({
|
||||
model:model
|
||||
});
|
||||
});
|
||||
FetchUtil('/field/list/'+this.props.params.id,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldList:data.data.field
|
||||
});
|
||||
});
|
||||
|
||||
FetchUtil('/common/plugins','GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
plugins:data.data.plugins
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=1000;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.params.id;
|
||||
param.destField=this.state.destField;
|
||||
param.label=this.state.label;
|
||||
param.plugin=this.state.plugin;
|
||||
param.status=this.state.status;
|
||||
|
||||
FetchUtil('/preitem','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({loading:false});
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum,
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.setState({
|
||||
pageNo:1
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
deletePreItem=(id)=>{
|
||||
FetchUtil('/preitem/','DELETE','['+id+']',
|
||||
(data) => {
|
||||
message.info('删除成功!');
|
||||
this.fetchTableData();
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},{
|
||||
title: '字段名',
|
||||
dataIndex: 'label'
|
||||
},{
|
||||
title: '来源字段名',
|
||||
dataIndex: 'sourceLabel'
|
||||
},{
|
||||
title: '插件',
|
||||
dataIndex: 'plugin',
|
||||
render:
|
||||
(t) =>{
|
||||
let plugin=this.state.plugins.filter(x=>x.method==t);
|
||||
return plugin.length!=0?plugin[0].desc:'';
|
||||
}
|
||||
},{
|
||||
title: '插件参数(可选)',
|
||||
dataIndex: 'args'
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:
|
||||
(t,r,i) => {
|
||||
return(
|
||||
<span>
|
||||
<EditPreItem modelId={this.props.params.id} row={r} fieldList={this.state.fieldList} plugins={this.state.plugins} reload={this.fetchTableData}/>
|
||||
<span className="ant-divider"></span>
|
||||
<Popconfirm placement="bottomRight" title={'确认删除该字段吗?'} onConfirm={this.deletePreItem.bind(this,r.id)}>
|
||||
<Tooltip title="删除"><a style={{color:'#FD5B5B'}}>删除</a></Tooltip>
|
||||
</Popconfirm>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="字段名:">
|
||||
<Input value={this.state.destField} name="destField" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
{' '}
|
||||
<AddPreItem modelId={this.props.params.id} fieldList={this.state.fieldList} plugins={this.state.plugins} reload={this.fetchTableData} />
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData.filter((item,index,array)=>{
|
||||
var reg = new RegExp('('+ this.state.destField+')','gi');
|
||||
if(this.state.destField){
|
||||
return (reg.test(item.label));
|
||||
}else {
|
||||
return true;
|
||||
}
|
||||
})}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<div style={{display:"none",width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,333 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class AddPreItem extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
destField:'',
|
||||
label:'',
|
||||
sourceField:'',
|
||||
sourceLabel:'',
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:'',
|
||||
reqType:'GET',
|
||||
configJson:JSON.stringify({})
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
console.log(e,'==')
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = typeof value==='number'?value: trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
if(name=='plugin'){
|
||||
state['sourceField']='';
|
||||
state['sourceLabel']='';
|
||||
state['args']='';
|
||||
state['status']=1;
|
||||
state['configJson']= JSON.stringify({});
|
||||
}
|
||||
state[name] = trim(value);
|
||||
|
||||
if(name=='sourceField'){
|
||||
state['sourceLabel']= this.props.fieldList.filter(x => x.fieldName==value)[0].label;
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleMultiSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
if(value==''){
|
||||
state[name]='';
|
||||
}
|
||||
else{
|
||||
state[name] = trim(value.join(','));
|
||||
state['sourceLabel'] = value.map((info)=>{
|
||||
return this.props.fieldList.filter(x=>x.fieldName==info)[0].label;
|
||||
}).join(',');
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
destField:'',
|
||||
label:'',
|
||||
sourceField:'',
|
||||
sourceLabel:'',
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:'',
|
||||
reqType:'GET',
|
||||
visible:true,
|
||||
configJson:JSON.stringify({})
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(typeof JSON.parse(this.state.configJson)!='object'){
|
||||
return message.error('多文本框json格式不对');
|
||||
}
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.modelId=this.props.modelId;
|
||||
param.destField=this.state.destField;
|
||||
param.label=this.state.label;
|
||||
param.sourceField=this.state.sourceField;
|
||||
param.sourceLabel=this.state.sourceLabel;
|
||||
param.plugin=this.state.plugin;
|
||||
param.status=this.state.status;
|
||||
param.reqType=this.state.reqType;
|
||||
param.args=this.state.args;
|
||||
param.configJson=JSON.parse(this.state.configJson);
|
||||
FetchUtil('/preitem/','PUT', JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('添加成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
plugin:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
sourceField:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
args:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.plugin){
|
||||
validate.plugin.help='请选择插件';
|
||||
validate.plugin.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入目标字段名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的目标显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.sourceField){
|
||||
validate.sourceField.help='请选择原始字段名';
|
||||
validate.sourceField.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.args){
|
||||
validate.args.status='warning';
|
||||
if(this.state.plugin=='SUBSTRING'){
|
||||
validate.args.help='请输入截取字段位数';
|
||||
isValidated=false;
|
||||
} else if (this.state.plugin=='DATEFORMAT') {
|
||||
validate.args.help='请输入日期格式化字符串';
|
||||
isValidated=false;
|
||||
} else if (this.state.plugin=='RESTUTIL') {
|
||||
validate.args.help='请输入正确的 url';
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
const plugin=this.state.plugin;
|
||||
let fieldArr=this.state.sourceField==''?[]:this.state.sourceField.split(',');
|
||||
console.log( this.props.plugins)
|
||||
return (
|
||||
<span>
|
||||
<Button onClick={this.showModal} type="primary">新增</Button>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="插件种类:" help={validate.plugin.help} validateStatus={validate.plugin.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select value={this.state.plugin} onChange={this.handleSelect.bind(this,'plugin')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.props.plugins.map(x=><Option key={x.key} value={x.method}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'插件种类,如 IP转换成地址(将IP地址转换成详细的实际地址),字段合并(将多个原始字段合并起来),字符串截短(例将手机号码截取部分进行筛选,如前七位0,7),等等'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="目标字段名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段显示名称,一般为中文,如"IP归属地"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="原始字段名:" style={plugin!='ALLINONE'?{}:{display:"none"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select value={this.state.sourceField} onChange={this.handleSelect.bind(this,'sourceField')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.props.fieldList==null?'':this.props.fieldList.map(x=><Option key={x.id} value={x.fieldName}>{x.label}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'原始字段名,均为自己定义的字段名'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="原始字段名:" style={plugin=='ALLINONE'?{}:{display:"none"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select multiple placeholder="Please select" value={fieldArr} onChange={this.handleMultiSelect.bind(this,'sourceField')}>
|
||||
{
|
||||
this.props.fieldList==null?'':this.props.fieldList.map(x=><Option key={x.id} value={x.fieldName}>{x.label}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'原始字段名,均为自己定义的字段名'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="截取位数" style={plugin=='SUBSTRING'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'截取位数,属于字符串截短插件的参数,如筛选手机号码前7位,填写 0,7'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="格式化字符串" style={plugin=='DATEFORMAT'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'日期格式化字符串,例如:yyyyMMdd HH:mm:ss'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="请求信息" style={plugin=='HTTP_UTIL'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Radio.Group name="reqType" onChange={this.handleChange} value={this.state.reqType}>
|
||||
<Radio value={'GET'}>GET</Radio>
|
||||
<Radio disabled={true} value={'POST'}>POST</Radio>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'请求方式: POST, GET'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'Rest url, like http://xxx/getSth?id={1}'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="configJson" value={this.state.configJson} onChange={(e)=>this.handleChange(e)} rows={4} placeholder="请输入响应结果字段描叙信息:json数组" />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'响应字段元信息, like:[{"column":"country","title":"国家","type":"STRING"},{"column":"province","title":"省份","type":"STRING"}]'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,328 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Checkbox,Select,Radio,Switch,Form,Row,Col,Icon,Modal,Input,InputNumber,Cascader,Tooltip,message } from 'antd';
|
||||
|
||||
const FormItem = Form.Item;
|
||||
const RadioGroup = Radio.Group;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../../utils/fetchUtil';
|
||||
import {trim} from '../../utils/validateUtil';
|
||||
|
||||
export default class EditPreItem extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
visible:false,
|
||||
|
||||
destField:'',
|
||||
label:'',
|
||||
sourceField:'',
|
||||
sourceLabel:'',
|
||||
plugin:'',
|
||||
status:1,
|
||||
args:'',
|
||||
reqType:'GET',
|
||||
configJson:JSON.stringify({}),
|
||||
preItem:null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchData=()=>{
|
||||
FetchUtil('/preitem/'+this.props.row.id,'GET','',
|
||||
(data) => {
|
||||
const preItem=data.data.preItem;
|
||||
this.setState({
|
||||
destField:preItem.destField,
|
||||
label:preItem.label,
|
||||
sourceField:preItem.sourceField,
|
||||
sourceLabel:preItem.sourceLabel,
|
||||
plugin:preItem.plugin,
|
||||
status:preItem.status,
|
||||
reqType:preItem.reqType,
|
||||
args:preItem.args,
|
||||
configJson:JSON.stringify(preItem.configJson)
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = typeof value==='number'?value: trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
if(name=='plugin'){
|
||||
state['sourceField']='';
|
||||
state['sourceLabel']='';
|
||||
state['args']='';
|
||||
state['configJson']=JSON.stringify({});
|
||||
}
|
||||
state[name] = trim(value);
|
||||
|
||||
if(name=='sourceField'){
|
||||
state['sourceLabel']=this.props.fieldList.filter(x=>x.fieldName==value)[0].label;
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleMultiSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
if(value==''){
|
||||
state[name]='';
|
||||
}
|
||||
else{
|
||||
state[name] = trim(value.join(','));
|
||||
state['sourceLabel'] = value.map((info)=>{
|
||||
return this.props.fieldList.filter(x=>x.fieldName==info)[0].label;
|
||||
}).join(',');
|
||||
}
|
||||
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
showModal=()=>{
|
||||
this.fetchData();
|
||||
this.setState({
|
||||
visible:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSubmit=(validated)=>{
|
||||
if(typeof JSON.parse(this.state.configJson)!='object'){
|
||||
return message.error('多文本框json格式不对');
|
||||
}
|
||||
if(!validated){
|
||||
Modal.error({
|
||||
title: '提交失败',
|
||||
content: '请确认表单内容输入正确',
|
||||
});
|
||||
}
|
||||
else{
|
||||
var param={};
|
||||
param.id=this.props.row.id;
|
||||
param.modelId=this.props.modelId;
|
||||
param.destField=this.state.destField;
|
||||
param.label=this.state.label;
|
||||
param.sourceField=this.state.sourceField;
|
||||
param.sourceLabel=this.state.sourceLabel;
|
||||
param.plugin=this.state.plugin;
|
||||
param.status=this.state.status;
|
||||
param.args=this.state.args;
|
||||
param.reqType=this.state.reqType;
|
||||
param.configJson=JSON.parse(this.state.configJson);
|
||||
|
||||
FetchUtil('/preitem/','PUT',JSON.stringify(param),
|
||||
(data) => {
|
||||
if(data.success){
|
||||
message.success('修改成功');
|
||||
}else{
|
||||
message.error(data.msg);
|
||||
}
|
||||
this.setState({
|
||||
visible:false
|
||||
});
|
||||
this.props.reload();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
const formItemLayout = {
|
||||
labelCol: { span: 6 },
|
||||
wrapperCol: { span: 16 },
|
||||
};
|
||||
|
||||
let validate={
|
||||
plugin:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
label:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
sourceField:{
|
||||
help:'',
|
||||
status:'success'
|
||||
},
|
||||
args:{
|
||||
help:'',
|
||||
status:'success'
|
||||
}
|
||||
};
|
||||
let isValidated=true;
|
||||
|
||||
if(!this.state.plugin){
|
||||
validate.plugin.help='请选择插件';
|
||||
validate.plugin.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.label){
|
||||
validate.label.help='请输入目标字段名';
|
||||
validate.label.status='warning';
|
||||
isValidated=false;
|
||||
}else {
|
||||
let reg = /^[\u4e00-\u9fa5 \w]{2,20}$/;
|
||||
let label = this.state.label;
|
||||
if(!reg.test(label)){
|
||||
validate.label.help='按照提示输入正确的目标显示名称';
|
||||
validate.label.status='error';
|
||||
isValidated=false;
|
||||
|
||||
}
|
||||
}
|
||||
if(!this.state.sourceField){
|
||||
validate.sourceField.help='请选择原始字段名';
|
||||
validate.sourceField.status='warning';
|
||||
isValidated=false;
|
||||
}
|
||||
if(!this.state.args){
|
||||
validate.args.help='请输入截取字段位数';
|
||||
validate.args.status='warning';
|
||||
if(this.state.plugin=='SUBSTRING'){
|
||||
isValidated=false;
|
||||
}
|
||||
}
|
||||
|
||||
const plugin=this.state.plugin;
|
||||
let fieldArr=this.state.sourceField==''?[]:this.state.sourceField.split(',');
|
||||
return (
|
||||
<span>
|
||||
<Tooltip title="编辑" onClick={this.showModal}><a>编辑</a></Tooltip>
|
||||
<Modal title="编辑字段" visible={this.state.visible} onOk={this.handleSubmit.bind(this,isValidated)} onCancel={this.handleCancel}>
|
||||
<Form horizontal form={this.props.form}>
|
||||
<FormItem required={true} {...formItemLayout} label="插件种类:" help={validate.plugin.help} validateStatus={validate.plugin.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select value={this.state.plugin} onChange={this.handleSelect.bind(this,'plugin')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.props.plugins.map(x=><Option key={x.key} value={x.method}>{x.desc}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'插件种类,如 IP转换成地址(将IP地址转换成详细的实际地址),字段合并(将多个原始字段合并起来),字符串截短(例将手机号码截取部分进行筛选,如前七位0,7),等等'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="目标字段名:" help={validate.label.help} validateStatus={validate.label.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="label" value={this.state.label} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'字段显示名称,一般为中文,如"IP归属地"'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="原始字段名:" style={plugin!='ALLINONE'?{}:{display:"none"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select value={this.state.sourceField} onChange={this.handleSelect.bind(this,'sourceField')}>
|
||||
<Option value="">请选择</Option>
|
||||
{
|
||||
this.props.fieldList.map(x=><Option key={x.id} value={x.fieldName}>{x.label}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'原始字段名,均为自己定义的字段名'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="原始字段名:" style={plugin=='ALLINONE'?{}:{display:"none"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Select multiple placeholder="Please select" value={fieldArr} onChange={this.handleMultiSelect.bind(this,'sourceField')}>
|
||||
{
|
||||
this.props.fieldList.map(x=><Option key={x.id} value={x.fieldName}>{x.label}</Option>)
|
||||
}
|
||||
</Select>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'原始字段名,均为自己定义的字段名'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
<FormItem required={true} {...formItemLayout} label="截取位数" style={plugin=='SUBSTRING'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'截取位数,属于字符串截短插件的参数,如筛选手机号码前7位,填写 0,7'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
</FormItem>
|
||||
|
||||
<FormItem required={true} {...formItemLayout} label="请求信息" style={plugin=='HTTP_UTIL'?{}:{display:"none"}} help={validate.args.help} validateStatus={validate.args.status}>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Radio.Group name="reqType" onChange={this.handleChange} value={this.state.reqType}>
|
||||
<Radio value={'GET'}>GET</Radio>
|
||||
<Radio disabled={true} value={'POST'}>POST</Radio>
|
||||
</Radio.Group>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'请求方式: POST, GET'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input type="text" name="args" value={this.state.args} onChange={this.handleChange}/>
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'Rest url, like http://xxx/getSth?id={1}'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={20}>
|
||||
<Input.TextArea name="configJson" value={this.state.configJson} onChange={(e)=>this.handleChange(e)} rows={4} placeholder="请输入响应结果字段描叙信息:json数组" />
|
||||
</Col>
|
||||
<Col span={2} offset={1}>
|
||||
<Tooltip placement="right" title={'响应字段元信息,like:[{"column":"country","title":"国家","type":"STRING"},{"column":"province","title":"省份","type":"STRING"}]'}>
|
||||
<Icon style={{fontSize:16}} type="question-circle-o" />
|
||||
</Tooltip>
|
||||
</Col>
|
||||
</Row>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import {Card,Form,Input,Button,Icon,Alert,Col,message,Modal} from 'antd';
|
||||
const FormItem = Form.Item;
|
||||
import './Login.less';
|
||||
import {fetchVersion} from './utils/fetchUtil';
|
||||
class Register extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
visible: false,
|
||||
rd:Math.random(),
|
||||
};
|
||||
}
|
||||
handleOk = () => {
|
||||
|
||||
const { validateFields, } = this.props.form
|
||||
validateFields((err, values) => {
|
||||
if (!err) {
|
||||
const { loginName,passwd,verifyPasswd,captcha } = values;
|
||||
fetch(fetchVersion+`/merchant/regist?loginName=${loginName}&passwd=${passwd}&verifyPasswd=${verifyPasswd}&captcha=${captcha}`,{method: 'POST',
|
||||
})
|
||||
.then((res) => {
|
||||
if(res.ok){
|
||||
return res.json();
|
||||
}
|
||||
}).then((res) => {
|
||||
if(res.code==='100'&&res.success){
|
||||
message.success(res.msg)
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
}else{
|
||||
message.error(res.msg)
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e.msg);
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
onCancel = () => {
|
||||
this.setState({
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
registerHandler = () => {
|
||||
this.setState({
|
||||
visible: true
|
||||
});
|
||||
}
|
||||
|
||||
handleClick=(event)=>{
|
||||
this.setState({
|
||||
rd:Math.random()
|
||||
})
|
||||
}
|
||||
|
||||
validator = (rule, value, callback) => {
|
||||
const { getFieldValue } = this.props.form
|
||||
if (value && value !== getFieldValue('passwd')) {
|
||||
callback('两次输入不一致!')
|
||||
}
|
||||
callback()
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
this.setState({
|
||||
rd:Math.random()
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
const { visible} = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
sm: { span: 8 }
|
||||
},
|
||||
wrapperCol: {
|
||||
sm: { span: 10 }
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div style={{display: 'inline-block'}}>
|
||||
<Button
|
||||
className="ant-btn-lg"
|
||||
type="primary"
|
||||
style={{marginLeft: 10}}
|
||||
onClick={this.registerHandler}
|
||||
>
|
||||
注册
|
||||
</Button>
|
||||
<Modal
|
||||
title="注册账号"
|
||||
visible={visible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.onCancel}
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
centered={true}
|
||||
width="600px"
|
||||
okText="确认"
|
||||
cancelText="取消"
|
||||
>
|
||||
<FormItem label={'账号'} {...formItemLayout}>
|
||||
{getFieldDecorator('loginName', {
|
||||
rules: [{ required: true, message: '请输入账号' }],
|
||||
})(<Input placeholder={'请输入账号'} />)}
|
||||
</FormItem>
|
||||
<FormItem label={'密码'} {...formItemLayout}>
|
||||
{getFieldDecorator('passwd', {
|
||||
rules: [{ required: true, message: '请输入密码' }],
|
||||
})(<Input type="password" placeholder={'请输入密码'} />)}
|
||||
</FormItem>
|
||||
<FormItem label={'确认密码'} {...formItemLayout}>
|
||||
{getFieldDecorator('verifyPasswd', {
|
||||
rules: [{ required: true, message: '请输入确认密码' },{validator:this.validator}],
|
||||
})(<Input type="password" placeholder={'请输入确认密码'} />)}
|
||||
</FormItem>
|
||||
<FormItem label={'验证码'} {...formItemLayout}>
|
||||
{getFieldDecorator('captcha', {
|
||||
rules: [{ required: true, message: '请输入验证码或者真确的位数!' ,max:4}],
|
||||
})(<Input placeholder={'请输入验证码'} />)}
|
||||
<img src={fetchVersion+"/common/getCaptcha?"+this.state.rd} onClick={this.handleClick}/>
|
||||
</FormItem>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Form.create()(Register)
|
||||
@@ -1,507 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Form,Button,Table,Pagination,Input,Select,Modal,DatePicker,Cascader} from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import './ListEvent.less';
|
||||
|
||||
import ExportField from './modal/ExportField';
|
||||
|
||||
export default class ListEvent extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
fieldName:'',
|
||||
fieldValue:'',
|
||||
activationName:'',
|
||||
ruleId:'',
|
||||
risk:'',
|
||||
beginTime:moment().add(-3,'days'),
|
||||
endTime:moment(),
|
||||
rangeSelect:'-3',
|
||||
|
||||
tData:[],
|
||||
loading:true,
|
||||
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
pageSize:30,
|
||||
|
||||
exportDisabled:true,
|
||||
showAdvance:false,
|
||||
searchType:''
|
||||
}
|
||||
|
||||
if(this.props.params.modelId){
|
||||
this.state.showAdvance=true;
|
||||
this.state.searchType='rule';
|
||||
this.state.activationName=this.props.params.activationName;
|
||||
this.state.ruleId=this.props.params.ruleId+'';
|
||||
}
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=30;
|
||||
let param={};
|
||||
let errMsg='';
|
||||
switch(this.state.searchType){
|
||||
case '':param.fieldName='';param.fieldValue='';break;
|
||||
case 'field':
|
||||
if(!this.state.fieldName){
|
||||
errMsg='请选择字段!';
|
||||
break;
|
||||
}
|
||||
if(!this.state.fieldValue){
|
||||
errMsg='请输入字段值!';
|
||||
break;
|
||||
}
|
||||
param.fieldName=this.state.fieldName;
|
||||
param.fieldValue=this.state.fieldValue;
|
||||
break;
|
||||
case 'rule':
|
||||
if(!this.state.activationName){
|
||||
errMsg='请选择策略!';
|
||||
break;
|
||||
}
|
||||
if(!this.state.ruleId){
|
||||
errMsg='请选择规则!';
|
||||
break;
|
||||
}
|
||||
param.fieldName='hitsDetail.'+this.state.activationName+'.rule_'+this.state.ruleId+'.key';
|
||||
param.fieldValue=this.state.ruleId;
|
||||
break;
|
||||
case 'risk':
|
||||
if(!this.state.activationName){
|
||||
errMsg='请选择策略!';
|
||||
break;
|
||||
}
|
||||
if(!this.state.risk){
|
||||
errMsg='请选择评估结果!';
|
||||
break;
|
||||
}
|
||||
param.fieldName='activations.'+this.state.activationName+'.risk';
|
||||
param.fieldValue=this.state.risk;
|
||||
break;
|
||||
}
|
||||
|
||||
if(errMsg){
|
||||
Modal.error({
|
||||
title:errMsg
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.modelId;
|
||||
param.beginTime=this.state.beginTime.format('YYYY-MM-DD HH:mm:ss');
|
||||
param.endTime=this.state.endTime.format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
this.setState({loading:true});
|
||||
FetchUtil('/event/search','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({
|
||||
tData:data.data.page.list,
|
||||
pageNo:data.data.page.pageNum
|
||||
});
|
||||
if(data.data.page.rowCount > 9990){
|
||||
this.setState({
|
||||
rowCount:9990
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
}
|
||||
},
|
||||
()=>{
|
||||
this.setState({loading:false,exportDisabled:false});
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.modelId!=this.props.modelId){
|
||||
this.setState({
|
||||
fieldName:'',
|
||||
fieldValue:'',
|
||||
activationName:'',
|
||||
ruleId:'',
|
||||
risk:'',
|
||||
pageNo:1,
|
||||
fieldName:'',
|
||||
fieldValue:'',
|
||||
beginTime:moment().add(-3,'days'),
|
||||
endTime:moment(),
|
||||
rangeSelect:'-3',
|
||||
showAdvance:false,
|
||||
searchType:''
|
||||
},this.fetchTableData());
|
||||
}
|
||||
}
|
||||
|
||||
toggleAdvance=()=>{
|
||||
this.setState({
|
||||
showAdvance:!this.state.showAdvance,
|
||||
searchType:'',
|
||||
fieldName:'',
|
||||
fieldValue:'',
|
||||
activationName:'',
|
||||
ruleId:'',
|
||||
risk:'',
|
||||
});
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
state['exportDisabled']=true;
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name]=value;
|
||||
state['exportDisabled']=true;
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleCalendar=(dates,dateStrings)=>{
|
||||
this.setState({
|
||||
beginTime:dates[0],
|
||||
endTime:dates[1],
|
||||
rangeSelect:'',
|
||||
exportDisabled:true
|
||||
});
|
||||
}
|
||||
|
||||
handleChangeDate=(value)=>{
|
||||
//console.log(value);
|
||||
if(value === '-1'){
|
||||
this.setState({
|
||||
beginTime:moment().add(value,'months'),
|
||||
endTime:moment()
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
beginTime:moment().add(value,'days'),
|
||||
endTime:moment()
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
rangeSelect:value,
|
||||
exportDisabled:true
|
||||
});
|
||||
}
|
||||
|
||||
handleField=(value)=>{
|
||||
this.setState({
|
||||
fieldName:value.join("."),
|
||||
fieldValue:'',
|
||||
exportDisabled:true
|
||||
})
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.fetchTableData();
|
||||
if(this.props.location.pathname.indexOf('ruleid')!=-1){
|
||||
window.location.href='/#/event';
|
||||
}
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
displayRender = (labels, selectedOptions) => labels.map((label, i) => {
|
||||
const option = selectedOptions[i];
|
||||
if (i === labels.length - 1) {
|
||||
return (
|
||||
<span key={option.value+i}>
|
||||
{label}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span key={option.value+i}>{label} / </span>;
|
||||
})
|
||||
|
||||
showModal=(record)=>{
|
||||
const hitsDetail=record.hitsDetail;
|
||||
const activations=record.activations;
|
||||
const columns=[{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},{
|
||||
title: '命中规则',
|
||||
dataIndex: 'desc',
|
||||
key: 'rule'
|
||||
},{
|
||||
title: '得分',
|
||||
dataIndex:'value'
|
||||
}];
|
||||
let data=[];
|
||||
for(var Key in hitsDetail){
|
||||
for(var subKey in hitsDetail[Key]){
|
||||
data.push(hitsDetail[Key][subKey]);
|
||||
}
|
||||
}
|
||||
const columnsActivation=[{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},{
|
||||
title: '策略名称',
|
||||
dataIndex: 'name',
|
||||
},{
|
||||
title: '得分',
|
||||
dataIndex:'score'
|
||||
},{
|
||||
title: '处理结果',
|
||||
dataIndex:'risk'
|
||||
}];
|
||||
let dataActivation=[];
|
||||
for(var Keys in activations){
|
||||
activations[Keys].name = Keys;
|
||||
if(activations[Keys].risk === 'pass'){
|
||||
activations[Keys].risk = '通过';
|
||||
}else if(activations[Keys].risk === 'review'){
|
||||
activations[Keys].risk = '人工审核';
|
||||
}else if(activations[Keys].risk === 'reject'){
|
||||
activations[Keys].risk = '拒绝';
|
||||
}
|
||||
dataActivation.push(activations[Keys]);
|
||||
}
|
||||
|
||||
Modal.info({
|
||||
title: '风险详情',
|
||||
width:600,
|
||||
content: (
|
||||
<div style={{paddingTop:20}}>
|
||||
<h3>命中明细</h3>
|
||||
<Table
|
||||
dataSource={data}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
bordered
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<h3 style={{paddingTop:20}}>策略明细</h3>
|
||||
<Table
|
||||
dataSource={dataActivation}
|
||||
columns={columnsActivation}
|
||||
size="middle"
|
||||
bordered
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
let columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
fixed:'left',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
let getChildren=(valueArr,children)=>{
|
||||
return children.map((info)=>{
|
||||
let va=valueArr.concat(info.value);
|
||||
if(info.children==undefined){
|
||||
let column={
|
||||
title:info.label,
|
||||
dataIndex:va.join(''),
|
||||
key:va.join(''),
|
||||
rowSpan:4-va.length,
|
||||
className:'fixed-table'
|
||||
};
|
||||
if(this.state.model!=null&&this.state.model.referenceDate==info.value){
|
||||
column.render=(t)=>{
|
||||
return moment(parseInt(t)).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
else{
|
||||
return {
|
||||
title:info.label,
|
||||
children:getChildren(va,info.children)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
columns=columns.concat(getChildren([],this.props.fieldList));
|
||||
|
||||
let dataList=[];
|
||||
this.state.tData.map((info)=>{
|
||||
let data={};
|
||||
|
||||
for(var Key in info.fields){
|
||||
data['fields'+Key]=info.fields[Key];
|
||||
}
|
||||
|
||||
for(var Key in info.preItems){
|
||||
if(typeof info.preItems[Key]=='object'){
|
||||
for(var subKey in info.preItems[Key]){
|
||||
data['preItems'+Key+subKey]=info.preItems[Key][subKey];
|
||||
}
|
||||
}
|
||||
else{
|
||||
data['preItems'+Key]=info.preItems[Key];
|
||||
}
|
||||
}
|
||||
|
||||
data['hitsDetail']=info.hitsDetail;
|
||||
data['activations']=info.activations;
|
||||
|
||||
dataList.push(data);
|
||||
});
|
||||
|
||||
const actList=this.props.activationList.filter(x=>x.value==this.state.activationName);
|
||||
let ruleList=[];
|
||||
if(actList.length!=0){
|
||||
ruleList=actList[0].children;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="起始时间">
|
||||
<Select dropdownMatchSelectWidth={false} showSearch placeholder="选择时间段" value={this.state.rangeSelect} onChange={this.handleChangeDate} style={{width:100,marginRight:10}}>
|
||||
<Option value='-3'>三天内</Option>
|
||||
<Option value='-7'>七天内</Option>
|
||||
<Option value='-1'>一月内</Option>
|
||||
</Select>
|
||||
<RangePicker value={[this.state.beginTime,this.state.endTime]} showTime format="YYYY/MM/DD HH:mm:ss" onChange={this.handleCalendar} />
|
||||
</FormItem>
|
||||
|
||||
<Button type="primary" onClick={this.handleSearch}>查询</Button>
|
||||
{' '}
|
||||
<ExportField eventFieldList={this.props.eventFieldList} disabled={this.state.exportDisabled}/>
|
||||
|
||||
<a onClick={this.toggleAdvance}>高级搜索>></a>
|
||||
</Form>
|
||||
{this.state.showAdvance?
|
||||
<Form inline style={{marginTop:5}}>
|
||||
<FormItem label="搜索种类">
|
||||
<Select dropdownMatchSelectWidth={false} placeholder="选择时间段" value={this.state.searchType} onChange={this.handleSelect.bind(this,'searchType')} style={{marginRight:10}}>
|
||||
<Option value=''>请选择搜索种类</Option>
|
||||
<Option value='field'>按字段搜索</Option>
|
||||
<Option value='rule'>按规则搜索</Option>
|
||||
<Option value='risk'>按评估结果搜索</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
{this.state.searchType==''?''
|
||||
:this.state.searchType=='field'?
|
||||
<span>
|
||||
<FormItem label="选择字段:">
|
||||
<Cascader
|
||||
options={this.props.fieldList}
|
||||
value={this.state.fieldName.split('.')}
|
||||
displayRender={this.displayRender}
|
||||
onChange={this.handleField}
|
||||
allowClear
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem label="字段值:">
|
||||
<Input value={this.state.fieldValue} name="fieldValue" id="blue" onChange={this.handleChange}/>
|
||||
</FormItem>
|
||||
</span>
|
||||
:this.state.searchType=='rule'?
|
||||
<span>
|
||||
<FormItem label="选择策略:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.activationName} onChange={this.handleSelect.bind(this,'activationName')} style={{width:100}}>
|
||||
{this.props.activationList.map((info,i)=>{
|
||||
return <Option key={info.label} value={info.value}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="选择规则:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.ruleId} onChange={this.handleSelect.bind(this,'ruleId')} style={{width:100}}>
|
||||
{ruleList==undefined?'':ruleList.map((info,i)=>{
|
||||
return <Option key={info.label} value={info.type}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
</span>
|
||||
:this.state.searchType=='risk'?
|
||||
<span>
|
||||
<FormItem label="选择策略:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.activationName} onChange={this.handleSelect.bind(this,'activationName')} style={{width:100}}>
|
||||
{this.props.activationList.map((info,i)=>{
|
||||
return <Option key={info.label} value={info.value}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="处理结果:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.risk} onChange={this.handleSelect.bind(this,'risk')} style={{width:100}}>
|
||||
<Option value='pass'>通过</Option>
|
||||
<Option value='review'>人工审核</Option>
|
||||
<Option value='reject'>拒绝</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
</span>
|
||||
:''}
|
||||
</Form>
|
||||
:''
|
||||
}
|
||||
</div>
|
||||
|
||||
<div id="table" className="fixed-table">
|
||||
<Table
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
bordered
|
||||
onRowClick={this.showModal}
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
scroll={{ x: true }}
|
||||
/>
|
||||
<div style={{width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} defaultPageSize={this.state.pageSize} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.fixed-table{
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -1,413 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Form,Button,Table,Pagination,Input,Select,Modal,DatePicker,Cascader} from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import './ListEvent.less';
|
||||
|
||||
export default class Rule extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
beginTime:moment().add(-3,'days'),
|
||||
endTime:moment(),
|
||||
rangeSelect:'-3',
|
||||
|
||||
endOpen:false,
|
||||
|
||||
tData:[],
|
||||
loading:true,
|
||||
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
pageSize:30,
|
||||
|
||||
activationName:'',
|
||||
ruleId:'',
|
||||
risk:[],
|
||||
activationNameOne:'' //存储策略中的第一个value值,便于按处理结果查询
|
||||
}
|
||||
|
||||
if(this.props.params.modelId){
|
||||
this.state.activationName=this.props.params.activationName;
|
||||
this.state.ruleId=this.props.params.ruleId+'';
|
||||
}
|
||||
}
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=()=>{
|
||||
const pageSize=30;
|
||||
this.setState({loading:true});
|
||||
|
||||
var param={};
|
||||
param.pageNo=this.state.pageNo;
|
||||
param.pageSize=pageSize;
|
||||
param.modelId=this.props.modelId;
|
||||
if(this.state.risk.length != 0){
|
||||
if(this.state.activationName!=''){
|
||||
param.fieldName='activations.'+this.state.activationName+'.risk';
|
||||
param.fieldValue=this.state.risk;
|
||||
}else {
|
||||
param.fieldName='activations.'+this.state.activationNameOne+'.risk';
|
||||
param.fieldValue=this.state.risk;
|
||||
}
|
||||
}else{
|
||||
if(this.state.activationName!=''){
|
||||
param.fieldName='hitsDetail.'+this.state.activationName+'.rule_'+this.state.ruleId+'.key';
|
||||
param.fieldValue=this.state.ruleId;
|
||||
}
|
||||
}
|
||||
|
||||
param.beginTime=this.state.beginTime.format('YYYY-MM-DD HH:mm:ss');
|
||||
param.endTime=this.state.endTime.format('YYYY-MM-DD HH:mm:ss');
|
||||
|
||||
FetchUtil('/event/search','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
this.setState({
|
||||
tData:data.data.page.list.map((info)=>{return JSON.parse(info)}),
|
||||
pageNo:data.data.page.pageNum
|
||||
});
|
||||
if(data.data.page.rowCount > 9990){
|
||||
this.setState({
|
||||
rowCount:9990
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
rowCount:data.data.page.rowCount
|
||||
});
|
||||
}
|
||||
},
|
||||
()=>{
|
||||
this.setState({loading:false});
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.modelId!=this.props.modelId){
|
||||
this.setState({
|
||||
beginTime:moment().add(-3,'days'),
|
||||
endTime:moment(),
|
||||
rangeSelect:'-3',
|
||||
activationName:'',
|
||||
ruleId:'',
|
||||
},this.fetchTableData());
|
||||
}
|
||||
}
|
||||
|
||||
handleChange=(e)=>{
|
||||
var name = e.target.name;
|
||||
var value = e.target.value;
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
// if(name=='modelId'){
|
||||
// this.setState({
|
||||
// tData:[]
|
||||
// });
|
||||
// FetchUtil('/abstraction/datacolumns/'+value,'GET','',
|
||||
// (data) => {
|
||||
// this.setState({
|
||||
// fieldList:data.data.list
|
||||
// });
|
||||
// });
|
||||
// FetchUtil('/activation/rulecolumns/'+value,'GET','',
|
||||
// (data) => {
|
||||
// this.setState({
|
||||
// activationList:data.data.list
|
||||
// });
|
||||
// });
|
||||
// FetchUtil('/model/'+value,'GET','',
|
||||
// (data) => {
|
||||
// this.setState({
|
||||
// model:data.data.model
|
||||
// })
|
||||
// }
|
||||
// )
|
||||
// this.setState({
|
||||
// activationName:'',
|
||||
// ruleId:''
|
||||
// })
|
||||
// }
|
||||
if(name=='activationName'){
|
||||
const activation=this.props.activationList.filter(x=>x.value==value)[0];
|
||||
if(activation.children&&activation.children.length>0){
|
||||
this.setState({
|
||||
ruleId:activation.children[0].type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleCalendar=(dates,dateStrings)=>{
|
||||
this.setState({
|
||||
beginTime:dates[0],
|
||||
endTime:dates[1]
|
||||
});
|
||||
}
|
||||
|
||||
handleChangeDate=(value)=>{
|
||||
//console.log(value);
|
||||
if(value === '-1'){
|
||||
this.setState({
|
||||
beginTime:moment().add(value,'months'),
|
||||
endTime:moment()
|
||||
});
|
||||
}else {
|
||||
this.setState({
|
||||
beginTime:moment().add(value,'days'),
|
||||
endTime:moment()
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
handleSearch=()=>{
|
||||
this.fetchTableData();
|
||||
}
|
||||
|
||||
selectPage=(page)=>{
|
||||
this.setState({
|
||||
pageNo:page
|
||||
},()=>{this.fetchTableData()});
|
||||
}
|
||||
|
||||
showModal=(record)=>{
|
||||
const hitsDetail=record.hitsDetail;
|
||||
const activations=record.activations;
|
||||
const columns=[{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},{
|
||||
title: '命中规则',
|
||||
dataIndex: 'desc',
|
||||
key: 'rule'
|
||||
},{
|
||||
title: '得分',
|
||||
dataIndex:'value'
|
||||
}];
|
||||
let data=[];
|
||||
for(var Key in hitsDetail){
|
||||
for(var subKey in hitsDetail[Key]){
|
||||
data.push(hitsDetail[Key][subKey]);
|
||||
}
|
||||
}
|
||||
|
||||
const columnsActivation=[{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
},{
|
||||
title: '策略名称',
|
||||
dataIndex: 'name',
|
||||
},{
|
||||
title: '得分',
|
||||
dataIndex:'score'
|
||||
},{
|
||||
title: '处理结果',
|
||||
dataIndex:'risk'
|
||||
}];
|
||||
let dataActivation=[];
|
||||
for(var Keys in activations){
|
||||
activations[Keys].name = Keys;
|
||||
if(activations[Keys].risk === 'pass'){
|
||||
activations[Keys].risk = '通过';
|
||||
}else if(activations[Keys].risk === 'review'){
|
||||
activations[Keys].risk = '人工审核';
|
||||
}else if(activations[Keys].risk === 'reject'){
|
||||
activations[Keys].risk = '拒绝';
|
||||
}
|
||||
dataActivation.push(activations[Keys]);
|
||||
}
|
||||
|
||||
Modal.info({
|
||||
title: '风险详情',
|
||||
width:600,
|
||||
content: (
|
||||
<div style={{paddingTop:20}}>
|
||||
<h3>命中明细</h3>
|
||||
<Table
|
||||
dataSource={data}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
bordered
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
<h3 style={{paddingTop:20}}>策略明细</h3>
|
||||
<Table
|
||||
dataSource={dataActivation}
|
||||
columns={columnsActivation}
|
||||
size="middle"
|
||||
bordered
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
render(){
|
||||
let columns = [
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
key:'id',
|
||||
width:50,
|
||||
fixed:'left',
|
||||
render:(t,r,i)=>{
|
||||
return i+1;
|
||||
}
|
||||
}];
|
||||
|
||||
|
||||
let getChildren=(valueArr,children)=>{
|
||||
return children.map((info)=>{
|
||||
let va=valueArr.concat(info.value);
|
||||
if(info.children==undefined){
|
||||
let column={
|
||||
title:info.label,
|
||||
dataIndex:va.join(''),
|
||||
key:va.join(''),
|
||||
rowSpan:4-va.length,
|
||||
className:'fixed-table'
|
||||
};
|
||||
if(this.state.model!=null&&this.state.model.referenceDate==info.value){
|
||||
column.render=(t)=>{
|
||||
return moment(t).format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
}
|
||||
|
||||
return column;
|
||||
}
|
||||
else{
|
||||
return {
|
||||
title:info.label,
|
||||
children:getChildren(va,info.children)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
columns=columns.concat(getChildren([],this.props.fieldList));
|
||||
|
||||
let dataList=[];
|
||||
this.state.tData.map((info)=>{
|
||||
let data={};
|
||||
|
||||
for(var Key in info.fields){
|
||||
data['fields'+Key]=info.fields[Key];
|
||||
}
|
||||
|
||||
for(var Key in info.preItems){
|
||||
if(typeof info.preItems[Key]=='object'){
|
||||
for(var subKey in info.preItems[Key]){
|
||||
data['preItems'+Key+subKey]=info.preItems[Key][subKey];
|
||||
}
|
||||
}
|
||||
else{
|
||||
data['preItems'+Key]=info.preItems[Key];
|
||||
}
|
||||
}
|
||||
|
||||
data['hitsDetail']=info.hitsDetail;
|
||||
data['activations']=info.activations;
|
||||
|
||||
dataList.push(data);
|
||||
});
|
||||
|
||||
const actList=this.props.activationList.filter(x=>x.value==this.state.activationName);
|
||||
let ruleList=[];
|
||||
if(actList.length!=0){
|
||||
ruleList=actList[0].children;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<div id="header">
|
||||
<Form inline>
|
||||
<FormItem label="选择策略:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.activationName} onChange={this.handleSelect.bind(this,'activationName')} style={{width:100}}>
|
||||
{this.props.activationList.map((info,i)=>{
|
||||
return <Option key={info.label} value={info.value}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
<FormItem label="选择规则:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.ruleId} onChange={this.handleSelect.bind(this,'ruleId')} style={{width:100}}>
|
||||
{ruleList==undefined?'':ruleList.map((info,i)=>{
|
||||
return <Option key={info.label} value={info.type}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
|
||||
<FormItem label="处理结果:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.risk} onChange={this.handleSelect.bind(this,'risk')} style={{width:100}}>
|
||||
<Option value='pass'>通过</Option>
|
||||
<Option value='review'>人工审核</Option>
|
||||
<Option value='reject'>拒绝</Option>
|
||||
</Select>
|
||||
</FormItem>
|
||||
|
||||
|
||||
<FormItem label="起始时间">
|
||||
<Select dropdownMatchSelectWidth={false} showSearch defaultValue='-3' onChange={this.handleChangeDate} style={{width:100,marginRight:10}}>
|
||||
<Option value='-3'>三天内</Option>
|
||||
<Option value='-7'>七天内</Option>
|
||||
<Option value='-1'>一月内</Option>
|
||||
</Select>
|
||||
<RangePicker value={[this.state.beginTime,this.state.endTime]} showTime format="YYYY/MM/DD HH:mm:ss" onChange={this.handleCalendar} />
|
||||
</FormItem>
|
||||
|
||||
<Button type="primary" onClick={this.handleSearch}>查询</Button>
|
||||
{' '}
|
||||
</Form>
|
||||
</div>
|
||||
|
||||
<div id="table" className="fixed-table">
|
||||
<Table
|
||||
dataSource={dataList}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
bordered
|
||||
onRowClick={this.showModal}
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
scroll={{ x: true }}
|
||||
/>
|
||||
<div style={{width:"100%",marginTop:16,height:40}}>
|
||||
<div style={{float:"right"}}>
|
||||
<Pagination onChange={this.selectPage} defaultCurrent={this.state.pageNo} defaultPageSize={this.state.pageSize} total={this.state.rowCount} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Breadcrumb,Menu,Icon,Form,Select} from 'antd';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class Report extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
current:'',
|
||||
|
||||
modelList:[],
|
||||
modelId:'',
|
||||
fieldList:[],
|
||||
eventFieldList:[],
|
||||
activationList:[]
|
||||
}
|
||||
}
|
||||
|
||||
handleClick=(e)=>{
|
||||
window.location.href='/#/'+e.key;
|
||||
this.setState({
|
||||
current:e.key
|
||||
})
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
let state=this.state;
|
||||
state[name]=value;
|
||||
this.setState(state);
|
||||
|
||||
FetchUtil('/abstraction/datacolumns/'+value,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
fieldList:data.data.list
|
||||
});
|
||||
});
|
||||
FetchUtil('/event/datacolumns/'+value,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
eventFieldList:data.data.list
|
||||
});
|
||||
});
|
||||
FetchUtil('/activation/rulecolumns/'+value,'GET','',
|
||||
(data) => {
|
||||
this.setState({
|
||||
activationList:data.data.list,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
let key='';
|
||||
let modelId='';
|
||||
switch(this.props.location.pathname.split('/')[1]){
|
||||
case 'event':
|
||||
key='event';break;
|
||||
case 'graph':
|
||||
key='graph';break;
|
||||
case 'ruleid':
|
||||
key='event';
|
||||
modelId=this.props.location.pathname.split('/')[2];
|
||||
break;
|
||||
case 'dashboard':
|
||||
key='dashboard';break;
|
||||
}
|
||||
this.setState({
|
||||
current:key
|
||||
});
|
||||
|
||||
FetchUtil('/model/list','GET',{},
|
||||
(data) => {
|
||||
this.setState({
|
||||
modelList:data.data.modelList
|
||||
},()=>{
|
||||
if(this.state.modelList.length>0&&modelId==''){
|
||||
this.handleSelect('modelId',this.state.modelList[0].id+'');
|
||||
}
|
||||
else{
|
||||
this.handleSelect('modelId',modelId);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
getItems=()=>{
|
||||
if(this.state.modelId==''){
|
||||
return '请选择模型!';
|
||||
}
|
||||
const props={
|
||||
modelId:this.state.modelId,
|
||||
model:this.state.modelList.filter(x=>x.id==this.state.modelId)[0],
|
||||
fieldList:this.state.fieldList,
|
||||
eventFieldList:this.state.eventFieldList,
|
||||
activationList:this.state.activationList
|
||||
}
|
||||
return React.cloneElement(this.props.children,props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ant-layout-wrapper">
|
||||
<div className="ant-layout-breadcrumb">
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>首页</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>报表查询</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
<div className="ant-layout-container">
|
||||
<div style={{lineHeight:"46px",padding:"0 20px 0",margin:"0 24px",borderBottom:"1px solid #e9e9e9"}}>
|
||||
<Form inline>
|
||||
<FormItem label="模型:">
|
||||
<Select dropdownMatchSelectWidth={false} value={this.state.modelId} onChange={this.handleSelect.bind(this,'modelId')} style={{width:100}}>
|
||||
{this.state.modelList.map((info)=>{
|
||||
return <Option key={info.id} value={info.id+''}>{info.label}</Option>
|
||||
})}
|
||||
</Select>
|
||||
</FormItem>
|
||||
</Form>
|
||||
</div>
|
||||
<div className="ant-layout-header" style={{padding:"0 24px 24px"}}>
|
||||
<Menu onClick={this.handleClick} selectedKeys={[this.state.current]} mode="horizontal">
|
||||
<Menu.Item key="event">
|
||||
<Icon type="file-text"/>调用查询
|
||||
</Menu.Item>
|
||||
<Menu.Item key="graph">
|
||||
<Icon type="pushpin-o"/>规则命中
|
||||
</Menu.Item>
|
||||
<Menu.Item key="dashboard">
|
||||
<Icon type="file-text"/>指示板
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
{this.getItems()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Form,Button,Table,Pagination,Input,Select,Modal,DatePicker,Cascader} from 'antd';
|
||||
//import moment from 'moment';
|
||||
import { Link } from 'react-router';
|
||||
import echarts from 'echarts';
|
||||
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
/*
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
*/
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
export default class RuleGraph extends React.Component{
|
||||
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
modelId:'',
|
||||
tData:[],
|
||||
|
||||
loading:true,
|
||||
|
||||
pageNo:1,
|
||||
rowCount:0,
|
||||
|
||||
ruleLabelList:[],
|
||||
countList:[],
|
||||
|
||||
modelList:[],
|
||||
fieldList:[]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// 获取表格数据
|
||||
fetchTableData=(value)=>{
|
||||
this.setState({loading:true});
|
||||
|
||||
FetchUtil('/rule/hitsSort/'+value,'GET',{},
|
||||
(data) => {
|
||||
this.setState({
|
||||
countList:data.data.hits.map((hit)=>{return hit.count}),
|
||||
ruleLabelList:data.data.hits.map((hit)=>{return hit.ruleLable}),
|
||||
tData:data.data.hits,
|
||||
loading:false
|
||||
});
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
this.fetchTableData(this.props.modelId);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.modelId!=this.props.modelId){
|
||||
this.fetchTableData(nextProps.modelId);
|
||||
}
|
||||
}
|
||||
|
||||
handleSelect=(name,value)=>{
|
||||
var state = this.state;
|
||||
state[name] = trim(value);
|
||||
this.setState(state);
|
||||
|
||||
FetchUtil('/rule/hitsSort/'+value,'GET',{},
|
||||
(data) => {
|
||||
console.log(data.data.hits);
|
||||
this.setState({
|
||||
countList:data.data.hits.map((hit)=>{return hit.count}),
|
||||
ruleLabelList:data.data.hits.map((hit)=>{return hit.ruleLable}),
|
||||
tData:data.data.hits
|
||||
});
|
||||
|
||||
this.setState({loading:false});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
render(){
|
||||
|
||||
/*定义表格列*/
|
||||
const columns = [
|
||||
{
|
||||
title: '字段名',
|
||||
dataIndex: 'ruleLable'
|
||||
},
|
||||
{
|
||||
title: '命中数',
|
||||
dataIndex: 'count'
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'handle',
|
||||
render:(t,r)=>{
|
||||
return <Link to={"/ruleid/"+this.props.modelId+"/"+r.id+"/"+r.activationName} target="_blank">查看明细</Link>;
|
||||
}
|
||||
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
|
||||
<div id="echartsMain" style={{width:900,height:400}}></div>
|
||||
<div id="table">
|
||||
<Table
|
||||
dataSource={this.state.tData}
|
||||
columns={columns}
|
||||
size="middle"
|
||||
bordered
|
||||
pagination={false}
|
||||
loading={this.state.loading}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
componentDidUpdate=()=>{
|
||||
// 基于准备好的dom元素,初始化echarts实例
|
||||
let myChart = echarts.init(document.getElementById('echartsMain'));
|
||||
// 绘制图表
|
||||
myChart.setOption({
|
||||
tooltip : {
|
||||
trigger: 'axis',
|
||||
axisPointer : { // 坐标轴指示器,坐标轴触发有效
|
||||
type : 'shadow' // 默认为直线,可选为:'line' | 'shadow'
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
data: ['命中数']
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '3%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: this.state.ruleLabelList
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '命中数',
|
||||
type: 'bar',
|
||||
stack: '总量',
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
position: 'right'
|
||||
}
|
||||
},
|
||||
data: this.state.countList
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Form,Button,Table,Pagination,Input,Select,Modal,DatePicker,Cascader} from 'antd';
|
||||
import moment from 'moment';
|
||||
|
||||
const FormItem=Form.Item;
|
||||
const Option = Select.Option;
|
||||
const RangePicker = DatePicker.RangePicker;
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
import {trim} from '../utils/validateUtil';
|
||||
|
||||
import './ListEvent.less';
|
||||
|
||||
export default class DashBoard extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
modelId:'',
|
||||
loading:true,
|
||||
modelList:[],
|
||||
dashboardUrl:''
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount(){
|
||||
if(!this.props.model.dashboardUrl){
|
||||
Modal.warning({
|
||||
title: '信息提醒',
|
||||
content: '该模型统计报表未初始化!',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(this.props.modelId!=nextProps.modelId&&!nextProps.model.dashboardUrl){
|
||||
Modal.warning({
|
||||
title: '信息提醒',
|
||||
content: '该模型统计报表未初始化!',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<iframe ref="dashBoard" name="dashBoard" src={this.props.model.dashboardUrl} style={{minHeight:'800px',width:'100%',border:'0px'}}></iframe>
|
||||
</div>);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Button,Modal,Tree,Tooltip} from 'antd';
|
||||
|
||||
const TreeNode = Tree.TreeNode;
|
||||
|
||||
import {FetchUtil,fetchVersion} from '../../utils/fetchUtil';
|
||||
|
||||
export default class ExportField extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
loading:false,
|
||||
visible:false,
|
||||
|
||||
selectedKeys:[]
|
||||
};
|
||||
|
||||
console.log(this.props.eventFieldList);
|
||||
}
|
||||
|
||||
|
||||
showModal=()=>{
|
||||
this.setState({
|
||||
visible:true
|
||||
});
|
||||
}
|
||||
|
||||
handleOk=()=>{
|
||||
if(this.state.selectedKeys.length==0){
|
||||
Modal.error({
|
||||
title: '请选择需要导出的字段'
|
||||
});
|
||||
}
|
||||
|
||||
let param={
|
||||
fields:[],
|
||||
preItems:[],
|
||||
activations:[],
|
||||
rules:[]
|
||||
};
|
||||
this.state.selectedKeys.forEach((info)=>{
|
||||
if(info&&info.indexOf('.')!=-1){
|
||||
let arr=info.split('.');
|
||||
param[arr[0]].push(arr[1]);
|
||||
}
|
||||
});
|
||||
FetchUtil('/event/export','POST',JSON.stringify(param),
|
||||
(data) => {
|
||||
var url=fetchVersion+"/event/download";
|
||||
var a = document.createElement('a');
|
||||
var filename = 'download.xlsx';
|
||||
a.href = url;
|
||||
a.download = filename;
|
||||
a.click();
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel=()=>{
|
||||
this.setState({
|
||||
selectedKeys:[],
|
||||
visible:false
|
||||
})
|
||||
}
|
||||
|
||||
onSelect=(selectedKeys)=>{
|
||||
this.setState({ selectedKeys });
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<span>
|
||||
{this.props.disabled?
|
||||
<Tooltip title="导出前请先执行查询!">
|
||||
<Button disabled type="primary" loading={this.state.loading} onClick={this.showModal}>导出</Button>
|
||||
</Tooltip>
|
||||
:<Button type="primary" loading={this.state.loading} onClick={this.showModal}>导出</Button>
|
||||
}
|
||||
<Modal title="选择需要导出的字段" visible={this.state.visible} maskClosable={false} closable={false} onOk={this.handleOk} okText={'导出报表'} onCancel={this.handleCancel}>
|
||||
{this.props.eventFieldList.length==0?'该模型无字段可选':
|
||||
<Tree checkable onCheck={this.onCheck} onCheck={this.onSelect} selectedKeys={this.state.selectedKeys}>
|
||||
{this.props.eventFieldList.map((info,i)=>{
|
||||
return (
|
||||
<TreeNode key={info.value} title={info.label}>
|
||||
{info.children.map((child,i)=>{
|
||||
return <TreeNode key={info.value+'.'+child.value} title={child.label}/>
|
||||
})}
|
||||
</TreeNode>
|
||||
);
|
||||
})}
|
||||
</Tree>
|
||||
}
|
||||
</Modal>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Switch} from 'antd';
|
||||
|
||||
import './Collapse.less';
|
||||
|
||||
export default class Collapse extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
height:0
|
||||
}
|
||||
|
||||
//this.props.handleClick(this);
|
||||
|
||||
}
|
||||
|
||||
slideDown=()=>{
|
||||
if(this.state.height=="auto"){
|
||||
return;
|
||||
}
|
||||
if(this.state.height<this.refs.pChild.offsetHeight){
|
||||
this.setState({
|
||||
height:this.state.height+15
|
||||
},()=>{
|
||||
setTimeout(this.slideDown,1);
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:"auto"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
slideUp=()=>{
|
||||
if(this.state.height=="auto"){
|
||||
this.state.height=this.refs.pChild.offsetHeight;
|
||||
}
|
||||
if(this.state.height>0){
|
||||
this.setState({
|
||||
height:this.state.height-15
|
||||
},()=>{
|
||||
setTimeout(this.slideUp,1);
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleClick=()=>{
|
||||
this.props.handleClick();
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps){
|
||||
if(nextProps.slide){
|
||||
this.slideDown();
|
||||
}
|
||||
else{
|
||||
this.slideUp();
|
||||
}
|
||||
}
|
||||
|
||||
handleDragStart=()=>{
|
||||
console.log(2);
|
||||
}
|
||||
|
||||
switchClick=(e)=>{
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div className="p-block" draggable="true" onDragStart={this.handleDragStart}>
|
||||
<div className={'p-block-titles'+(this.props.slide?' p-block-title-select':'')} onClick={this.handleClick}>
|
||||
<div className='p-block-title-left'>{this.props.title}</div>
|
||||
{this.props.switcher!=undefined?
|
||||
<div className='p-block-title-right' onClick={this.switchClick}><Switch /></div>
|
||||
:''}
|
||||
</div>
|
||||
<div className={'p-block-contents'+(this.props.slide?' p-block-content-select':'')} style={{height:this.state.height}} ref="pContent">
|
||||
<div ref="pChild" className="p-block-main">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
.p-block{
|
||||
margin-bottom:8px;
|
||||
}
|
||||
|
||||
.p-block-titles{
|
||||
height: 40px;
|
||||
border:1px solid #d9d9d9;
|
||||
padding-left: 30px;
|
||||
cursor:pointer;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
.p-block-titles:hover{
|
||||
background-color:#FAFAFA;
|
||||
}
|
||||
|
||||
.p-block-title-left{
|
||||
float:left;
|
||||
line-height:38px;
|
||||
}
|
||||
|
||||
.p-block-title-right{
|
||||
float:right;
|
||||
line-height:34px;
|
||||
margin-right:20px;
|
||||
}
|
||||
|
||||
.p-block-title-select{
|
||||
background-color:#f7f7f7;
|
||||
border-bottom-right-radius:0;
|
||||
border-bottom-left-radius:0;
|
||||
border-bottom:none;
|
||||
}
|
||||
|
||||
.p-block-contents{
|
||||
clear:both;
|
||||
background-color:white;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.p-block-content-select{
|
||||
border:1px solid #d9d9d9;
|
||||
border-top:none;
|
||||
}
|
||||
|
||||
.p-block-main{
|
||||
padding:20px
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
export default class CollapseGroup extends React.Component{
|
||||
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
activeKey:'',
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getItems=()=>{
|
||||
return this.props.children.map((child,index)=>{
|
||||
const key=child.key;
|
||||
const props={
|
||||
slide:child.key==this.state.activeKey?true:false,
|
||||
index:index,
|
||||
|
||||
handleClick:()=>{
|
||||
if(this.state.activeKey==key){
|
||||
this.setState({
|
||||
activeKey:''
|
||||
})
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
activeKey:key
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return React.cloneElement(child,props);
|
||||
})
|
||||
}
|
||||
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
{this.getItems()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
import React from 'react';
|
||||
import {Icon,Popover} from 'antd';
|
||||
|
||||
import CollapseGroup from './CollapseGroup';
|
||||
import Collapse from './Collapse';
|
||||
|
||||
import './Test.less';
|
||||
|
||||
import {FetchUtil} from '../utils/fetchUtil';
|
||||
|
||||
export default class Test extends React.Component{
|
||||
constructor(props){
|
||||
super(props);
|
||||
|
||||
this.state={
|
||||
slide:false,
|
||||
height:0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
slideDown=()=>{
|
||||
if(this.state.height<this.refs.pChild.offsetHeight){
|
||||
this.setState({
|
||||
height:this.state.height+=5
|
||||
})
|
||||
setTimeout(this.slideDown,10);
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:"auto",
|
||||
slide:true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
slideUp=()=>{
|
||||
if(this.state.height>0){
|
||||
this.setState({
|
||||
height:this.state.height-=5
|
||||
})
|
||||
setTimeout(this.slideUp,10);
|
||||
}
|
||||
else{
|
||||
this.setState({
|
||||
height:0,
|
||||
slide:false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
handleClick=()=>{
|
||||
// if(this.state.slide==false){
|
||||
// this.slideDown();
|
||||
// }
|
||||
// else{
|
||||
// let height=this.refs.pContent.clientHeight;
|
||||
// this.setState({
|
||||
// height:height
|
||||
// },this.slideUp)
|
||||
// }
|
||||
|
||||
// this.setState({
|
||||
// slide:!this.state.slide
|
||||
// })
|
||||
}
|
||||
|
||||
render(){
|
||||
var content=<span>hello world</span>;
|
||||
return (
|
||||
<div className="ant-layout-content">
|
||||
<CollapseGroup>
|
||||
<Collapse key="a" title="a" ><div>ad<br/>asfdasdflasdf</div></Collapse>
|
||||
<Collapse key="b" title="b"><div>bd</div></Collapse>
|
||||
<Collapse key="c" title="c"><div>cd</div></Collapse>
|
||||
</CollapseGroup>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
.p-block-title{
|
||||
height: 40px;
|
||||
border:1px solid #d9d9d9;
|
||||
line-height: 40px;
|
||||
padding-left: 30px;
|
||||
cursor:pointer;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.p-block-title:hover{
|
||||
background-color:#f7f7f7;
|
||||
}
|
||||
|
||||
.p-block-content{
|
||||
border:1px solid #d9d9d9;
|
||||
background-color:white;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
import {Modal,message} from 'antd';
|
||||
import 'whatwg-fetch';
|
||||
// import 'es6-promise/dist/es6-promise.min.js';
|
||||
import 'fetch-ie8/fetch.js';
|
||||
|
||||
export var fetchVersion='/services/v1';
|
||||
|
||||
export var FetchUtil=function(url,method,param,callback,done=()=>{}){
|
||||
let config={
|
||||
credentials: 'include',
|
||||
headers:{
|
||||
"x-auth-token": localStorage.getItem('x-auth-token')
|
||||
}
|
||||
};
|
||||
let hide=null;
|
||||
console.log(param,'=====')
|
||||
if(method!='GET'){
|
||||
config.method=method;
|
||||
config.headers['Content-Type']="application/json"
|
||||
config.body=param;
|
||||
hide = message.loading('正在执行中...', 0);
|
||||
}
|
||||
return fetch(fetchVersion+url,config)
|
||||
.then((res) => {
|
||||
if(method!='GET'){hide();}
|
||||
if(res.ok){
|
||||
return res.json();
|
||||
}
|
||||
else{
|
||||
if(window.modal==undefined){
|
||||
window.modal=Modal.error({
|
||||
title: '系统错误',
|
||||
content: '请检查是否有参数配置错误',
|
||||
onOk:()=>{
|
||||
window.modal=undefined;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.then((data)=>{
|
||||
if(!data.success&&data.code.indexOf('60')!==-1){
|
||||
if(window.modal==undefined){
|
||||
window.modal=Modal.error({
|
||||
title: '您尚未登录',
|
||||
content: '请返回登录页面重新登录',
|
||||
onOk:()=>{
|
||||
window.modal=undefined;
|
||||
window.location.href="#/login";
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else if(!data.success){
|
||||
if(window.modal==undefined){
|
||||
window.modal=Modal.error({
|
||||
title: '系统错误',
|
||||
content: data.msg,
|
||||
});
|
||||
}
|
||||
}
|
||||
else{
|
||||
callback(data);
|
||||
}
|
||||
done();
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e.message);
|
||||
});
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
function getIndent(level) {
|
||||
var result = "";
|
||||
for (var i = 0; i < level; i++) {
|
||||
result = result + " ";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getExpression(expreObject) {
|
||||
if(!expreObject){
|
||||
return null;
|
||||
}
|
||||
var className = expreObject["class"];
|
||||
var type = expreObject["type"];
|
||||
var column = expreObject["column"];
|
||||
var value = expreObject["value"];
|
||||
//console.log(expreObject);
|
||||
//console.log(value);
|
||||
if (className == "ENTATTR") // 选择的数据类型
|
||||
return "data." + column;
|
||||
else if (className == "CONST") {
|
||||
if (type == "STRING") {
|
||||
return "'" + value + "'";
|
||||
} else if (type == "DOUBLE") {
|
||||
return "" + value;
|
||||
} else {
|
||||
return "" + value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function processRule(ruleObject, level) {
|
||||
var className = ruleObject["class"];
|
||||
var enabled = ruleObject["enabled"];
|
||||
var operator = ruleObject["operator"];
|
||||
var expressions = ruleObject["expressions"];
|
||||
if (className == "PDCT") {
|
||||
return processRules(ruleObject, level + 1);
|
||||
}
|
||||
// if (operator=="Equal") {
|
||||
// return getExpression(expressions[0]) + "==" + getExpression(expressions[1]);
|
||||
// } else if (operator=="InList") {
|
||||
// return getExpression(expressions[0]) + " in blackList["+getExpression(expressions[1])+"]";
|
||||
// } else if (operator=="IsNull") {
|
||||
// return getExpression(expressions[0]) + " is null";
|
||||
// } else if (operator=="Field_Equal") {
|
||||
// return getExpression(expressions[0]) + "==" + getExpression(expressions[1]);
|
||||
// } else if (operator=="StartsWith") {
|
||||
// return getExpression(expressions[0]) + ".startsWith("+getExpression(expressions[1])+")";
|
||||
// }
|
||||
//console.log(ruleObject);
|
||||
switch (operator) {
|
||||
case "StartsWith":
|
||||
return getExpression(expressions[0]) + ".startsWith(" + getExpression(expressions[1]) + ")";
|
||||
case "NotStartsWith":
|
||||
return "!" + getExpression(expressions[0]) + ".startsWith(" + getExpression(expressions[1]) + ")";
|
||||
case "Contains":
|
||||
return getExpression(expressions[0]) + ".contains(" + getExpression(expressions[1]) + ")";
|
||||
case "NotContains":
|
||||
return "!" + getExpression(expressions[0]) + ".contains(" + getExpression(expressions[1]) + ")";
|
||||
case "Equal":
|
||||
case "Field_Equal":
|
||||
return getExpression(expressions[0]) + "==" + getExpression(expressions[1]);
|
||||
case "NotEqual":
|
||||
case "Field_Not_Equal":
|
||||
return getExpression(expressions[0]) + "!=" + getExpression(expressions[1]);
|
||||
case "Less":
|
||||
case "Field_Less":
|
||||
return getExpression(expressions[0]) + "<" + getExpression(expressions[1]);
|
||||
case "Less_Equal":
|
||||
case "Field_Less_Equal":
|
||||
return getExpression(expressions[0]) + "<=" + getExpression(expressions[1]);
|
||||
case "Greater":
|
||||
case "Field_Greater":
|
||||
return getExpression(expressions[0]) + ">" + getExpression(expressions[1]);
|
||||
case "Greater_Equal":
|
||||
case "Field_Greater_Equal":
|
||||
return getExpression(expressions[0]) + ">=" + getExpression(expressions[1]);
|
||||
case "InList":
|
||||
return "lists." + getExpression(expressions[1]) + ".containsKey(" + getExpression(expressions[0]) + ")";
|
||||
case "NotInList":
|
||||
return "!lists." + getExpression(expressions[1]) + ".containsKey(" + getExpression(expressions[0]) + ")";
|
||||
case "IsNull":
|
||||
return "!" + getExpression(expressions[0]);
|
||||
case "IsNotNull":
|
||||
return getExpression(expressions[0]);
|
||||
}
|
||||
}
|
||||
|
||||
function processRules(jsonObject, level) {
|
||||
var className = jsonObject["class"];
|
||||
var enabled = jsonObject["enabled"];
|
||||
var linking = jsonObject["linking"];
|
||||
var conditions = jsonObject["conditions"];
|
||||
var length = conditions.length;
|
||||
var result="";
|
||||
if (linking == "NotAll" || linking == "None") {
|
||||
result += "!";
|
||||
}
|
||||
result += "(";
|
||||
for (var i in conditions) {
|
||||
result = result + processRule(conditions[i], level);
|
||||
if (i != length - 1) {
|
||||
// if (linking=="All") {
|
||||
// result = result + "\n"+getIndent(level)+"and ";
|
||||
// } else if (linking=="Any") {
|
||||
// result = result + "\n"+getIndent(level)+"or ";
|
||||
// }
|
||||
switch (linking) {
|
||||
case "All":
|
||||
case "NotAll":
|
||||
result += "&&";
|
||||
break;
|
||||
case "Any":
|
||||
case "None":
|
||||
result += "||";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result + ")";
|
||||
}
|
||||
|
||||
export var generateScript = function(jsonObject, className) {
|
||||
if(jsonObject==null){
|
||||
return '';
|
||||
}
|
||||
var script = "class " + className + "CheckScript {" + "\n";
|
||||
script += " public boolean check(def data, def lists) {";
|
||||
script += " if (" + processRules(jsonObject, 1) + ")\n";
|
||||
script += " return true;" + "\n";
|
||||
script += " else" + "\n";
|
||||
script += " return false;" + "\n";
|
||||
script += "}";
|
||||
script += "}";
|
||||
return script;
|
||||
}
|
||||
|
||||
export let validateRules = function(jsonObject) {
|
||||
if(jsonObject==null){
|
||||
return true;
|
||||
}
|
||||
|
||||
let conditions = jsonObject["conditions"];
|
||||
for (let i in conditions) {
|
||||
if(!validateRule(conditions[i])){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function validateRule(ruleObject){
|
||||
var className = ruleObject["class"];
|
||||
var operator = ruleObject["operator"];
|
||||
var expressions = ruleObject["expressions"];
|
||||
if (className == "PDCT") {
|
||||
return validateRules(ruleObject);
|
||||
}
|
||||
|
||||
if(!operator){
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (operator) {
|
||||
case "StartsWith":
|
||||
case "NotStartsWith":
|
||||
case "Contains":
|
||||
case "NotContains":
|
||||
case "Equal":
|
||||
case "Field_Equal":
|
||||
case "NotEqual":
|
||||
case "Field_Not_Equal":
|
||||
case "Less":
|
||||
case "Field_Less":
|
||||
case "Less_Equal":
|
||||
case "Field_Less_Equal":
|
||||
case "Greater":
|
||||
case "Field_Greater":
|
||||
case "Greater_Equal":
|
||||
case "Field_Greater_Equal":
|
||||
case "InList":
|
||||
case "NotInList":
|
||||
return getExpression(expressions[1])&&getExpression(expressions[0]);
|
||||
case "IsNull":
|
||||
case "IsNotNull":
|
||||
return getExpression(expressions[0])&&true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
export var Operator = {
|
||||
StartsWith:{label:'以...开始',value:'StartsWith',nextType:'input'},
|
||||
Contains:{label:'包含',value:'Contains',nextType:'input'},
|
||||
Equal : {label:'等于',value:'Equal',nextType:'input'},
|
||||
Less : {label:'小于',value:'Less',nextType:'input'},
|
||||
Less_Equal : {label:'小于等于',value:'Less_Equal',nextType:'input'},
|
||||
Greater : {label:'大于',value:'Greater',nextType:'input'},
|
||||
Greater_Equal : {label:'大于等于',value:'Greater_Equal',nextType:'input'},
|
||||
InList : {label:'在列表...中',value:'InList',nextType:'list'},
|
||||
NotStartsWith : {label:'不以...开始',value:'NotStartsWith',nextType:'input'},
|
||||
NotContains : {label:'不包含',value:'NotContains',nextType:'input'},
|
||||
NotEqual : {label:'不等于',value:'NotEqual',nextType:'input'},
|
||||
NotInList : {label:'不在列表...中',value:'NotInList',nextType:'list'},
|
||||
IsNull : {label:'为空',value:'IsNull',nextType:'empty'},
|
||||
IsNotNull : {label:'不为空',value:'IsNotNull',nextType:'empty'},
|
||||
Field_Greater : {label:'大于(字段)',value:'Field_Greater',nextType:'field'},
|
||||
Field_Less : {label:'小于(字段)',value:'Field_Less',nextType:'field'},
|
||||
Field_Greater_Equal : {label:'大于等于(字段)',value:'Field_Greater_Equal',nextType:'field'},
|
||||
Field_Less_Equal : {label:'小于等于(字段)',value:'Field_Less_Equal',nextType:'field'},
|
||||
Field_Equal : {label:'等于(字段)',value:'Field_Equal',nextType:'field'},
|
||||
Field_Not_Equal : {label:'不等于(字段)',value:'Field_Not_Equal',nextType:'field'}
|
||||
};
|
||||
|
||||
/*nextType:{
|
||||
input,list,empty,field
|
||||
}
|
||||
*/
|
||||
|
||||
export var operatorMap={
|
||||
'STRING':[
|
||||
Operator.StartsWith,
|
||||
Operator.NotStartsWith,
|
||||
Operator.Contains,
|
||||
Operator.NotContains,
|
||||
Operator.Equal,
|
||||
Operator.NotEqual,
|
||||
Operator.InList,
|
||||
Operator.NotInList,
|
||||
Operator.IsNull,
|
||||
Operator.IsNotNull,
|
||||
Operator.Field_Equal,
|
||||
Operator.Field_Not_Equal
|
||||
],
|
||||
'INTEGER':[
|
||||
Operator.Equal,
|
||||
Operator.NotEqual,
|
||||
Operator.InList,
|
||||
Operator.NotInList,
|
||||
Operator.Less,
|
||||
Operator.Less_Equal,
|
||||
Operator.Greater,
|
||||
Operator.Greater_Equal,
|
||||
Operator.IsNull,
|
||||
Operator.IsNotNull,
|
||||
Operator.Field_Greater,
|
||||
Operator.Field_Less,
|
||||
Operator.Field_Greater_Equal,
|
||||
Operator.Field_Less_Equal,
|
||||
Operator.Field_Equal,
|
||||
Operator.Field_Not_Equal
|
||||
],
|
||||
'DOUBLE':[
|
||||
Operator.Equal,
|
||||
Operator.NotEqual,
|
||||
Operator.InList,
|
||||
Operator.NotInList,
|
||||
Operator.Less,
|
||||
Operator.Less_Equal,
|
||||
Operator.Greater,
|
||||
Operator.Greater_Equal,
|
||||
Operator.IsNull,
|
||||
Operator.IsNotNull,
|
||||
Operator.Field_Greater,
|
||||
Operator.Field_Less,
|
||||
Operator.Field_Greater_Equal,
|
||||
Operator.Field_Less_Equal,
|
||||
Operator.Field_Equal,
|
||||
Operator.Field_Not_Equal
|
||||
],
|
||||
'LONG':[
|
||||
Operator.Equal,
|
||||
Operator.NotEqual,
|
||||
Operator.InList,
|
||||
Operator.NotInList,
|
||||
Operator.Less,
|
||||
Operator.Less_Equal,
|
||||
Operator.Greater,
|
||||
Operator.Greater_Equal,
|
||||
Operator.IsNull,
|
||||
Operator.IsNotNull,
|
||||
Operator.Field_Greater,
|
||||
Operator.Field_Less,
|
||||
Operator.Field_Greater_Equal,
|
||||
Operator.Field_Less_Equal,
|
||||
Operator.Field_Equal,
|
||||
Operator.Field_Not_Equal
|
||||
],
|
||||
'':[]
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
export var trim=function(str){
|
||||
return str.replace(/(^\s*)|(\s*$)/g, "");
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>风控引擎管理平台</title>
|
||||
<link rel="shortcut icon" href="/images/anquan.png">
|
||||
<!-- <link rel="stylesheet" href="dist/style.css"> -->
|
||||
<!-- Polyfills -->
|
||||
<!--[if lt IE 10]>
|
||||
<script src="https://as.alipayobjects.com/g/component/??console-polyfill/0.2.2/index.js,es5-shim/4.5.7/es5-shim.min.js,es5-shim/4.5.7/es5-sham.min.js,html5shiv/3.7.2/html5shiv.min.js,media-match/2.0.2/media.match.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<div id="react-content"></div>
|
||||
|
||||
<!-- <script src="dist/common.js"></script>
|
||||
<script src="dist/main.bundle.js"></script> -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,129 +0,0 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, Link, hashHistory,browserHistory,IndexRoute,IndexRedirect } from 'react-router';
|
||||
|
||||
import Abstraction from './component/abstraction/Abstraction';
|
||||
import AbstractionList from './component/abstraction/AbstractionList';
|
||||
import Activation from './component/activation/Activation';
|
||||
import Datalist from './component/datalist/Datalist';
|
||||
import DatalistRecord from './component/datalist/DatalistRecord';
|
||||
import Field from './component/field/Field';
|
||||
import ModelList from './component/model/ModelList';
|
||||
import Model from './component/model/Model';
|
||||
import PreItem from './component/preItem/PreItem';
|
||||
import RuleList from './component/activation/RuleList';
|
||||
import HistoryRecordList from './component/activation/HistoryRecordList';
|
||||
|
||||
import Report from './component/report/Report';
|
||||
import ListEvent from './component/report/ListEvent';
|
||||
import RuleGraph from './component/report/RuleGraph';
|
||||
import ListRule from './component/report/ListRule';
|
||||
import Rule from './component/report/ListRule';
|
||||
import DashBoard from './component/report/DashBoard';
|
||||
import ConfigCenter from './component/config/ConfigCenter';
|
||||
import ModelConfig from './component/modelconfig/ModelConfig';
|
||||
|
||||
//import Test from './component/test/Test';
|
||||
|
||||
import Index from './component/Index';
|
||||
import Login from './component/Login';
|
||||
|
||||
// 引入Ant-Design样式 & Animate.CSS样式
|
||||
import 'antd/dist/antd.min.css';
|
||||
import 'animate.css/animate.min.css';
|
||||
|
||||
import './main.less';
|
||||
|
||||
class NotFound extends React.Component{
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className="ibox">
|
||||
<div className="ibox-content">
|
||||
<div style={{
|
||||
width:450,margin:"200px auto",fontSize:26
|
||||
}}>功能尚未完成或页面未找到,敬请期待</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class Welcome extends React.Component{
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<div className="ibox">
|
||||
<div className="ibox-content">
|
||||
<h2>欢迎登录风控引擎管理平台!</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
class App extends React.Component{
|
||||
render(){
|
||||
return (
|
||||
<div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AppRoutes extends React.Component{
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Router history={hashHistory}>
|
||||
<Route path="/" component={App} >
|
||||
<IndexRedirect to="login"/>
|
||||
<Route path="/welcome" component={Welcome}>
|
||||
</Route>
|
||||
<Route path="/login" component={Login}>
|
||||
</Route>
|
||||
<Route path="/index" component={Index}>
|
||||
<Route path="/modelList" component={ModelList}/>
|
||||
<Route path="/model/:id" component={Model}>
|
||||
<IndexRedirect to="/field/:id"/>
|
||||
<Route path="/field/:id" component={Field}/>
|
||||
<Route path="/activation/:id" component={Activation}/>
|
||||
<Route path="/datalist/:id" component={Datalist}/>
|
||||
<Route path="/datalistRecord/:id/:datalistId" component={DatalistRecord}/>
|
||||
<Route path="/preItem/:id" component={PreItem}/>
|
||||
<Route path="/ruleList/:id/:activationId" component={RuleList}/>
|
||||
<Route path="/historyRecordList/:id/:activationId/:ruleId" component={HistoryRecordList}/>
|
||||
<Route path="/abstractionList/:id" component={AbstractionList}/>
|
||||
<Route path="/modelConfig/:id" component={ModelConfig}/>
|
||||
|
||||
{/*<Route path="/test/:id" component={Test}/>*/}
|
||||
</Route>
|
||||
|
||||
<Route path="/report" component={Report}>
|
||||
<IndexRedirect to="/event"/>
|
||||
<Route path="/event" component={ListEvent}/>
|
||||
<Route path="/graph" component={RuleGraph}/>
|
||||
<Route path="/rule" component={ListRule}/>
|
||||
<Route path="/ruleid/:modelId/:ruleId/:activationName" component={ListEvent}/>
|
||||
<Route path="/dashboard" component={DashBoard}/>
|
||||
|
||||
</Route>
|
||||
<Route path="/config" component={ConfigCenter}>
|
||||
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" component={Index}>
|
||||
<IndexRoute component={NotFound} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Router>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
<AppRoutes />
|
||||
, document.getElementById("react-content"));
|
||||
@@ -1,14 +0,0 @@
|
||||
body{
|
||||
margin:0;
|
||||
padding:0;
|
||||
|
||||
}
|
||||
|
||||
html,body{
|
||||
height:100%;
|
||||
background: #ececec;
|
||||
}
|
||||
|
||||
#react-content{
|
||||
height:100%;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
const path = require('path');
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const autoprefixer = require('autoprefixer');
|
||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // MINI CSS
|
||||
const CSSSplitWebpackPlugin = require('css-split-webpack-plugin').default;
|
||||
function assetsPath(_path) {
|
||||
return path.posix.join('static', _path);
|
||||
}
|
||||
|
||||
const config = {
|
||||
context: path.resolve(),
|
||||
resolve: {
|
||||
extensions: ['.js', '.json', '.jsx'],
|
||||
alias: {
|
||||
'@': path.resolve('./src')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js|jsx)$/,
|
||||
loader: 'eslint-loader',
|
||||
enforce: 'pre',
|
||||
include: [path.resolve('./src'), path.resolve('./test')],
|
||||
options: {
|
||||
formatter: require('eslint-friendly-formatter')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(sa|sc|c)ss$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
'sass-loader',
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
ident: 'postcss',
|
||||
plugins: () => [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
autoprefixer({
|
||||
browsers: [
|
||||
'>1%',
|
||||
'last 4 versions',
|
||||
'Firefox ESR',
|
||||
'not ie < 9' // React doesn't support IE8 anyway
|
||||
],
|
||||
flexbox: 'no-2009'
|
||||
})
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.less$/,
|
||||
use: [{
|
||||
loader: 'style-loader',
|
||||
}, {
|
||||
loader: 'css-loader', // translates CSS into CommonJS
|
||||
}, {
|
||||
loader: 'less-loader', // compiles Less to CSS
|
||||
options: {
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
}],
|
||||
},
|
||||
{
|
||||
test: /\.js|jsx$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: ['@babel/env', '@babel/preset-react'],
|
||||
plugins: [
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
"@babel/plugin-proposal-export-default-from"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'html-loader',
|
||||
options: { minimize: true }
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: assetsPath('media/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
|
||||
loader: 'url-loader',
|
||||
options: {
|
||||
limit: 10000,
|
||||
name: assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new CleanWebpackPlugin(['dist', 'build'], {
|
||||
root: path.resolve(),
|
||||
verbose: true,
|
||||
dry: false
|
||||
}),
|
||||
new CSSSplitWebpackPlugin({
|
||||
size: 3000
|
||||
})
|
||||
],
|
||||
// 生产
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new OptimizeCSSAssetsPlugin({
|
||||
cssProcessor: require('cssnano')({
|
||||
reduceIdents: false,
|
||||
// 避免 cssnano 重新计算 z-index
|
||||
safe: true
|
||||
})
|
||||
})
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
@@ -1,86 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const portfinder = require('portfinder');
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
|
||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const baseWebpackConfig = require('./webpack.config.base.js');
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
devtool: 'cheap-module-source-map',
|
||||
entry: ['@babel/polyfill', './src/index.jsx'],
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: 'app.bundle.js'
|
||||
},
|
||||
devServer: {
|
||||
contentBase: path.join(__dirname, 'dist'),
|
||||
port: 3000,
|
||||
disableHostCheck: true,
|
||||
host: 'localhost',
|
||||
compress: true,
|
||||
inline: true,
|
||||
hot: true,
|
||||
overlay: true,
|
||||
disableHostCheck: true, // 新增该配置项
|
||||
proxy: [{
|
||||
context: ["/services/v1/"],
|
||||
target: "http://localhost:8080",
|
||||
changeOrigin: true,
|
||||
secure: false,
|
||||
onProxyRes: function(proxyRes, req, res) { //
|
||||
// console.log(proxyRes)
|
||||
let proxyHost = proxyRes.req.getHeader('host');
|
||||
let proxyPath = proxyRes.req.path;
|
||||
//console.log(host, path)
|
||||
console.log(`Proxy ${req.get('host')}${req.path} -> ${proxyHost}${proxyPath}`)
|
||||
}
|
||||
}]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
// filename: devMode ? '[name].css' : '[name].[hash].css',
|
||||
// chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
|
||||
filename: 'index.[hash:8].css',
|
||||
// chunkFilename: '[id].[chunkhash].css'
|
||||
}),
|
||||
new HtmlWebPackPlugin({
|
||||
template: path.resolve('./src/index.html'),
|
||||
filename: './index.html'
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'SERVICE_URL': JSON.stringify("http://localhost:3000")
|
||||
})
|
||||
],
|
||||
mode: 'development'
|
||||
});
|
||||
|
||||
|
||||
module.exports = new Promise((resolve, reject) => {
|
||||
portfinder.basePort = process.env.PORT || devWebpackConfig.devServer.port;
|
||||
portfinder.getPort((err, port) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
// publish the new Port, necessary for e2e tests
|
||||
process.env.PORT = port;
|
||||
// add port to devServer config
|
||||
devWebpackConfig.devServer.port = port;
|
||||
|
||||
// Add FriendlyErrorsPlugin
|
||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`]
|
||||
}
|
||||
}));
|
||||
|
||||
resolve(devWebpackConfig);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
exports.config = devWebpackConfig;
|
||||
@@ -1,55 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const HtmlWebPackPlugin = require('html-webpack-plugin');
|
||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
|
||||
const baseWebpackConfig = require('./webpack.config.base.js');
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
entry: ['@babel/polyfill', './src/index.jsx'],
|
||||
externals:{},
|
||||
output: {
|
||||
path: path.resolve('dist'),
|
||||
filename: '[name].[hash:8].js',
|
||||
publicPath: './',
|
||||
libraryTarget: 'umd'
|
||||
},
|
||||
plugins: [
|
||||
new UglifyJSPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false,
|
||||
drop_debugger: true,
|
||||
drop_console: true
|
||||
},
|
||||
sourceMap: true
|
||||
}
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
// Options similar to the same options in webpackOptions.output
|
||||
// both options are optional
|
||||
// filename: devMode ? '[name].css' : '[name].[hash].css',
|
||||
// chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
|
||||
filename: 'index.[hash:8].css',
|
||||
// chunkFilename: '[id].[chunkhash].css'
|
||||
}),
|
||||
new HtmlWebPackPlugin({
|
||||
template: path.resolve('./src/index.html'),
|
||||
filename: './index.html',
|
||||
minify: {
|
||||
// 压缩HTML文件
|
||||
removeComments: true, // 移除HTML中的注释
|
||||
collapseWhitespace: false // 删除空白符与换行符
|
||||
}
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
'SERVICE_URL': JSON.stringify("")
|
||||
})
|
||||
],
|
||||
mode: 'production'
|
||||
});
|
||||
|
||||
|
||||
module.exports = webpackConfig;
|
||||
8939
webapp/yarn.lock
8939
webapp/yarn.lock
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user