feats: 机器学习配置前端页面

Signed-off-by: feihu.wang <wfh45678@163.com>
This commit is contained in:
feihu.wang
2020-01-06 19:52:45 +08:00
parent f4ccc6b408
commit 10f09a0641
6 changed files with 672 additions and 2 deletions

View File

@@ -33,6 +33,10 @@ export default class Index extends React.Component{
<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>

View File

@@ -0,0 +1,50 @@
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>&nbsp;</p>
<Link >进入配置</Link>
</Card>
</Col>
<Col span={6}>
<Card title="待开发" extra={<a >More</a>} style={{ width: 300 }}>
<p>待开发</p>
<p>&nbsp;</p>
</Card>
</Col>
<Col span={6} />
<Col span={6} />
</Row>
<Row>
</Row>
</div>
</div>
);
}
}

View File

@@ -0,0 +1,280 @@
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>
);
}
}

View File

@@ -71,6 +71,8 @@ export default class Model extends React.Component{
case 'ruleList':
case 'historyRecordList':
key='activation';break;
case 'modelConfig':
key='modelConfig';break;
}
this.setState({
current:key
@@ -186,6 +188,11 @@ export default class Model extends React.Component{
<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>

View File

@@ -0,0 +1,320 @@
import React from 'react';
import {Breadcrumb, Menu, Icon, Form, Upload, Input, Select, Card, Row, Col,Button, Tooltip, Tag, message} from 'antd';
const FormItem=Form.Item;
const Option = Select.Option;
import {FetchUtil} from '../utils/fetchUtil';
export default class ModelConfig extends React.Component{
constructor(props){
super(props);
this.state={
visible:false,
plugin:'TENSOR_DNN',
status:1,
args:'',
tags: ['argx=1', 'argy=2', 'argz=3'],
inputVisible: false,
inputValue: '',
pageNo:1,
rowCount:0,
model: null,
modelConfig: null,
name: "",
type: "",
path: "",
comment:"",
absColumns: [],
selectCols: [],
fileList:[],
paramsList:[],
}
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({
name: modelConfig.name,
type: modelConfig.type,
path: modelConfig.path,
comment: modelConfig.comment,
selectCols: selectCols,
paramsList: modelConfig.params,
fileList: [{
uid: -1,
name: modelConfig.path,
status: 'done',
}],
});
});
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(value) {
//console.log(`Selected: ${value}`);
}
uploadHandleChange = (info) => {
let fileList = info.fileList;
fileList = fileList.slice(-1);
this.setState({ fileList });
}
saveInputRef = input => this.input = input
render() {
const plugin=this.state.plugin;
const { tags,path, inputVisible, inputValue, paramsList} = this.state;
console.log("cols==", this.state.selectCols);
console.log("path==", path);
const uploadProps = {
name: 'file',
data: {"dataListId": ""},
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={
plugin:{
help:'',
status:'success'
},
label:{
help:'',
status:'success'
},
sourceField:{
help:'',
status:'success'
},
args:{
help:'',
status:'success'
}
};
return (
<div className="ant-layout-wrapper">
<div className="ant-layout-breadcrumb">
<Breadcrumb>
<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="name" value={this.state.name} 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} >
<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:"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>
<Select
mode="tags"
size={'default'}
placeholder="Please select"
value={this.state.selectCols}
onChange={this.handleChange}
style={{ width: '100%' }}
>
{this.state.absColumns}
</Select>
</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 {...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"}} help={validate.args.help} validateStatus={validate.args.status}>
<Row>
<Col span={20}>
<Input.TextArea name="comment" value={this.state.comment} 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>
<FormItem {...formItemLayout} label="模型入参">
{
paramsList.map(item => {
const selected = item.expressions.replace(/abstractions./g,"").split(",");
const rows = (<Row>
<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}
onChange={this.handleChange}
style={{ width: '100%' }}
>
{this.state.absColumns}
</Select>
</div>
</Col>
</Row>);
return rows;
})
}
</FormItem>
</Form>
</div>
</div>
);
}
}

View File

@@ -20,7 +20,9 @@ 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 LearningConfig from './component/config/LearningConfig';
import ModelConfig from './component/modelconfig/ModelConfig';
//import Test from './component/test/Test';
@@ -96,6 +98,7 @@ class AppRoutes extends React.Component{
<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>
@@ -108,7 +111,13 @@ class AppRoutes extends React.Component{
<Route path="/ruleid/:modelId/:ruleId/:activationName" component={ListEvent}/>
<Route path="/dashboard" component={DashBoard}/>
</Route>
</Route>
<Route path="/config" component={ConfigCenter}>
</Route>
<Route path="/learningConfig" component={LearningConfig}>
</Route>
</Route>
<Route path="*" component={Index}>
<IndexRoute component={NotFound} />