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

Signed-off-by: feihu.wang <wfh45678@163.com>
This commit is contained in:
feihu.wang
2020-01-11 11:39:09 +08:00
parent 10f09a0641
commit 4681b7e8ee
5 changed files with 427 additions and 53 deletions

View File

@@ -31,7 +31,7 @@ export default class ConfigCenter extends React.Component{
<Card title="待开发" extra={<a >More</a>} style={{ width: 300 }}>
<p>待开发</p>
<p>&nbsp;</p>
<Link >进入配置</Link>
</Card>
</Col>
<Col span={6} />

View File

@@ -187,7 +187,7 @@ export default class ModelList extends React.Component{
<div className="ant-layout-container">
<div className="ant-layout-content">
<div id="header">
<Form inline>
<Form layout="inline">
<FormItem label="模型名:">
<Input value={this.state.modelName} name="modelName" id="blue" onChange={this.handleChange}/>
</FormItem>

View File

@@ -1,10 +1,13 @@
import React from 'react';
import {Breadcrumb, Menu, Icon, Form, Upload, Input, Select, Card, Row, Col,Button, Tooltip, Tag, message} from 'antd';
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){
@@ -12,27 +15,37 @@ export default class ModelConfig extends React.Component{
this.state={
visible:false,
plugin:'TENSOR_DNN',
id : -1,
status:1,
args:'',
tags: ['argx=1', 'argy=2', 'argz=3'],
inputVisible: false,
inputValue: '',
pageNo:1,
rowCount:0,
model: null,
modelConfig: null,
name: "",
type: "",
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;
@@ -40,10 +53,14 @@ export default class ModelConfig extends React.Component{
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: [{
@@ -51,6 +68,7 @@ export default class ModelConfig extends React.Component{
name: modelConfig.path,
status: 'done',
}],
feed: paramVO.feed,
});
});
@@ -84,9 +102,9 @@ export default class ModelConfig extends React.Component{
handleInputChange = (e) => {
this.setState({ inputValue: e.target.value });
}
// handleInputChange = (e) => {
// this.setState({ inputValue: e.target.value });
// }
@@ -107,26 +125,79 @@ export default class ModelConfig extends React.Component{
handleChange(value) {
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;
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: {"dataListId": ""},
data: {"key": "machine"},
action: '/services/v1/common/upload',
headers: {
"x-auth-token": localStorage.getItem('x-auth-token'),
@@ -139,24 +210,81 @@ export default class ModelConfig extends React.Component{
wrapperCol: { span: 16 },
};
let validate={
plugin:{
name:{
help:'',
status:'success'
},
label:{
tag:{
help:'',
status:'success'
},
sourceField:{
operation:{
help:'',
status:'success'
},
args:{
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">
@@ -166,11 +294,11 @@ export default class ModelConfig extends React.Component{
</div>
<div className="ant-layout-container">
<Form horizontal form={this.props.form}>
<FormItem required={true} {...formItemLayout} label="模型名称:" >
<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="请输入模型名称"/>
<Input type="text" name="name" value={this.state.name} placeholder="请输入模型名称" onChange={this.handlInputChange}/>
</Col>
<Col span={2} offset={1}>
<Tooltip placement="right" title={'机器学习模型名称'}>
@@ -180,7 +308,7 @@ export default class ModelConfig extends React.Component{
</Row>
</FormItem>
<FormItem required={true} {...formItemLayout} label="学习框架:" help={validate.plugin.help} >
<FormItem required={true} {...formItemLayout} label="学习框架:" >
<Row>
<Col span={20} >
<Select value={this.state.type}>
@@ -195,7 +323,7 @@ export default class ModelConfig extends React.Component{
</Row>
</FormItem>
<FormItem required={true} {...formItemLayout} label="算法参数:" style={{display:"on"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
<FormItem required={true} {...formItemLayout} label="算法参数:" style={{display:"None"}} >
<Row>
<Col span={20}>
<div>
@@ -231,29 +359,30 @@ export default class ModelConfig extends React.Component{
</Row>
</FormItem>
<FormItem required={true} {...formItemLayout} label="特征指标:" style={{display:"on"}} help={validate.sourceField.help} validateStatus={validate.sourceField.status}>
<FormItem required={true} {...formItemLayout} label="Tag" help={validate.tag.help} validateStatus={validate.tag.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>
<Input type="text" name="tag" value={this.state.tag} placeholder="tag" onChange={this.handlInputChange}/>
</Col>
<Col span={2} offset={1}>
<Tooltip placement="right" title={'模型需要的特征指标描叙,模型计算依赖的数据'}>
<Tooltip placement="right" title={'tag'}>
<Icon style={{fontSize:16}} type="question-circle-o" />
</Tooltip>
</Col>
</Row>
</FormItem>
</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>
@@ -273,11 +402,11 @@ export default class ModelConfig extends React.Component{
</Row>
</FormItem>
<FormItem required={true} {...formItemLayout} label="描叙信息" style={{display:"on"}} help={validate.args.help} validateStatus={validate.args.status}>
<FormItem required={true} {...formItemLayout} label="描叙信息" style={{display:"on"}} >
<Row>
<Col span={20}>
<Input.TextArea name="comment" value={this.state.comment} rows={4} placeholder="模型描叙信息。" />
<Input.TextArea name="comment" value={this.state.comment} rows={4} placeholder="模型描叙信息。" onChange={this.handlInputChange}/>
</Col>
<Col span={2} offset={1}>
<Tooltip placement="right" title={'模型描叙信息。'}>
@@ -287,12 +416,13 @@ export default class ModelConfig extends React.Component{
</Row>
</FormItem>
<FormItem {...formItemLayout} label="模型入参">
<FormItem required={true} {...formItemLayout} label="模型入参" help={validate.feed.help} validateStatus={validate.feed.status}>
{
paramsList.map(item => {
paramsList.map((item,index) => {
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>
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
@@ -300,6 +430,29 @@ export default class ModelConfig extends React.Component{
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%' }}
>
@@ -307,11 +460,24 @@ export default class ModelConfig extends React.Component{
</Select>
</div>
</Col>
</Row>);
return rows;
})
</Row>
)
: ""
}
</FormItem>
</FormItem>
<FormItem>
<Row>
<Col span={20} offset={18}>
<Button type="primary" htmlType="submit">
更新配置
</Button>
</Col>
</Row>
</FormItem>
</Form>
</div>
</div>

View File

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

View File

@@ -21,7 +21,6 @@ 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';
@@ -114,10 +113,7 @@ class AppRoutes extends React.Component{
</Route>
<Route path="/config" component={ConfigCenter}>
</Route>
<Route path="/learningConfig" component={LearningConfig}>
</Route>
</Route>
</Route>
<Route path="*" component={Index}>
<IndexRoute component={NotFound} />