gaozhan 5 rokov pred
rodič
commit
6b3e59a0d0
36 zmenil súbory, kde vykonal 2002 pridanie a 655 odobranie
  1. 1 0
      .gitignore
  2. 1 1
      package.json
  3. 30 14
      src/apis/base.js
  4. 5 5
      src/apis/hook.js
  5. 2 2
      src/apis/index.js
  6. 36 37
      src/pages/dc/bi/components/Fields/index.js
  7. 0 1
      src/pages/dc/subscribe/components/Edit/index.js
  8. 24 24
      src/pages/dc/subscribe/components/Job/index.js
  9. 1 3
      src/pages/dc/subscribe/data.js
  10. 12 13
      src/pages/dc/subscribe/list.js
  11. 4 4
      src/pages/fengkong/features/feature.js
  12. 4 1
      src/pages/fengkong/features/group/add/index.js
  13. 12 12
      src/pages/fengkong/features/group/index.js
  14. 32 0
      src/pages/fengkong/model/components/back.js
  15. 67 0
      src/pages/fengkong/model/components/editModel.js
  16. 216 0
      src/pages/fengkong/model/index.js
  17. 30 0
      src/pages/fengkong/model/service.js
  18. 40 0
      src/pages/fengkong/namelist/blackdevicelist/components/Edit.js
  19. 141 0
      src/pages/fengkong/namelist/blackdevicelist/index.js
  20. 13 0
      src/pages/fengkong/namelist/blackdevicelist/service.js
  21. 40 0
      src/pages/fengkong/namelist/blackiplist/components/Edit.js
  22. 137 0
      src/pages/fengkong/namelist/blackiplist/index.js
  23. 13 0
      src/pages/fengkong/namelist/blackiplist/service.js
  24. 40 0
      src/pages/fengkong/namelist/blackuserlist/components/Edit.js
  25. 137 0
      src/pages/fengkong/namelist/blackuserlist/index.js
  26. 13 0
      src/pages/fengkong/namelist/blackuserlist/service.js
  27. 40 0
      src/pages/fengkong/namelist/whiteuserlist/components/Edit.js
  28. 137 0
      src/pages/fengkong/namelist/whiteuserlist/index.js
  29. 13 0
      src/pages/fengkong/namelist/whiteuserlist/service.js
  30. 164 0
      src/pages/fengkong/risk/sale/sale.js
  31. 164 0
      src/pages/fengkong/risk/user/user.js
  32. 155 32
      src/pages/fengkong/strategies/add/index.js
  33. 166 33
      src/pages/fengkong/strategies/edit/$name.js
  34. 12 0
      src/pages/fengkong/strategies/service.js
  35. 28 8
      src/pages/fengkong/strategies/strategies.js
  36. 72 465
      yarn.lock

+ 1 - 0
.gitignore

@@ -5,6 +5,7 @@
 /npm-debug.log*
 /yarn-error.log
 /package-lock.json
+/.history
 
 # production
 /dist

+ 1 - 1
package.json

@@ -18,7 +18,7 @@
     "react-copy-to-clipboard": "^5.0.2",
     "react-dom": "^16.9.0",
     "react-rnd": "^10.1.8",
-    "wptpc-design": "^1.2.31"
+    "wptpc-design": "^2.0.28"
   },
   "devDependencies": {
     "@babel/plugin-proposal-decorators": "^7.7.4",

+ 30 - 14
src/apis/base.js

@@ -1,8 +1,9 @@
+/* eslint-disable camelcase */
 import axios from 'axios'
 import { message } from 'antd'
 import { beforeRequest, handleRequestError, handleResponseSuccess, handleResponseError } from '@/apis/hook'
 import { auth } from '@/conf/config'
-import getRealUrl from "@/utils/getRealUrl";
+import getRealUrl from '@/utils/getRealUrl'
 
 function getPrefix () {
   if (process.env.NODE_ENV === 'development') {
@@ -16,8 +17,7 @@ export const request = axios.create({
   baseURL: `${getPrefix()}`,
   timeout: 5000,
   withCredentials: true,
-  headers: {
-    'content-type': 'application/json'}
+  headers: { 'content-type': 'application/json' }
 })
 
 request.interceptors.request.use(
@@ -33,12 +33,12 @@ request.interceptors.request.use(
 
 request.interceptors.response.use(
   async response => {
-    if (response.data.code === 200 || response.data.code===0) {
+    if (response.data.code === 200 || response.data.code === 0) {
       await handleResponseSuccess(response)
     } else if (response.data.code === 9001) {
       message.warning('登录过期,请重新登录!')
       const { protocol, host } = window.location
-      window.location.href = `https://login.weipaitang.com/wechatLogin?loginUrl=${protocol+'//'+host}/login&redirect=${window.location.pathname || ''}`
+      window.location.href = `https://login.weipaitang.com/wechatLogin?loginUrl=${protocol + '//' + host}/login&redirect=${window.location.pathname || ''}`
       await handleResponseError(Error('登录过期,请重新登录!'))
     } else {
       message.error(response.data.msg)
@@ -52,7 +52,7 @@ request.interceptors.response.use(
   }
 )
 
-async function authRequest ({method, url, params, data}) {
+async function authRequest ({ method, url, params, data }) {
   const {
     code,
     msg,
@@ -62,15 +62,32 @@ async function authRequest ({method, url, params, data}) {
       ding_id: dd_id,
       user_name: dd_name,
       ding_mobile: telephone,
-      power,
-    },
+      power
+    }
   } = await request({
-    method: "get",
+    method: 'get',
     url: `${auth}/common/token?url=${encodeURIComponent(getRealUrl(url))}`,
-    params: {},
-  });
-  if (code===0) {
-    const newParams = (method && method.toLowerCase() === 'post')?{data: {...data,token, time, dd_id, dd_name, telephone, power}}:{params: {...params,token, time, dd_id, dd_name, telephone, power}}
+    params: {}
+  })
+  if (code === 0) {
+    const newParams = (method && method.toLowerCase() === 'post') ? { data: { ...data, token, time, dd_id, dd_name, telephone, power } } : { params: { ...params, token, time, dd_id, dd_name, telephone, power } }
+    if (!!data && data.body instanceof FormData) {
+      // console.log('--------------- formData body -------------------', params.body);
+      data.body.append('token', token)
+      data.body.append('time', time)
+      data.body.append('ddid', dd_id)
+      data.body.append('ddname', dd_name)
+      data.body.append('ddphone', telephone)
+      data.body.append('power', power)
+      return axios({
+        method: 'post',
+        url: url,
+        data: data.body,
+        headers: {
+          'content-type': 'multipart/form-data'
+        }
+      })
+    }
     return request({
       method,
       url,
@@ -79,7 +96,6 @@ async function authRequest ({method, url, params, data}) {
   } else {
     message.error(msg)
   }
-  
 }
 
 // 把原来的request变成authRequest,不需要改变原先的代码。如果直接用原来的不调用auth的request,使用解构的方式引用即可

+ 5 - 5
src/apis/hook.js

@@ -1,18 +1,18 @@
 import router from 'umi/router'
 
 async function beforeRequest (config) {
-  console.log(config)
+
 }
 async function handleRequestError (error) {
-  console.log(error)
+
 }
 async function handleResponseSuccess (response) {
-  console.log(response)
+
 }
 async function handleResponseError (error) {
   // if (error.response.status === 401) {
-    //   router.push('/login')
-    // }
+  //   router.push('/login')
+  // }
 }
 
 export {

+ 2 - 2
src/apis/index.js

@@ -1,4 +1,4 @@
-import request, {request as baseRequest} from './base.js'
+import request, { request as baseRequest } from './base.js'
 import { auth } from '@/conf/config'
 
 export function getUserList (params) {
@@ -10,7 +10,7 @@ export function getUserList (params) {
 }
 
 export function login (params) {
-  return baseRequest({url: `${auth}/login/ssoLogin`, params});
+  return baseRequest({ url: `${auth}/login/ssoLogin`, params })
 }
 
 export function fetchApi (url, params) {

+ 36 - 37
src/pages/dc/bi/components/Fields/index.js

@@ -10,42 +10,42 @@ export default class Index extends Component {
       params: {}
     }
     this.formSetting = [{
-        label: '数据表名',
-        type: 'input',
-        key: 'targetTable',
-        isRquired: true,
-      },
-      { 
-        label: '映射字段别名', 
-        type: 'input',
-        key: 'aliasField',
-        isRquired:true,
-      },
-      { 
-        label: '原始字段名', 
-        type: 'input',
-        key: 'originField',
-        isRquired:true,
-      },
-      {
-        label: '字段描述',
-        type:'input',
-        key:'description',
-        isRquired:true
-      },
-      {
-          label: '字段类型',
-          type:'input',
-          key:'fieldType',
-          isRquired:true
-      },
-      {
-          label: '字段特殊处理规则',
-          type:'input',
-          key:'customRule',
-          isRquired:true
-      }
-  ]
+      label: '数据表名',
+      type: 'input',
+      key: 'targetTable',
+      isRquired: true
+    },
+    {
+      label: '映射字段别名',
+      type: 'input',
+      key: 'aliasField',
+      isRquired: true
+    },
+    {
+      label: '原始字段名',
+      type: 'input',
+      key: 'originField',
+      isRquired: true
+    },
+    {
+      label: '字段描述',
+      type: 'input',
+      key: 'description',
+      isRquired: true
+    },
+    {
+      label: '字段类型',
+      type: 'input',
+      key: 'fieldType',
+      isRquired: true
+    },
+    {
+      label: '字段特殊处理规则',
+      type: 'input',
+      key: 'customRule',
+      isRquired: true
+    }
+    ]
   }
 
   // 组件挂在的时候调用的生命周期函数
@@ -69,7 +69,6 @@ export default class Index extends Component {
   render () {
     const { showModal, onCancel, loading } = this.props
     const { params } = this.state
-    console.log(params)
     return (
       <Modal
         title={params.id ? '编辑指标字段' : '添加指标字段'}

+ 0 - 1
src/pages/dc/subscribe/components/Edit/index.js

@@ -89,7 +89,6 @@ export default class Index extends Component {
   }
 
   clickDeleteJob = () => {
-    console.log('delete')
   }
 
   // 组件挂在的时候调用的生命周期函数

+ 24 - 24
src/pages/dc/subscribe/components/Job/index.js

@@ -41,15 +41,15 @@ class JobModal extends React.PureComponent {
               this.onParamsChange('fieldsJson', fieldsJson)
             }}/></div>
             <div className={s.spanMargin}>
-              <span style = {{ width:197}}>* 订阅描述</span>
-              <span style = {{ width:197}}>* 查询名</span>
-              <span style = {{ width:197}}>* 唯一标识</span>
-              <span style = {{ width:197}}>* 返回数据字段</span>
-              <span style = {{ width:131}}>* 订阅类型</span>
-              <span style = {{ width:120}}>* 缓存类型-天</span>
-              <span style = {{ width:122}}>* 缓存类型-小时</span>
-              <span style = {{ width:122}}>* 缓存过期天数</span>
-              <span style = {{ width:120}}>* 操作</span>
+              <span style = {{ width: 197 }}>* 订阅描述</span>
+              <span style = {{ width: 197 }}>* 查询名</span>
+              <span style = {{ width: 197 }}>* 唯一标识</span>
+              <span style = {{ width: 197 }}>* 返回数据字段</span>
+              <span style = {{ width: 131 }}>* 订阅类型</span>
+              <span style = {{ width: 120 }}>* 缓存类型-天</span>
+              <span style = {{ width: 122 }}>* 缓存类型-小时</span>
+              <span style = {{ width: 122 }}>* 缓存过期天数</span>
+              <span style = {{ width: 120 }}>* 操作</span>
             </div>
             <div>
               {fieldsJson.map((f, index) => <div>
@@ -80,7 +80,7 @@ class JobModal extends React.PureComponent {
                 <Checkbox checked={fieldsJson[index].cacheDay === 1 || fieldsJson[index].cacheDay === true} onChange={(e) => {
                   fieldsJson[index].cacheDay = e.target.checked
                   this.onParamsChange('fieldsJson', fieldsJson)
-                }} style={{ width: 110}}>按天缓存</Checkbox>
+                }} style={{ width: 110 }}>按天缓存</Checkbox>
                 <Checkbox checked={fieldsJson[index].cacheHour === 1 || fieldsJson[index].cacheHour === true} onChange={(e) => {
                   fieldsJson[index].cacheHour = e.target.checked
                   this.onParamsChange('fieldsJson', fieldsJson)
@@ -89,8 +89,8 @@ class JobModal extends React.PureComponent {
                   fieldsJson[index].expireDay = e.target.value
                   this.onParamsChange('fieldsJson', fieldsJson)
                 }} style={{ width: 100, marginRight: 10 }}/>
-                <Popconfirm title="确定要保存吗?" onConfirm={()=>this.clickSaveJob(index)}><Button type="primary" size="small" style={{ marginRight: 5 }} >保存</Button></Popconfirm>
-                <Popconfirm title="确定要删除吗?" onConfirm={()=>this.clickDeleteJob(index)}><Button type="danger" size="small">删除</Button></Popconfirm>
+                <Popconfirm title="确定要保存吗?" onConfirm={() => this.clickSaveJob(index)}><Button type="primary" size="small" style={{ marginRight: 5 }} >保存</Button></Popconfirm>
+                <Popconfirm title="确定要删除吗?" onConfirm={() => this.clickDeleteJob(index)}><Button type="danger" size="small">删除</Button></Popconfirm>
               </div>)}
             </div>
           </div>
@@ -120,12 +120,12 @@ class JobModal extends React.PureComponent {
               this.onParamsChange('customJson', customJson)
             }}/></div>
             <div className={s.spanMargin}>
-              <span style = {{ width:195}}>* 订阅描述</span>
-              <span style = {{ width:195}}>* 查询名</span>
-              <span style = {{ width:195}}>* 唯一标识</span>
-              <span style = {{ width:195}}>* 定制规则名</span>
-              <span style = {{ width:195}}>* 缓存天数</span>
-              <span style = {{ width:195}}>* 操作</span>
+              <span style = {{ width: 195 }}>* 订阅描述</span>
+              <span style = {{ width: 195 }}>* 查询名</span>
+              <span style = {{ width: 195 }}>* 唯一标识</span>
+              <span style = {{ width: 195 }}>* 定制规则名</span>
+              <span style = {{ width: 195 }}>* 缓存天数</span>
+              <span style = {{ width: 195 }}>* 操作</span>
             </div>
             <div>
               {customJson.map((f, index) => <div>
@@ -151,16 +151,16 @@ class JobModal extends React.PureComponent {
                   this.onParamsChange('customJson', customJson)
                 }} style={{ width: 188, marginRight: 10 }}/>
                 <Popconfirm title="确定保存吗?"
-          onConfirm={() => this.clickSaveCustomJob(index)}><Button type="primary" size="small" style={{ marginRight: 5 }}>保存</Button>
+                  onConfirm={() => this.clickSaveCustomJob(index)}><Button type="primary" size="small" style={{ marginRight: 5 }}>保存</Button>
                 </Popconfirm>
                 <Popconfirm title="确定要删除吗?" onConfirm={() => this.clickDeleteCustomJob(index)}><Button type="danger" size="small">删除</Button>
                 </Popconfirm>
-               
+
               </div>)}
             </div>
           </div>
         }
-      },
+      }
     ]
   }
 
@@ -168,7 +168,6 @@ class JobModal extends React.PureComponent {
     const { params } = this.state
     const { fieldsJson } = params
     const type = 'subscribetpl/_editSubJobItem'
-    console.log(params)
     fieldsJson[index].sid = params.id
     this.props.dispatch({
       type,
@@ -177,7 +176,7 @@ class JobModal extends React.PureComponent {
         const { code, data } = res || {}
         if (code === 0) {
           const msg = params.id ? '编辑成功' : '添加成功'
-          console.log(data)
+
           fieldsJson[index].id = data
           message.success(msg)
           params.fieldsJson = fieldsJson
@@ -248,7 +247,7 @@ class JobModal extends React.PureComponent {
     })
   }
 
-  clickDeleteCustomJob = (index)  => {
+  clickDeleteCustomJob = (index) => {
     const { params } = this.state
     const { customJson } = params
     const type = 'subscribetpl/_deleteSubJobItem'
@@ -272,6 +271,7 @@ class JobModal extends React.PureComponent {
       }
     })
   }
+
   // 组件挂在的时候调用的生命周期函数
   componentDidMount () {
     const params = { ...this.props.params }

+ 1 - 3
src/pages/dc/subscribe/data.js

@@ -146,7 +146,6 @@ class Index extends React.PureComponent {
     })
   }
 
-
   // 点击新建、编辑对话框的取消按钮的事件处理函数
   onModalCancel = () => {
     this.setState({ showModal: false })
@@ -169,8 +168,7 @@ class Index extends React.PureComponent {
       return t
     }, {})
     params.fieldsJson = JSON.stringify(fieldsJson)
-    console.log(params, 235)
-    const type =  'subscribetpl/_editSubRuleItem'
+    const type = 'subscribetpl/_editSubRuleItem'
     this.props.dispatch({
       type,
       payload: params,

+ 12 - 13
src/pages/dc/subscribe/list.js

@@ -52,32 +52,31 @@ class SubJobList extends React.PureComponent {
         dataIndex: 'uniquId'
       },
       {
-          title: '订阅的数据库',
-          dataIndex: "subDb"
+        title: '订阅的数据库',
+        dataIndex: 'subDb'
       },
       {
-          title: '订阅的数据表',
-          dataIndex: "subTable"
+        title: '订阅的数据表',
+        dataIndex: 'subTable'
       },
       {
-          title: '订阅字段',
-          dataIndex: "subFields"
+        title: '订阅字段',
+        dataIndex: 'subFields'
       },
       {
-          title: '订阅过滤条件',
-          dataIndex: "subFilter"
+        title: '订阅过滤条件',
+        dataIndex: 'subFilter'
       },
       {
-           title: '订阅回调地址',
-           dataIndex: "url"
+        title: '订阅回调地址',
+        dataIndex: 'url'
       },
       {
         title: '订阅计算类型',
         dataIndex: 'type',
-        render:(text) => { 
-          console.log("enter")
+        render: (text) => {
           if (text === 1) return '自增'
-          else if(text === 2) return '变量增加'
+          else if (text === 2) return '变量增加'
           else if (text === 3) return '自定义'
         }
       }

+ 4 - 4
src/pages/fengkong/features/feature.js

@@ -34,10 +34,10 @@ class FeaturesList extends React.PureComponent {
       pageSize: 10
     },
     columnConfig: [
-      {
-        title: 'ID',
-        dataIndex: 'id'
-      },
+      // {
+      //   title: 'ID',
+      //   dataIndex: 'id'
+      // },
       {
         title: '名称',
         dataIndex: 'name'

+ 4 - 1
src/pages/fengkong/features/group/add/index.js

@@ -1,11 +1,12 @@
 import React from 'react'
-import { Form, Input, Row, Col, Switch, Button, Modal, message } from 'antd'
+import { Form, Input, Row, Col, Button, Modal, message } from 'antd'
 import AceEditor from 'react-ace'
 import { create, test } from '../service'
 
 import 'ace-builds/src-noconflict/mode-java'
 import 'ace-builds/src-noconflict/theme-monokai'
 import { connect } from 'dva'
+import router from 'umi/router'
 
 const formItemLayout = {
   layout: 'vertical'
@@ -36,6 +37,8 @@ class Add extends React.PureComponent {
               title: '提交成功',
               content: '策略代码编译正常,点击“测试按钮”可以继续测试策略逻辑'
             })
+            // 跳转到列表页
+            router.push('/fengkong/features/group')
           }
         })
       }

+ 12 - 12
src/pages/fengkong/features/group/index.js

@@ -40,10 +40,10 @@ class GroupList extends React.PureComponent {
       pageSize: 10
     },
     columnConfig: [
-      {
-        title: 'ID',
-        dataIndex: 'id'
-      },
+      // {
+      //   title: 'ID',
+      //   dataIndex: 'id'
+      // },
       {
         title: '分组名称',
         dataIndex: 'name'
@@ -104,14 +104,14 @@ class GroupList extends React.PureComponent {
       })
     }
 
-  render () {
-    return (
-      <div>
-        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
-        />
-      </div>
-    )
-  }
+    render () {
+      return (
+        <div>
+          <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+          />
+        </div>
+      )
+    }
 }
 
 export default GroupList

+ 32 - 0
src/pages/fengkong/model/components/back.js

@@ -0,0 +1,32 @@
+import React, { Component } from 'react'
+import { Modal } from 'antd'
+import { FormItem } from 'wptpc-design'
+
+export default class Index extends Component {
+
+  render () {
+    const { showModal, params, versions, onChange, onOk, onCancel, fetching } = this.props
+    const formSetting = [{
+      label: '模型名称',
+      type: 'input',
+      key: 'name'
+    },
+    {
+      label: '模型版本',
+      type: 'select',
+      key: 'version',
+      options: versions.map(item => ({ label: item, value: item }))
+    }]
+    return (
+      <Modal
+        title={'模型回退'}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange}/>
+      </Modal>
+    )
+  }
+}

+ 67 - 0
src/pages/fengkong/model/components/editModel.js

@@ -0,0 +1,67 @@
+import React, { Component } from 'react'
+import { Modal, Upload, Button, message } from 'antd'
+import { FormItem } from 'wptpc-design'
+
+export default class Index extends Component {
+  uploadProps = {
+    name: 'file',
+    headers: {
+      credentials: 'include'
+    },
+    beforeUpload: file => {
+      if (!file.name.endsWith('.pmml')) {
+        message.warning('请上传 pmml 格式的文件')
+        return false
+      }
+      if (file == null) {
+        message.warn('请选择模型文件')
+        return false
+      }
+      this.props.onChange('file', file)
+      return false
+    }
+  };
+
+  render () {
+    const { showModal, params, onChange, onOk, onCancel, fetching } = this.props
+    const formSetting = [{
+      label: '模型名称',
+      type: 'input',
+      key: 'name'
+    },
+    {
+      label: '模型描述',
+      type: 'textarea',
+      key: 'description'
+    },
+    {
+      label: '模型版本',
+      type: 'input',
+      key: 'version'
+    }, {
+      label: '',
+      key: 'file',
+      render: () => {
+        return (
+          <div style={{ marginLeft: '120px' }}>
+            <Upload {...this.uploadProps}>
+              <Button type="primary">上传模型文件</Button>
+            </Upload>
+            <p>文件类型:.pmml</p>
+          </div>
+        )
+      }
+    }]
+    return (
+      <Modal
+        title={'模型上传'}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange} />
+      </Modal>
+    )
+  }
+}

+ 216 - 0
src/pages/fengkong/model/index.js

@@ -0,0 +1,216 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { thanos } from '@/conf/config'
+import { Divider, message, Button } from 'antd'
+import { connect } from 'dva'
+import moment from 'moment'
+import { delItem, update, upload, back, versions } from './service.js'
+import Edit from './components/editModel'
+import Back from './components/back'
+const apiUrl = `${thanos}/thanos-admin/api/v1/model/list`
+
+@connect(({ user }) => ({
+  currentUser: user.currentUser
+}))
+class ModelList extends React.PureComponent {
+  state = {
+    showModal: false,
+    showBack: false,
+    params: {},
+    allVersions: [],
+    updateModel: false
+  }
+
+  filterSetting = {
+    rfBtnsJsx: <Button onClick={() => this.addItem()}>上传模型</Button>,
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '描述:',
+        type: 'input',
+        key: 'queryName',
+        placeholder: '模型名称'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.type = 3
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    rowKey: 'id',
+    // isFrontPagination: true,
+    pagination: {
+      pageSize: 10
+    },
+    columnConfig: [
+      // {
+      //   title: 'ID',
+      //   dataIndex: 'id'
+      // },
+      {
+        title: '名称',
+        dataIndex: 'name'
+      },
+      {
+        title: '描述',
+        dataIndex: 'description'
+      },
+      {
+        title: '版本',
+        dataIndex: 'version'
+      },
+      {
+        title: '最后更新',
+        dataIndex: 'updateUser'
+      },
+      {
+        title: '更新时间',
+        dataIndex: 'updateTime',
+        render: text => {
+          return moment(parseInt(text)).format('YYYY-MM-DD HH:mm:ss')
+        }
+      },
+      {
+        title: '操作',
+        dataIndex: 'actions',
+        // 所有需要弹窗操作的都可以用编辑的逻辑;所有不需要弹窗的操作,比如上架、发布等,都可以用”删除“的逻辑
+        render: (text, record) => (
+          <span>
+            <Button type="primary" onClick={() => this.updateItem(record)}>更新</Button>
+            <Divider type="vertical"/>
+            <Button type="primary" onClick={() => this.backItem(record)}>回退</Button>
+          </span>)
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  // 点击编辑按钮时的事件处理函数
+  editItem (record) {
+    // const fields = JSON.parse(record.fieldsJson)
+    // console.log('=====', fields)
+    const { fields } = record
+    const fieldsJson = Object.keys(fields).map(f => ({
+      key: f,
+      desc: fields[f].desc,
+      column: fields[f].column
+    }))
+    console.log(fieldsJson)
+    this.setState({
+      showModal: true,
+      params: {
+        ...record,
+        fieldsJson
+      }
+    })
+  }
+
+  // 点击删除按钮时的事件处理函数
+  delItem = (record) => {
+    delItem({ id: record.id, name: record.name }).then(res => {
+      if (res.code === 0) {
+        message.success('删除成功')
+        this.refresh()
+      }
+    })
+  }
+
+  addItem = () => {
+    this.setState({ showEditModal: true, params: {}, updateModel: false })
+  }
+
+  updateItem = (record) => {
+    this.setState({ showEditModal: true, params: record, updateModel: true })
+  }
+
+  backItem = (record) => {
+    this.setState({ allVersions: [] })
+    versions({ name: record.name }).then(res => {
+      if (res != null) {
+        this.setState({ allVersions: res.data })
+      }
+    })
+    this.setState({ showEditBack: true, params: record })
+  }
+
+  onParamsChange = (key, value) => {
+    const params = { ...this.state.params }
+    params[key] = value
+    this.setState({ params })
+  }
+
+  onEditOk = () => {
+    const { file, name, description, version } = this.state.params
+    const updateModel = this.state.updateModel
+    const params = new FormData()
+    params.append('name', name)
+    params.append('description', description)
+    params.append('version', version)
+    params.append('file', file)
+    params.append('updateUser', this.props.currentUser.name)
+    if (updateModel) {
+      update(params).then(res => {
+        if (res.data != null && res.data.code === 0) {
+          message.success('处理成功')
+          this.refresh()// 刷新列表
+          this.onEditCancel()// 关闭弹窗
+        } else {
+          message.error('处理失败: ' + res.data.msg)
+        }
+      })
+    } else {
+      upload(params).then(res => {
+        if (res.data != null && res.data.code === 0) {
+          message.success('处理成功')
+          this.refresh()// 刷新列表
+          this.onEditCancel()// 关闭弹窗
+        } else {
+          message.error('处理失败: ' + res.data.msg)
+        }
+      })
+    }
+  }
+
+  onBackOk = () => {
+    const { name, version } = this.state.params
+    const params = {
+      name: name,
+      version: version
+    }
+    back(params).then(res => {
+      if (res.data != null && res.code === 0) {
+        message.success('处理成功')
+        this.refresh()// 刷新列表
+        this.onBackCancel()// 关闭弹窗
+      } else {
+        message.error('处理失败:' + res.msg)
+      }
+    })
+  }
+
+  onEditCancel = () => {
+    this.setState({ showEditModal: false })
+  }
+
+  onBackCancel = () => {
+    this.setState({ showEditBack: false })
+  }
+
+  render () {
+    const { showEditModal, showEditBack, params, allVersions } = this.state
+    return (
+      <div>
+        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl} />
+        <Edit showModal={showEditModal} params={params} onChange={this.onParamsChange} onOk={this.onEditOk} onCancel={this.onEditCancel} />
+        <Back showModal={showEditBack} params={params} versions={allVersions} onChange={this.onParamsChange} onOk={this.onBackOk} onCancel={this.onBackCancel}/>
+      </div>
+    )
+  }
+}
+
+export default ModelList

+ 30 - 0
src/pages/fengkong/model/service.js

@@ -0,0 +1,30 @@
+import { fetchApi } from '@/apis/'
+import { thanos } from '@/conf/config'
+
+// 上传模型
+export async function upload (body) {
+  const url = `${thanos}/thanos-admin/api/v1/model/upload`
+  return fetchApi(url, { method: 'POST', contentType: 'jsonString', body })
+}
+
+// 更新模型
+export async function update (body) {
+  const url = `${thanos}/thanos-admin/api/v1/model/update`
+  return fetchApi(url, { method: 'POST', contentType: 'jsonString', body })
+}
+
+// 模型删除
+export async function delItem (params) {
+  const url = `${thanos}/thanos-admin/api/v1/model/delete`
+  return fetchApi(url, params)
+}
+
+export async function back (params) {
+  const url = `${thanos}/thanos-admin/api/v1/model/back`
+  return fetchApi(url, params)
+}
+
+export async function versions (params) {
+  const url = `${thanos}/thanos-admin/api/v1/model/versions`
+  return fetchApi(url, params)
+}

+ 40 - 0
src/pages/fengkong/namelist/blackdevicelist/components/Edit.js

@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import { Modal } from 'antd';
+import { FormItem } from 'wptpc-design';
+
+export default class Index extends Component {
+
+  render() {
+    const { showModal, params, onChange, onOk, onCancel, fetching } = this.props;
+    const formSetting = [{
+      label: 'DeviceId',
+      isRequired: true,
+      type: 'input',
+      key: 'deviceId',
+      placeholder: 'deviceId',
+      maxLength: 50,
+    },
+    {
+      label: '是否启用',
+      type: 'select',
+      key: 'valid',
+      options: [
+        { value: "0", label: '禁用' },
+        { value: "1", label: '启用' },
+      ],
+      isRequired: true,
+      placeholder: '请选择'
+    }];
+    return (
+      <Modal
+        title={`新增deviceId`}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange} />
+      </Modal>
+    );
+  }
+}

+ 141 - 0
src/pages/fengkong/namelist/blackdevicelist/index.js

@@ -0,0 +1,141 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { connect } from 'dva'
+import { thanos } from '@/conf/config'
+import { Divider, message, Popconfirm, Button } from 'antd'
+import { delItem, addDeviceId } from './service.js'
+import Edit from './components/Edit'
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/nameList/blackDeviceList`
+
+@connect(({ user }) => ({
+  currentUser: user.currentUser
+}))
+
+class BlackDeviceList extends React.PureComponent {
+  constructor () {
+    super()
+    this.state = {
+      showModal: false,
+      selectedItem: {},
+      showEditModal: false,
+      params: {}
+    }
+  }
+
+  filterSetting = {
+    rfBtnsJsx: <Button type="primary" onClick={() => this.addItem()}>添加DeviceId</Button>,
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '',
+        type: 'input',
+        key: 'queryName',
+        placeholder: 'deviceId查询'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    pagination: {
+      pageSize: 10
+    },
+    columnConfig: [
+      {
+        title: '设备',
+        dataIndex: 'deviceId'
+      },
+      {
+        title: '类型',
+        dataIndex: 'type',
+        render: (text) => {
+          if (text === 0) return '默认'
+          else if (text === 1) return '风控规则自动拉黑'
+          else if (text === 2) return '后台手动录入'
+        }
+      },
+      {
+        title: '类型是否有效',
+        dataIndex: 'valid',
+        render: (text) => text === 1 ? '是' : '否'
+      },
+      {
+        title: '更新时间',
+        dataIndex: 'updateTime'
+      },
+      {
+        title: '操作',
+        dataIndex: 'actions',
+        // 所有需要弹窗操作的都可以用编辑的逻辑;所有不需要弹窗的操作,比如上架、发布等,都可以用”删除“的逻辑
+        render: (text, record) => (
+          <span>
+            <Popconfirm
+              title="启用/禁用"
+              onConfirm={() => this.delItem(record)}>
+              <a>{
+                record.valid === 1 ? '禁用' : '启用'
+              }</a>
+            </Popconfirm>
+          </span>)
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  // 点击删除按钮时的事件处理函数
+  delItem = (record) => {
+    delItem({ id: record.id, valid: record.valid === 1 ? 0 : 1, updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('操作成功')
+        this.refresh()
+      }
+    })
+  }
+
+  addItem = () => {
+    this.setState({ showEditModal: true, params: {} })
+  }
+
+  onParamsChange = (key, value) => {
+    const params = { ...this.state.params }
+    params[key] = value
+    this.setState({ params })
+  }
+
+  onEditOk = () => {
+    const { params } = this.state
+
+    const payload = { ...params }
+    addDeviceId({ deviceId: payload.deviceId.trim(), valid: payload.valid, type: 2, createUser: this.props.currentUser.name, updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('添加成功')
+        this.refresh()// 刷新列表
+        this.onEditCancel()// 关闭弹窗
+      }
+    })
+  }
+
+  onEditCancel = () => {
+    this.setState({ showEditModal: false })
+  }
+
+  render () {
+    const { showModal, selectedItem, showEditModal, params } = this.state
+    return (
+      <div>
+        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+        <Edit showModal={showEditModal} params={params} onChange={this.onParamsChange} onOk={this.onEditOk} onCancel={this.onEditCancel} />
+      </div>
+    )
+  }
+}
+
+export default BlackDeviceList

+ 13 - 0
src/pages/fengkong/namelist/blackdevicelist/service.js

@@ -0,0 +1,13 @@
+import { fetchApi, fetchApi_get as fetchApiGet } from '@/apis/'
+import { thanos } from '@/conf/config'
+
+//删除
+export async function delItem (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackDeviceList/enableDisable`
+  return fetchApi(url, params)
+}
+
+export async function addDeviceId (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackDeviceList/create`
+  return fetchApi(url, params)
+}

+ 40 - 0
src/pages/fengkong/namelist/blackiplist/components/Edit.js

@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import { Modal } from 'antd';
+import { FormItem } from 'wptpc-design';
+
+export default class Index extends Component {
+
+  render() {
+    const { showModal, params, onChange, onOk, onCancel, fetching } = this.props;
+    const formSetting = [{
+      label: 'IP',
+      isRequired: true,
+      type: 'input',
+      key: 'ip',
+      placeholder: 'IP地址',
+      maxLength: 15,
+    },
+    {
+      label: '是否启用',
+      type: 'select',
+      key: 'valid',
+      options: [
+        { value: "0", label: '禁用' },
+        { value: "1", label: '启用' },
+      ],
+      isRequired: true,
+      placeholder: '请选择'
+    }];
+    return (
+      <Modal
+        title={`新增IP`}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange} />
+      </Modal>
+    );
+  }
+}

+ 137 - 0
src/pages/fengkong/namelist/blackiplist/index.js

@@ -0,0 +1,137 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { connect } from 'dva'
+import { thanos } from '@/conf/config'
+import { message, Popconfirm, Button } from 'antd'
+import { delItem, addIP } from './service.js'
+import Edit from './components/Edit';
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/nameList/blackIpList`
+
+@connect(({ user }) => ({
+  currentUser: user.currentUser
+}))
+
+class BlackIpList extends React.PureComponent {
+  constructor() {
+    super();
+    this.state = {
+      showModal: false,
+      selectedItem: {},
+      showEditModal: false,
+      params: {}
+    }
+  }
+
+  filterSetting = {
+    rfBtnsJsx: <Button type="primary" onClick={() => this.addItem()}>添加IP</Button>,
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '',
+        type: 'input',
+        key: 'queryName',
+        placeholder: 'IP查询'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    pagination: {
+      pageSize: 10
+    },
+    columnConfig: [
+      {
+        title: 'ip',
+        dataIndex: 'ip'
+      },
+      {
+        title: '类型',
+        dataIndex: 'type',
+        render: (text) => {
+          if (text === 0) return '系统默认'
+          else if (text === 1) return '风控规则自动拉黑'
+          else if (text === 2) return '后台手动录入'
+        }
+      },
+      {
+        title: '是否有效',
+        dataIndex: 'valid',
+        render: (text) => text === 1 ? '是' : '否'
+      },
+      {
+        title: '更新时间',
+        dataIndex: 'updateTime'
+      },
+      {
+        title: '操作',
+        dataIndex: 'actions',
+        // 所有需要弹窗操作的都可以用编辑的逻辑;所有不需要弹窗的操作,比如上架、发布等,都可以用”删除“的逻辑
+        render: (text, record) => (
+          <span>
+            <Popconfirm
+              title="启用/禁用"
+              onConfirm={() => this.delItem(record)}>
+              <a>{
+                record.valid === 1 ? '禁用' : '启用'
+              }</a>
+            </Popconfirm>
+          </span>)
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  // 点击删除按钮时的事件处理函数
+  delItem = (record) => {
+    delItem({ id: record.id, valid: record.valid === 1? 0 : 1,updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('操作成功')
+        this.refresh()
+      }
+    })
+  }
+
+  addItem = () => {
+    this.setState({ showEditModal: true, params: {} });
+  }
+  onParamsChange = (key, value) => {
+    const params = { ...this.state.params };
+    params[key] = value;
+    this.setState({ params });
+  }
+  onEditOk = () => {
+    const { params } = this.state;
+
+    const payload = { ...params };
+    addIP({ ip: payload.ip.trim(), valid: payload.valid, type:2, createUser: this.props.currentUser.name, updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('添加成功')
+        this.refresh()//刷新列表
+        this.onEditCancel()//关闭弹窗
+      }
+    })
+  }
+  onEditCancel = () => {
+    this.setState({ showEditModal: false })
+  }
+  render() {
+    const { showModal, selectedItem, showEditModal, params } = this.state;
+    return (
+      <div>
+        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+        <Edit showModal={showEditModal} params={params} onChange={this.onParamsChange} onOk={this.onEditOk} onCancel={this.onEditCancel} />
+      </div>
+    )
+  }
+}
+
+export default BlackIpList

+ 13 - 0
src/pages/fengkong/namelist/blackiplist/service.js

@@ -0,0 +1,13 @@
+import { fetchApi, fetchApi_get as fetchApiGet } from '@/apis/'
+import { thanos } from '@/conf/config'
+
+//删除
+export async function delItem (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackIpList/enableDisable`
+  return fetchApi(url, params)
+}
+
+export async function addIP (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackIpList/create`
+  return fetchApi(url, params)
+}

+ 40 - 0
src/pages/fengkong/namelist/blackuserlist/components/Edit.js

@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import { Modal } from 'antd';
+import { FormItem } from 'wptpc-design';
+
+export default class Index extends Component {
+
+  render() {
+    const { showModal, params, onChange, onOk, onCancel, fetching } = this.props;
+    const formSetting = [{
+      label: 'userId',
+      isRequired: true,
+      type: 'input',
+      key: 'userId',
+      placeholder: '用户Id',
+      maxLength: 15,
+    },
+    {
+      label: '是否启用',
+      type: 'select',
+      key: 'valid',
+      options: [
+        { value: "0", label: '禁用' },
+        { value: "1", label: '启用' },
+      ],
+      isRequired: true,
+      placeholder: '请选择'
+    }];
+    return (
+      <Modal
+        title={`新增黑名单用户Id`}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange} />
+      </Modal>
+    );
+  }
+}

+ 137 - 0
src/pages/fengkong/namelist/blackuserlist/index.js

@@ -0,0 +1,137 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { connect } from 'dva'
+import { thanos } from '@/conf/config'
+import { message, Popconfirm, Button } from 'antd'
+import { delItem, addUserId } from './service.js'
+import Edit from './components/Edit';
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/nameList/blackUserList`
+
+@connect(({ user }) => ({
+  currentUser: user.currentUser
+}))
+
+class BlackIpList extends React.PureComponent {
+  constructor() {
+    super();
+    this.state = {
+      showModal: false,
+      selectedItem: {},
+      showEditModal: false,
+      params: {}
+    }
+  }
+
+  filterSetting = {
+    rfBtnsJsx: <Button type="primary" onClick={() => this.addItem()}>添加用户Id</Button>,
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '',
+        type: 'input',
+        key: 'queryName',
+        placeholder: 'IP查询'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    pagination: {
+      pageSize: 10
+    },
+    columnConfig: [
+      {
+        title: 'userId',
+        dataIndex: 'userId'
+      },
+      {
+        title: '类型',
+        dataIndex: 'type',
+        render: (text) => {
+          if (text === 0) return '系统默认'
+          else if (text === 1) return '风控规则自动拉黑'
+          else if (text === 2) return '后台手动录入'
+        }
+      },
+      {
+        title: '是否有效',
+        dataIndex: 'valid',
+        render: (text) => text === 1 ? '是' : '否'
+      },
+      {
+        title: '更新时间',
+        dataIndex: 'updateTime'
+      },
+      {
+        title: '操作',
+        dataIndex: 'actions',
+        // 所有需要弹窗操作的都可以用编辑的逻辑;所有不需要弹窗的操作,比如上架、发布等,都可以用”删除“的逻辑
+        render: (text, record) => (
+          <span>
+            <Popconfirm
+              title="启用/禁用"
+              onConfirm={() => this.delItem(record)}>
+              <a>{
+                record.valid === 1 ? '禁用' : '启用'
+              }</a>
+            </Popconfirm>
+          </span>)
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  // 点击删除按钮时的事件处理函数
+  delItem = (record) => {
+    delItem({ id: record.id, valid: record.valid === 1? 0 : 1,updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('操作成功')
+        this.refresh()
+      }
+    })
+  }
+
+  addItem = () => {
+    this.setState({ showEditModal: true, params: {} });
+  }
+  onParamsChange = (key, value) => {
+    const params = { ...this.state.params };
+    params[key] = value;
+    this.setState({ params });
+  }
+  onEditOk = () => {
+    const { params } = this.state;
+
+    const payload = { ...params };
+    addUserId({ userId: payload.userId, valid: payload.valid, type:2, createUser: this.props.currentUser.name, updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('添加成功')
+        this.refresh()//刷新列表
+        this.onEditCancel()//关闭弹窗
+      }
+    })
+  }
+  onEditCancel = () => {
+    this.setState({ showEditModal: false })
+  }
+  render() {
+    const { showModal, selectedItem, showEditModal, params } = this.state;
+    return (
+      <div>
+        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+        <Edit showModal={showEditModal} params={params} onChange={this.onParamsChange} onOk={this.onEditOk} onCancel={this.onEditCancel} />
+      </div>
+    )
+  }
+}
+
+export default BlackIpList

+ 13 - 0
src/pages/fengkong/namelist/blackuserlist/service.js

@@ -0,0 +1,13 @@
+import { fetchApi, fetchApi_get as fetchApiGet } from '@/apis/'
+import { thanos } from '@/conf/config'
+
+//删除
+export async function delItem (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackUserList/enableDisable`
+  return fetchApi(url, params)
+}
+
+export async function addUserId (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/blackUserList/create`
+  return fetchApi(url, params)
+}

+ 40 - 0
src/pages/fengkong/namelist/whiteuserlist/components/Edit.js

@@ -0,0 +1,40 @@
+import React, { Component } from 'react';
+import { Modal } from 'antd';
+import { FormItem } from 'wptpc-design';
+
+export default class Index extends Component {
+
+  render() {
+    const { showModal, params, onChange, onOk, onCancel, fetching } = this.props;
+    const formSetting = [{
+      label: 'userId',
+      isRequired: true,
+      type: 'input',
+      key: 'userId',
+      placeholder: '用户Id',
+      maxLength: 15,
+    },
+    {
+      label: '是否启用',
+      type: 'select',
+      key: 'valid',
+      options: [
+        { value: "0", label: '禁用' },
+        { value: "1", label: '启用' },
+      ],
+      isRequired: true,
+      placeholder: '请选择'
+    }];
+    return (
+      <Modal
+        title={`新增白名单用户`}
+        visible={showModal}
+        onOk={onOk}
+        onCancel={onCancel}
+        okButtonProps={{ disabled: fetching }}
+      >
+        <FormItem formSetting={formSetting} params={params} onChange={onChange} />
+      </Modal>
+    );
+  }
+}

+ 137 - 0
src/pages/fengkong/namelist/whiteuserlist/index.js

@@ -0,0 +1,137 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { connect } from 'dva'
+import { thanos } from '@/conf/config'
+import { message, Popconfirm, Button } from 'antd'
+import { delItem, addUserId } from './service.js'
+import Edit from './components/Edit';
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/nameList/whiteUserList`
+
+@connect(({ user }) => ({
+  currentUser: user.currentUser
+}))
+
+class BlackIpList extends React.PureComponent {
+  constructor() {
+    super();
+    this.state = {
+      showModal: false,
+      selectedItem: {},
+      showEditModal: false,
+      params: {}
+    }
+  }
+
+  filterSetting = {
+    rfBtnsJsx: <Button type="primary" onClick={() => this.addItem()}>添加用户Id</Button>,
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '',
+        type: 'input',
+        key: 'queryName',
+        placeholder: '用户Id查询'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    pagination: {
+      pageSize: 10
+    },
+    columnConfig: [
+      {
+        title: '用户Id',
+        dataIndex: 'userId'
+      },
+      {
+        title: '类型',
+        dataIndex: 'type',
+        render: (text) => {
+          if (text === 0) return '系统默认'
+          else if (text === 1) return '风控规则自动拉黑'
+          else if (text === 2) return '后台手动录入'
+        }
+      },
+      {
+        title: '是否有效',
+        dataIndex: 'valid',
+        render: (text) => text === 1 ? '是' : '否'
+      },
+      {
+        title: '更新时间',
+        dataIndex: 'updateTime'
+      },
+      {
+        title: '操作',
+        dataIndex: 'actions',
+        // 所有需要弹窗操作的都可以用编辑的逻辑;所有不需要弹窗的操作,比如上架、发布等,都可以用”删除“的逻辑
+        render: (text, record) => (
+          <span>
+            <Popconfirm
+              title="启用/禁用"
+              onConfirm={() => this.delItem(record)}>
+              <a>{
+                record.valid === 1 ? '禁用' : '启用'
+              }</a>
+            </Popconfirm>
+          </span>)
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  // 点击删除按钮时的事件处理函数
+  delItem = (record) => {
+    delItem({ id: record.id, valid: record.valid === 1? 0 : 1,updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('操作成功')
+        this.refresh()
+      }
+    })
+  }
+
+  addItem = () => {
+    this.setState({ showEditModal: true, params: {} });
+  }
+  onParamsChange = (key, value) => {
+    const params = { ...this.state.params };
+    params[key] = value;
+    this.setState({ params });
+  }
+  onEditOk = () => {
+    const { params } = this.state;
+
+    const payload = { ...params };
+    addUserId({ userId: payload.userId, valid: payload.valid, type:2, createUser: this.props.currentUser.name, updateUser: this.props.currentUser.name }).then(res => {
+      if (res.code === 0) {
+        message.success('添加成功')
+        this.refresh()//刷新列表
+        this.onEditCancel()//关闭弹窗
+      }
+    })
+  }
+  onEditCancel = () => {
+    this.setState({ showEditModal: false })
+  }
+  render() {
+    const { showModal, selectedItem, showEditModal, params } = this.state;
+    return (
+      <div>
+        <FilterTable filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+        <Edit showModal={showEditModal} params={params} onChange={this.onParamsChange} onOk={this.onEditOk} onCancel={this.onEditCancel} />
+      </div>
+    )
+  }
+}
+
+export default BlackIpList

+ 13 - 0
src/pages/fengkong/namelist/whiteuserlist/service.js

@@ -0,0 +1,13 @@
+import { fetchApi, fetchApi_get as fetchApiGet } from '@/apis'
+import { thanos } from '@/conf/config'
+
+//删除
+export async function delItem (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/whiteUserList/enableDisable`
+  return fetchApi(url, params)
+}
+
+export async function addUserId (params) {
+  const url = `${thanos}/thanos-admin/api/v1/nameList/whiteUserList/create`
+  return fetchApi(url, params)
+}

+ 164 - 0
src/pages/fengkong/risk/sale/sale.js

@@ -0,0 +1,164 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { thanos } from '@/conf/config'
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/risk/order/query`
+
+// const renderContent = (text, row, index) => {
+//   const obj = {
+//     children: text,
+//     props: {}
+//   }
+//   // if (index === 4) {
+//   obj.props.rowSpan = 1
+
+//   return text
+// }
+
+const format = (a) => {
+  const o = []
+  for (let i = 0; i < a.length - 1; i++) {
+    o.push(a.slice(0, i + 1).reduce((pre, next) => Number(pre) + Number(next)))
+  }
+  return o
+}
+
+class SaleRiskQuery extends React.PureComponent {
+  state = {
+    showModal: false,
+    params: {
+    }
+  }
+
+  filterSetting = {
+    changeApiData: (data) => {
+      const list = []
+      const page = []
+      data.data.list.forEach(item => {
+        page.push(Object.keys(JSON.parse(item.input)).length)
+        for (const key in JSON.parse(item.input)) {
+          list.push({ name: item.name, output: item.output, tzname: key, tzvalue: JSON.parse(item.input)[key], result: item.output })
+        }
+      })
+      this.page = page
+      return {
+        code: 0,
+        data: { list: list }
+      }
+    },
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '描述:',
+        type: 'input',
+        key: 'saleId',
+        placeholder: '订单ID'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    // rowKey: 'alias',
+    // isFrontPagination: true,
+    pagination: false,
+    bordered: true,
+    columnConfig: [
+      {
+        title: '决策名',
+        dataIndex: 'name',
+        render: (text, row, index) => {
+          if (index === 0) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[0]
+              }
+            }
+          } else if (format(this.page).includes(index)) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[format(this.page).indexOf(index) + 1]
+              }
+            }
+          } else {
+            return {
+              children: text,
+              props: {
+                rowSpan: 0
+              }
+            }
+          }
+        }
+      },
+      {
+        title: '决策输入',
+        dataIndex: 'tzname'
+        // render: renderContent
+      },
+      {
+        title: '决策输出',
+        dataIndex: 'tzvalue'
+        // render: renderContent
+      },
+      {
+        title: '决策结果',
+        dataIndex: 'result',
+        align: 'center',
+        width: 100,
+        render: (text, row, index) => {
+          if (index === 0) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[0]
+              }
+            }
+          } else if (format(this.page).includes(index)) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[format(this.page).indexOf(index) + 1]
+              }
+            }
+          } else {
+            return {
+              children: text,
+              props: {
+                rowSpan: 0
+              }
+            }
+          }
+        }
+      }, {
+        width: 1,
+        render: () => {
+          return {
+            children: '',
+            props: {
+            }
+          }
+        }
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  render () {
+    return (
+      <div>
+        <FilterTable fetctWhenMount={false} filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+      </div>
+    )
+  }
+}
+
+export default SaleRiskQuery

+ 164 - 0
src/pages/fengkong/risk/user/user.js

@@ -0,0 +1,164 @@
+import React from 'react'
+import { FilterTable } from 'wptpc-design'
+import { thanos } from '@/conf/config'
+
+const apiUrl = `${thanos}/thanos-admin/api/v1/risk/user/query`
+
+// const renderContent = (text, row, index) => {
+//   const obj = {
+//     children: text,
+//     props: {}
+//   }
+//   // if (index === 4) {
+//   obj.props.rowSpan = 1
+
+//   return text
+// }
+
+const format = (a) => {
+  const o = []
+  for (let i = 0; i < a.length - 1; i++) {
+    o.push(a.slice(0, i + 1).reduce((pre, next) => Number(pre) + Number(next)))
+  }
+  return o
+}
+
+class UserRiskQuery extends React.PureComponent {
+  state = {
+    showModal: false,
+    params: {
+    }
+  }
+
+  filterSetting = {
+    changeApiData: (data) => {
+      const list = []
+      const page = []
+      data.data.list.forEach(item => {
+        page.push(Object.keys(JSON.parse(item.input)).length)
+        for (const key in JSON.parse(item.input)) {
+          list.push({ name: item.name, output: item.output, tzname: key, tzvalue: JSON.parse(item.input)[key], result: item.output })
+        }
+      })
+      this.page = page
+      return {
+        code: 0,
+        data: { list: list }
+      }
+    },
+    isClearSearch: true,
+    formFields: [
+      {
+        label: '描述:',
+        type: 'input',
+        key: 'userId',
+        placeholder: '用户ID'
+      }
+    ]
+    // 在接口请求前,可以修改给接口的入参
+    // beforeSearchFunc: params => {
+    //   params.pageNum = params.pageNum
+    // }
+  }
+
+  // filtertable的列表配置
+  tableSetting = {
+    // rowKey: 'alias',
+    // isFrontPagination: true,
+    pagination: false,
+    bordered: true,
+    columnConfig: [
+      {
+        title: '决策名',
+        dataIndex: 'name',
+        render: (text, row, index) => {
+          if (index === 0) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[0]
+              }
+            }
+          } else if (format(this.page).includes(index)) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[format(this.page).indexOf(index) + 1]
+              }
+            }
+          } else {
+            return {
+              children: text,
+              props: {
+                rowSpan: 0
+              }
+            }
+          }
+        }
+      },
+      {
+        title: '决策输入',
+        dataIndex: 'tzname'
+        // render: renderContent
+      },
+      {
+        title: '决策输出',
+        dataIndex: 'tzvalue'
+        // render: renderContent
+      },
+      {
+        title: '决策结果',
+        dataIndex: 'result',
+        align: 'center',
+        width: 100,
+        render: (text, row, index) => {
+          if (index === 0) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[0]
+              }
+            }
+          } else if (format(this.page).includes(index)) {
+            return {
+              children: text,
+              props: {
+                rowSpan: this.page[format(this.page).indexOf(index) + 1]
+              }
+            }
+          } else {
+            return {
+              children: text,
+              props: {
+                rowSpan: 0
+              }
+            }
+          }
+        }
+      }, {
+        width: 1,
+        render: () => {
+          return {
+            children: '',
+            props: {
+            }
+          }
+        }
+      }
+    ],
+    getRefresh: refresh => {
+      this.refresh = refresh
+    }
+  }
+
+  render () {
+    return (
+      <div>
+        <FilterTable fetctWhenMount={false} filterSetting={this.filterSetting} tableSetting={this.tableSetting} apiUrl={apiUrl}
+        />
+      </div>
+    )
+  }
+}
+
+export default UserRiskQuery

+ 155 - 32
src/pages/fengkong/strategies/add/index.js

@@ -1,11 +1,12 @@
 import React from 'react'
-import { Form, Input, Row, Col, Switch, Button, Modal, message } from 'antd'
+import { Form, Input, Row, Col, Switch, Button, Modal, message, Select, Icon } from 'antd'
 import AceEditor from 'react-ace'
-import { create, test } from '../service'
+import { create, test, groupList } from '../service'
 
 import 'ace-builds/src-noconflict/mode-java'
 import 'ace-builds/src-noconflict/theme-monokai'
 import { connect } from 'dva'
+import router from 'umi/router'
 
 const formItemLayout = {
   layout: 'vertical'
@@ -18,15 +19,28 @@ const formItemLayout = {
 @Form.create()
 class Add extends React.PureComponent {
   state = {
+    type: 0,
     content: '',
     enabled: false,
+    timeTaskEnabled: false,
     showTest: false, // 是否展示测试内容
     testContent: '', // 测试数据
-    testResult: '' // 测试结果
+    testResult: '', // 测试结果
+    dos: [],
+    groupList: [],
+    group: '',
+    features: ''
+  }
+
+  componentDidMount () {
+    groupList({ pageNum: 999 }).then(res => this.setState({ groupList: res.data.list, group: res.data.list[0].name, features: res.data.list[0].features }))
   }
 
   create = () => {
     this.props.form.validateFields((err, values) => {
+      if (this.state.type === 4) {
+        values.content = JSON.stringify({ group: this.state.group, dos: this.state.dos })
+      }
       if (!err) {
         create({
           ...values,
@@ -37,8 +51,10 @@ class Add extends React.PureComponent {
             this.setState({ ...values })
             Modal.success({
               title: '提交成功',
-              content: '策代码编译正常,点击“测试按钮”可以继续测试策逻辑'
+              content: '策代码编译正常,点击“测试按钮”可以继续测试策逻辑'
             })
+            // 跳转到列表页
+            router.push('/fengkong/strategies/strategies')
           }
         })
       }
@@ -47,11 +63,16 @@ class Add extends React.PureComponent {
 
   test =() => {
     if (!this.state.name) {
-      message.warn('请先提交策略内容!')
+      message.warn('请先提交决策内容!')
+      return false
+    }
+    if (this.state.timeTaskEnabled) {
+      message.warn('定时启用不能测试,请先关闭!')
       return false
     }
     test({
       name: this.state.name,
+      type: this.state.type,
       input: JSON.parse(this.state.testContent)
     }).then(res => {
       if (res.code === 0) {
@@ -60,49 +81,151 @@ class Add extends React.PureComponent {
     })
   }
 
+  addDos = () => {
+    const dos = this.state.dos.slice()
+    dos.push({
+      r: { ep: '', f: '', v: '' }, ep: '', v: ''
+    })
+    this.setState({ dos: dos })
+  }
+
+  changeDos = (index, key, value) => {
+    const dos = this.state.dos.slice()
+    const keyList = key.split('.')
+
+    if (keyList.length > 1) {
+      dos[index][keyList[0]][keyList[1]] = value
+    } else {
+      dos[index][keyList[0]] = value
+    }
+    this.setState({ dos: dos })
+  }
+
+  removeDos = (index) => {
+    const dos = this.state.dos.slice()
+    dos.slice(index, 1)
+    this.setState({ dos: dos })
+  }
+
   render () {
     const { getFieldDecorator } = this.props.form
-
     return (
       <div>
-        <h1>新增策略</h1>
+        <h1>新增策</h1>
         <Row>
           <Col span={12}>
             <Form {...formItemLayout}>
-              <Form.Item label="策略名称">
+              <Form.Item label="策名称">
                 {getFieldDecorator('name')(<Input placeholder="全英文或英文带下划线" />)}
               </Form.Item>
-              <Form.Item label="策略描述">
+              <Form.Item label="策描述">
                 {getFieldDecorator('description')(<Input.TextArea placeholder="多行输入" />)}
               </Form.Item>
+              <Form.Item label="决策类型">
+                {getFieldDecorator('type', { initialValue: this.state.type })(
+                  <Select placeholder={'请选择类型'} onChange={value => this.setState({ type: value })}>
+                    <Select.Option value= {0}>策略</Select.Option>
+                    <Select.Option value= {1}>流程</Select.Option>
+                    <Select.Option value= {2}>模型</Select.Option>
+                    <Select.Option value= {3}>调度</Select.Option>
+                    <Select.Option value= {4}>规则</Select.Option>
+                  </Select>)
+                }
+              </Form.Item>
+              {
+                this.state.type === 4 && (
+                  <Form.Item label="特征分组">
+                    {getFieldDecorator('group', { initialValue: this.state.group })(
+                      <Select placeholder={'请选择分组'} onChange={value => this.setState({ group: value }, () => this.setState({ dos: [], features: this.state.groupList.filter(item => item.name === value)[0].features }))}>
+                        {
+                          this.state.groupList.map(item => <Select.Option value={item.name}>{item.name}</Select.Option>)
+                        }
+                      </Select>)
+                    }
+                  </Form.Item>
+                )
+              }
+
               <Form.Item label="是否启用">
                 {getFieldDecorator('enabled', {
                   initialValue: this.state.enabled
                 })(<Switch checked={this.state.enabled} onChange={checked => this.setState({ enabled: checked })} />)}
               </Form.Item>
-              <Form.Item label="策略逻辑开发">
-                {getFieldDecorator('content')(
-                  <AceEditor
-                    style={{ width: this.state.showTest ? '100%' : '200%' }}
-                    mode="java"
-                    theme="monokai"
-                    name="content"
-                    onChange={(value) => this.setState({ content: value })}
-                    fontSize={14}
-                    showPrintMargin={true}
-                    showGutter={true}
-                    highlightActiveLine={true}
-                    value={''}
-                    setOptions={{
-                      enableBasicAutocompletion: true,
-                      enableLiveAutocompletion: true,
-                      enableSnippets: true,
-                      showLineNumbers: true,
-                      tabSize: 2
-                    }}
-                  />
-                )}
-              </Form.Item>
+              {
+                this.state.type === 3 && (
+                  <Form.Item label="定时是否启用">
+                    {getFieldDecorator('timeTaskEnabled', {
+                      initialValue: this.state.timeTaskEnabled
+                    })(<Switch checked={this.state.timeTaskEnabled} onChange={checked => this.setState({ timeTaskEnabled: checked })} />)}
+                  </Form.Item>
+                )
+              }
+
+              {
+                this.state.type === 4 && (
+                  <Form.Item label="决策规则开发">
+                    <Button onClick={this.addDos}>点击创建规则</Button>
+                    {
+                      this.state.dos.map((item, index) => (
+                        <div style={{ margin: '10px 0' }}>
+                          <Select value={item.r.f} style={{ width: '150px' }} onChange={(value) => this.changeDos(index, 'r.f', value)}>
+                            {
+                              this.state.features.split(',').map(item => (<Select.Option value={item}>{item}</Select.Option>))
+                            }
+                          </Select>&emsp;
+                          <Select value={item.r.ep} style={{ width: '60px' }} onChange={(value) => this.changeDos(index, 'r.ep', value)}>
+                            <Select.Option value=">">{'>'}</Select.Option>
+                            <Select.Option value=">=">{'>='}</Select.Option>
+                            <Select.Option value="<">{'<'}</Select.Option>
+                            <Select.Option value="<=">{'<='}</Select.Option>
+                            <Select.Option value="!=">{'!='}</Select.Option>
+                          </Select>&emsp;
+                          <Input defaultValue={item.r.v} style={{ width: '50px' }} onChange={(e) => this.changeDos(index, 'r.v', e.target.value)} />&emsp;
+                          <Select value={item.ep} style={{ width: '50px' }} onChange={(value) => this.changeDos(index, 'ep', value)}>
+                            <Select.Option value="+">{'+'}</Select.Option>
+                            <Select.Option value="-">{'-'}</Select.Option>
+                            <Select.Option value="*">{'*'}</Select.Option>
+                            <Select.Option value="/">{'/'}</Select.Option>
+                          </Select>&emsp;
+                          <Input defaultValue={item.v} style={{ width: '50px' }} onChange={(e) => this.changeDos(index, 'v', e.target.value)} />&emsp;
+                          <Icon
+                            type="minus-circle-o"
+                            theme="twoTone"
+                            twoToneColor="#eb2f96"
+                            onClick={() => this.removeDos(index)}
+                          />
+                        </div>
+                      ))
+                    }
+                  </Form.Item>
+                )
+              }
+              {
+                this.state.type !== 4 && (<Form.Item label="决策逻辑开发">
+                  {getFieldDecorator('content')(
+                    <AceEditor
+                      style={{ width: this.state.showTest ? '100%' : '200%' }}
+                      mode="java"
+                      theme="monokai"
+                      name="content"
+                      onChange={(value) => this.setState({ content: value })}
+                      fontSize={14}
+                      showPrintMargin={true}
+                      showGutter={true}
+                      highlightActiveLine={true}
+                      value={''}
+                      setOptions={{
+                        enableBasicAutocompletion: true,
+                        enableLiveAutocompletion: true,
+                        enableSnippets: true,
+                        showLineNumbers: true,
+                        tabSize: 2
+                      }}
+                    />
+                  )}
+                </Form.Item>)
+
+              }
               <Form.Item>
                 <Button type="primary" onClick={this.create}>提交</Button>&emsp;
                 <Button onClick={() => this.setState({ showTest: true })}>测试</Button>

+ 166 - 33
src/pages/fengkong/strategies/edit/$name.js

@@ -1,8 +1,8 @@
 import React from 'react'
-import { Form, Input, Row, Col, Switch, Button, Modal, message } from 'antd'
+import { Form, Input, Row, Col, Switch, Button, Modal, message, Select, Icon } from 'antd'
 import { connect } from 'dva'
 import AceEditor from 'react-ace'
-import { detail, test, update } from '../service'
+import { detail, test, update, groupList } from '../service'
 import { isJSON } from '@/utils/utils'
 
 import 'ace-builds/src-noconflict/mode-java'
@@ -21,15 +21,33 @@ class Add extends React.PureComponent {
     content: '',
     showTest: false, // 是否展示测试内容
     testContent: '', // 测试数据
-    testResult: '' // 测试结果
+    testResult: '', // 测试结果
+    timeTaskEnabled: false,
+    dos: [],
+    groupList: [],
+    group: '',
+    features: ''
   }
 
-  componentDidMount () {
+  async componentDidMount () {
+    await groupList({ pageNum: 999 }).then(res => this.setState({ groupList: res.data.list }))
+
     detail({
       name: this.props.match.params.name
     }).then(res => {
       if (res.code === 0) {
-        this.setState({ ...res.data })
+        if (res.data.type === 4) {
+          const content = JSON.parse(res.data.content)
+          const fts = (this.state.groupList.filter(item => item.name === content.group)[0] || { features: '' }).features
+          const obj = Object.create(null)
+          fts.split(',').forEach((k, index) => {
+            obj[k.trim()] = 0
+          })
+          this.state.testContent = JSON.stringify(obj)
+          this.setState({ ...res.data, dos: content.dos, group: content.group, features: fts })
+        } else {
+          this.setState({ ...res.data })
+        }
       }
     })
   }
@@ -37,9 +55,13 @@ class Add extends React.PureComponent {
   create = () => {
     this.props.form.validateFields((err, values) => {
       if (!err) {
+        if (this.state.type === 4) {
+          values.content = JSON.stringify({ group: this.state.group, dos: this.state.dos })
+        } else {
+          values.content = this.state.content
+        }
         update({
           ...values,
-          content: this.state.content,
           createUser: this.state.createUser || this.props.currentUser.name, // 创建人
           updateUser: this.props.currentUser.name // 最后修改人
         }).then(res => {
@@ -47,7 +69,7 @@ class Add extends React.PureComponent {
             this.setState({ ...values })
             Modal.success({
               title: '提交成功',
-              content: '策代码编译正常,点击“测试按钮”可以继续测试策逻辑'
+              content: '策代码编译正常,点击“测试按钮”可以继续测试策逻辑'
             })
           }
         })
@@ -57,7 +79,11 @@ class Add extends React.PureComponent {
 
   test =(id) => {
     if (!this.state.name) {
-      message.warn('请先提交策略内容!')
+      message.warn('请先提交决策内容!')
+      return false
+    }
+    if (this.state.timeTaskEnabled) {
+      message.warn('定时启用不能测试,请先关闭!')
       return false
     }
     if (!isJSON(this.state.testContent)) {
@@ -66,61 +92,168 @@ class Add extends React.PureComponent {
     }
     test({
       name: this.state.name,
+      type: this.state.type,
       input: JSON.parse(this.state.testContent)
     }).then(res => {
       if (res.code === 0) {
-        console.log(res)
         this.setState({ testResult: JSON.stringify(res) })
       }
     })
   }
 
+  addDos = () => {
+    const dos = this.state.dos.slice()
+    dos.push({
+      r: { ep: '', f: '', v: '' }, ep: '', v: ''
+    })
+    this.setState({ dos: dos })
+  }
+
+  changeDos = (index, key, value) => {
+    const dos = this.state.dos.slice()
+    const keyList = key.split('.')
+
+    if (keyList.length > 1) {
+      dos[index][keyList[0]][keyList[1]] = value
+    } else {
+      dos[index][keyList[0]] = value
+    }
+    this.setState({ dos: dos })
+  }
+
+  removeDos = (index) => {
+    const dos = this.state.dos.slice()
+    dos.splice(index, 1)
+    this.setState({ dos: dos })
+  }
+
   render () {
     const { getFieldDecorator } = this.props.form
     const { name, description, enabled, content } = this.state
     return (
       <div>
-        <h1>编辑策略</h1>
+        <h1>编辑策</h1>
         <Row>
           <Col span={12}>
             <Form {...formItemLayout}>
-              <Form.Item label="策略名称">
+              <Form.Item label="策名称">
                 {getFieldDecorator('name', {
                   initialValue: name
                 })(<Input placeholder="全英文或英文带下划线" />)}
               </Form.Item>
-              <Form.Item label="策略描述">
+              <Form.Item label="策描述">
                 {getFieldDecorator('description', {
                   initialValue: description
                 })(<Input.TextArea placeholder="多行输入" />)}
               </Form.Item>
+              <Form.Item label="决策类型">
+                {getFieldDecorator('type', { initialValue: this.state.type })(
+                  <Select placeholder={'请选择类型'} onChange={value => this.setState({ type: value })}>
+                    <Select.Option value= {0}>策略</Select.Option>
+                    <Select.Option value= {1}>流程</Select.Option>
+                    <Select.Option value= {2}>模型</Select.Option>
+                    <Select.Option value= {3}>调度</Select.Option>
+                    <Select.Option value= {4}>规则</Select.Option>
+                  </Select>)
+                }
+              </Form.Item>
+
+              {
+                this.state.type === 4 && (
+                  <Form.Item label="特征分组">
+                    {getFieldDecorator('group', { initialValue: this.state.group })(
+                      <Select placeholder={'请选择分组'} onChange={value => this.setState({ group: value }, () => this.setState({ dos: [], features: this.state.groupList.filter(item => item.name === value)[0].features }))}>
+                        {
+                          this.state.groupList.map(item => <Select.Option value={item.name}>{item.name}</Select.Option>)
+                        }
+                      </Select>)
+                    }
+                  </Form.Item>
+                )
+              }
+
               <Form.Item label="是否启用">
                 {getFieldDecorator('enabled', {
                   initialValue: enabled
                 })(<Switch checked={enabled} onChange={checked => this.setState({ enabled: checked })} />)}
               </Form.Item>
-              <Form.Item label="策略逻辑开发">
+              {
+                // (this.state.type !== 3 && this.setState({ timeTaskEnabled: false })) ||
+                (this.state.type === 3 && (
+                  <Form.Item label="定时是否启用">
+                    {getFieldDecorator('timeTaskEnabled', {
+                      initialValue: this.state.timeTaskEnabled
+                    })(<Switch checked={this.state.timeTaskEnabled} onChange={checked => this.setState({ timeTaskEnabled: checked })} />)}
+                  </Form.Item>
+                ))
+              }
 
-                <AceEditor
-                  style={{ width: this.state.showTest ? '100%' : '200%' }}
-                  mode="java"
-                  theme="monokai"
-                  name="content"
-                  onChange={(value) => this.setState({ content: value })}
-                  fontSize={14}
-                  showPrintMargin={true}
-                  showGutter={true}
-                  highlightActiveLine={true}
-                  value={content}
-                  setOptions={{
-                    enableBasicAutocompletion: true,
-                    enableLiveAutocompletion: true,
-                    enableSnippets: true,
-                    showLineNumbers: true,
-                    tabSize: 2
-                  }}
-                />
-              </Form.Item>
+              {
+                this.state.type === 4 && (
+                  <Form.Item label="决策规则开发">
+                    <Button onClick={this.addDos}>点击创建规则</Button>
+                    {
+                      this.state.dos.map((item, index) => (
+                        <div style={{ margin: '10px 0' }}>
+                          <Select value={item.r.f} style={{ width: '150px' }} onChange={(value) => this.changeDos(index, 'r.f', value)}>
+                            {
+                              this.state.features.split(',').map(item => (<Select.Option value={item}>{item}</Select.Option>))
+                            }
+                          </Select>&emsp;
+                          <Select value={item.r.ep} style={{ width: '60px' }} onChange={(value) => this.changeDos(index, 'r.ep', value)}>
+                            <Select.Option value=">">{'>'}</Select.Option>
+                            <Select.Option value=">=">{'>='}</Select.Option>
+                            <Select.Option value="<">{'<'}</Select.Option>
+                            <Select.Option value="<=">{'<='}</Select.Option>
+                            <Select.Option value="!=">{'!='}</Select.Option>
+                            <Select.Option value="==">{'='}</Select.Option>
+                          </Select>&emsp;
+                          <Input defaultValue={item.r.v} style={{ width: '50px' }} onChange={(e) => this.changeDos(index, 'r.v', e.target.value)} />&emsp;
+                          <Select value={item.ep} style={{ width: '50px' }} onChange={(value) => this.changeDos(index, 'ep', value)}>
+                            <Select.Option value="+">{'+'}</Select.Option>
+                            <Select.Option value="-">{'-'}</Select.Option>
+                            <Select.Option value="*">{'*'}</Select.Option>
+                            <Select.Option value="/">{'/'}</Select.Option>
+                          </Select>&emsp;
+                          <Input defaultValue={item.v} style={{ width: '50px' }} onChange={(e) => this.changeDos(index, 'v', e.target.value)} />&emsp;
+                          <Icon
+                            type="minus-circle-o"
+                            theme="twoTone"
+                            twoToneColor="#eb2f96"
+                            onClick={() => this.removeDos(index)}
+                          />
+                        </div>
+                      ))
+                    }
+                  </Form.Item>
+                )
+              }
+
+              {
+                this.state.type !== 4 && (
+                  <Form.Item label="决策逻辑开发">
+                    <AceEditor
+                      style={{ width: this.state.showTest ? '100%' : '200%' }}
+                      mode="java"
+                      theme="monokai"
+                      name="content"
+                      onChange={(value) => this.setState({ content: value })}
+                      fontSize={14}
+                      showPrintMargin={true}
+                      showGutter={true}
+                      highlightActiveLine={true}
+                      value={content}
+                      setOptions={{
+                        enableBasicAutocompletion: true,
+                        enableLiveAutocompletion: true,
+                        enableSnippets: true,
+                        showLineNumbers: true,
+                        tabSize: 2
+                      }}
+                    />
+                  </Form.Item>
+                )
+              }
               <Form.Item>
                 <Button type="primary" onClick={this.create}>提交</Button>&emsp;
                 <Button onClick={() => this.setState({ showTest: true })}>测试</Button>

+ 12 - 0
src/pages/fengkong/strategies/service.js

@@ -29,3 +29,15 @@ export async function delItem (params) {
   const url = `${thanos}/thanos-admin/api/v1/dsl/delete`
   return fetchApi(url, params)
 }
+
+// 查询所有分组
+export async function groupList (params) {
+  const url = `${thanos}/thanos-admin/api/v1/group/list?_from=strategies`
+  return fetchApi(url, params)
+}
+
+// 查询分组详情
+export async function groupDetail (params) {
+  const url = `${thanos}/thanos-admin/api/v1/group/query?_from=strategies`
+  return fetchApi(url, params)
+}

+ 28 - 8
src/pages/fengkong/strategies/strategies.js

@@ -18,7 +18,7 @@ class GroupList extends React.PureComponent {
       to={{
         pathname: './add'
       }}
-    ><Button>新增策</Button></Link>,
+    ><Button>新增策</Button></Link>,
     isClearSearch: true,
     formFields: [
       {
@@ -30,7 +30,7 @@ class GroupList extends React.PureComponent {
     ]
     // 在接口请求前,可以修改给接口的入参
     // beforeSearchFunc: params => {
-    //   params.pageNum = params.pageNum
+    //   params.type = 3
     // }
   }
 
@@ -42,10 +42,10 @@ class GroupList extends React.PureComponent {
       pageSize: 10
     },
     columnConfig: [
-      {
-        title: 'ID',
-        dataIndex: 'id'
-      },
+      // {
+      //   title: 'ID',
+      //   dataIndex: 'id'
+      // },
       {
         title: '分组名称',
         dataIndex: 'name'
@@ -55,7 +55,28 @@ class GroupList extends React.PureComponent {
         dataIndex: 'description'
       },
       {
-        title: '策略是否启用',
+        title: '类型',
+        dataIndex: 'type',
+        render: (text) => {
+          if (text === 0) {
+            return '策略'
+          }
+          if (text === 1) {
+            return '流程'
+          }
+          if (text === 2) {
+            return '模型'
+          }
+          if (text === 3) {
+            return '调度'
+          }
+          if (text === 4) {
+            return '规则'
+          }
+        }
+      },
+      {
+        title: '决策是否启用',
         dataIndex: 'enabled',
         render: (text) => text === true ? '是' : '否'
       },
@@ -95,7 +116,6 @@ class GroupList extends React.PureComponent {
 
   // 点击编辑按钮时的事件处理函数
   editItem (record) {
-    console.log('11111111=')
     // const fields = JSON.parse(record.fieldsJson)
     // console.log('=====', fields)
     const { fields } = record

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 72 - 465
yarn.lock


Niektoré súbory nie sú zobrazené, pretože je v týchto rozdielových dátach zmenené mnoho súborov