mirror of https://github.com/openspug/spug
				
				
				
			A web update
							parent
							
								
									7901fea27b
								
							
						
					
					
						commit
						dd8c7c62e0
					
				|  | @ -40,12 +40,12 @@ class ComForm extends React.Component { | |||
|         <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|           <Form.Item required label="服务名称"> | ||||
|             {getFieldDecorator('name', {initialValue: info['name']})( | ||||
|               <Input placeholder="请输入服务名称,例如:订单处理服务"/> | ||||
|               <Input placeholder="请输入服务名称,例如:订单数据库"/> | ||||
|             )} | ||||
|           </Form.Item> | ||||
|           <Form.Item required label="唯一标识符"> | ||||
|             {getFieldDecorator('key', {initialValue: info['key']})( | ||||
|               <Input placeholder="请输入唯一标识符,例如:api_order"/> | ||||
|               <Input placeholder="请输入唯一标识符,例如:mysql_order"/> | ||||
|             )} | ||||
|           </Form.Item> | ||||
|           <Form.Item label="备注信息"> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ class AddSelect extends React.Component { | |||
|   switchExt1 = () => { | ||||
|     store.addVisible = false; | ||||
|     store.ext1Visible = true; | ||||
|     store.record = { | ||||
|     store.deploy = { | ||||
|       git_type: 'branch', | ||||
|       is_audit: false, | ||||
|       versions: 10, | ||||
|  | @ -21,7 +21,7 @@ class AddSelect extends React.Component { | |||
|   switchExt2 = () => { | ||||
|     store.addVisible = false; | ||||
|     store.ext2Visible = true; | ||||
|     store.record = { | ||||
|     store.deploy = { | ||||
|       is_audit: false, | ||||
|       host_ids: [undefined], | ||||
|       host_actions: [], | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ export default observer(function Ext1From() { | |||
|       visible | ||||
|       width={800} | ||||
|       maskClosable={false} | ||||
|       title={store.record.id ? '编辑常规发布' : '新建常规发布'} | ||||
|       title={store.deploy.id ? '编辑常规发布' : '新建常规发布'} | ||||
|       onCancel={() => store.ext1Visible = false} | ||||
|       footer={null}> | ||||
|       <Steps current={store.page} className={styles.steps}> | ||||
|  |  | |||
|  | @ -6,12 +6,9 @@ import envStore from 'pages/config/environment/store'; | |||
| import store from './store'; | ||||
| 
 | ||||
| export default observer(function Ext2Setup1() { | ||||
|   const info = store.record; | ||||
|   const info = store.deploy; | ||||
|   return ( | ||||
|     <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|       <Form.Item required label="应用名称" help="相同应用不同环境,请保持应用名称相同,以便维护"> | ||||
|         <Input value={info.name} onChange={e => info.name = e.target.value} placeholder="请输入应用名称"/> | ||||
|       </Form.Item> | ||||
|       <Form.Item required label="发布环境"> | ||||
|         <Col span={16}> | ||||
|           <Select value={info.env_id} onChange={v => info.env_id = v} placeholder="请选择发布环境"> | ||||
|  | @ -27,12 +24,6 @@ export default observer(function Ext2Setup1() { | |||
|       <Form.Item required label="Git仓库地址"> | ||||
|         <Input value={info['git_repo']} onChange={e => info['git_repo'] = e.target.value} placeholder="请输入Git仓库地址"/> | ||||
|       </Form.Item> | ||||
|       <Form.Item label="Tag/Branch"> | ||||
|         <Select value={info['git_type']} onChange={v => info['git_type'] = v}> | ||||
|           <Select.Option value="branch">Branch(分支)</Select.Option> | ||||
|           <Select.Option value="tag">Tag(标签 / 版本)</Select.Option> | ||||
|         </Select> | ||||
|       </Form.Item> | ||||
|       <Form.Item label="发布审核"> | ||||
|         <Switch | ||||
|           checkedChildren="开启" | ||||
|  | @ -43,7 +34,7 @@ export default observer(function Ext2Setup1() { | |||
|       <Form.Item wrapperCol={{span: 14, offset: 6}}> | ||||
|         <Button | ||||
|           type="primary" | ||||
|           disabled={!(info.name && info.env_id && info['git_repo'])} | ||||
|           disabled={!(info.env_id && info['git_repo'])} | ||||
|           onClick={() => store.page += 1}>下一步</Button> | ||||
|       </Form.Item> | ||||
|     </Form> | ||||
|  |  | |||
|  | @ -14,12 +14,12 @@ class Ext1Setup2 extends React.Component { | |||
|   } | ||||
| 
 | ||||
|   checkStatus = () => { | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     return info['dst_dir'] && info['dst_repo'] && info['versions'] && info['host_ids'].filter(x => x).length > 0 | ||||
|   }; | ||||
| 
 | ||||
|   render() { | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     return ( | ||||
|       <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|         <Form.Item required label="目标主机部署路径" help="目标主机的应用根目录,例如:/var/www/html"> | ||||
|  |  | |||
|  | @ -20,13 +20,14 @@ class Ext1Setup3 extends React.Component { | |||
| 
 | ||||
|   handleSubmit = () => { | ||||
|     this.setState({loading: true}); | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     info['app_id'] = store.app_id; | ||||
|     info['extend'] = '1'; | ||||
|     info['host_ids'] = info['host_ids'].filter(x => x); | ||||
|     http.post('/api/app/', info) | ||||
|     http.post('/api/app/deploy/', info) | ||||
|       .then(() => { | ||||
|         message.success('保存成功'); | ||||
|         store.fetchRecords(); | ||||
|         store.loadDeploys(store.app_id); | ||||
|         store.ext1Visible = false | ||||
|       }, () => this.setState({loading: false})) | ||||
|   }; | ||||
|  | @ -45,7 +46,7 @@ class Ext1Setup3 extends React.Component { | |||
|   ); | ||||
| 
 | ||||
|   render() { | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     return ( | ||||
|       <React.Fragment> | ||||
|         <Row> | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ export default observer(function Ext2From() { | |||
|       visible | ||||
|       width={800} | ||||
|       maskClosable={false} | ||||
|       title={store.record.id ? '编辑自定义发布' : '新建自定义发布'} | ||||
|       title={store.deploy.id ? '编辑自定义发布' : '新建自定义发布'} | ||||
|       onCancel={() => store.ext2Visible = false} | ||||
|       footer={null}> | ||||
|       <Steps current={store.page} className={styles.steps}> | ||||
|  |  | |||
|  | @ -6,12 +6,9 @@ import envStore from 'pages/config/environment/store'; | |||
| import store from './store'; | ||||
| 
 | ||||
| export default observer(function Ext2Setup1() { | ||||
|   const info = store.record; | ||||
|   const info = store.deploy; | ||||
|   return ( | ||||
|     <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|       <Form.Item required label="应用名称" help="相同应用不同环境,请保持应用名称相同,以便维护"> | ||||
|         <Input value={info.name} onChange={e => info.name = e.target.value} placeholder="请输入应用名称"/> | ||||
|       </Form.Item> | ||||
|       <Form.Item required label="发布环境"> | ||||
|         <Col span={16}> | ||||
|           <Select value={info.env_id} onChange={v => info.env_id = v} placeholder="请选择发布环境"> | ||||
|  | @ -34,7 +31,7 @@ export default observer(function Ext2Setup1() { | |||
|       <Form.Item wrapperCol={{span: 14, offset: 6}}> | ||||
|         <Button | ||||
|           type="primary" | ||||
|           disabled={!(info.name && info.env_id)} | ||||
|           disabled={!info.env_id} | ||||
|           onClick={() => store.page += 1}>下一步</Button> | ||||
|       </Form.Item> | ||||
|     </Form> | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ class Ext2Setup2 extends React.Component { | |||
|   } | ||||
| 
 | ||||
|   render() { | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     return ( | ||||
|       <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|         <Form.Item required label="发布目标主机"> | ||||
|  |  | |||
|  | @ -19,24 +19,25 @@ class Ext2Setup3 extends React.Component { | |||
| 
 | ||||
|   handleSubmit = () => { | ||||
|     this.setState({loading: true}); | ||||
|     const info = store.record; | ||||
|     const info = store.deploy; | ||||
|     info['app_id'] = store.app_id; | ||||
|     info['extend'] = '2'; | ||||
|     info['host_actions'] = info['host_actions'].filter(x => x.title && x.data); | ||||
|     info['server_actions'] = info['server_actions'].filter(x => x.title && x.data); | ||||
|     http.post('/api/app/', info) | ||||
|     http.post('/api/app/deploy/', info) | ||||
|       .then(res => { | ||||
|         message.success('保存成功'); | ||||
|         store.ext2Visible = false; | ||||
|         store.fetchRecords() | ||||
|         store.loadDeploys(store.app_id) | ||||
|       }, () => this.setState({loading: false})) | ||||
|   }; | ||||
| 
 | ||||
|   render() { | ||||
|     const server_actions = store.record['server_actions']; | ||||
|     const host_actions = store.record['host_actions']; | ||||
|     const server_actions = store.deploy['server_actions']; | ||||
|     const host_actions = store.deploy['host_actions']; | ||||
|     return ( | ||||
|       <Form labelCol={{span: 6}} wrapperCol={{span: 14}} className={styles.ext2Form}> | ||||
|         {store.record.id === undefined && ( | ||||
|         {store.deploy.id === undefined && ( | ||||
|           <Alert | ||||
|             closable | ||||
|             showIcon | ||||
|  |  | |||
|  | @ -0,0 +1,62 @@ | |||
| import React from 'react'; | ||||
| import { observer } from 'mobx-react'; | ||||
| import { Modal, Form, Input, message } from 'antd'; | ||||
| import http from 'libs/http'; | ||||
| import store from './store'; | ||||
| 
 | ||||
| @observer | ||||
| class ComForm extends React.Component { | ||||
|   constructor(props) { | ||||
|     super(props); | ||||
|     this.state = { | ||||
|       loading: false, | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   handleSubmit = () => { | ||||
|     this.setState({loading: true}); | ||||
|     const formData = this.props.form.getFieldsValue(); | ||||
|     formData['id'] = store.record.id; | ||||
|     http.post('/api/app/', formData) | ||||
|       .then(res => { | ||||
|         message.success('操作成功'); | ||||
|         store.formVisible = false; | ||||
|         store.fetchRecords() | ||||
|       }, () => this.setState({loading: false})) | ||||
|   }; | ||||
| 
 | ||||
|   render() { | ||||
|     const info = store.record; | ||||
|     const {getFieldDecorator} = this.props.form; | ||||
|     return ( | ||||
|       <Modal | ||||
|         visible | ||||
|         width={800} | ||||
|         maskClosable={false} | ||||
|         title={store.record.id ? '编辑应用' : '新建应用'} | ||||
|         onCancel={() => store.formVisible = false} | ||||
|         confirmLoading={this.state.loading} | ||||
|         onOk={this.handleSubmit}> | ||||
|         <Form labelCol={{span: 6}} wrapperCol={{span: 14}}> | ||||
|           <Form.Item required label="应用名称"> | ||||
|             {getFieldDecorator('name', {initialValue: info['name']})( | ||||
|               <Input placeholder="请输入应用名称,例如:订单服务"/> | ||||
|             )} | ||||
|           </Form.Item> | ||||
|           <Form.Item required label="唯一标识符"> | ||||
|             {getFieldDecorator('key', {initialValue: info['key']})( | ||||
|               <Input placeholder="请输入唯一标识符,例如:api_order"/> | ||||
|             )} | ||||
|           </Form.Item> | ||||
|           <Form.Item label="备注信息"> | ||||
|             {getFieldDecorator('desc', {initialValue: info['desc']})( | ||||
|               <Input.TextArea placeholder="请输入备注信息"/> | ||||
|             )} | ||||
|           </Form.Item> | ||||
|         </Form> | ||||
|       </Modal> | ||||
|     ) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export default Form.create()(ComForm) | ||||
|  | @ -1,4 +1,5 @@ | |||
| import React from 'react'; | ||||
| import { toJS } from 'mobx'; | ||||
| import { observer } from 'mobx-react'; | ||||
| import { Table, Divider, Modal, Tag, Icon, message } from 'antd'; | ||||
| import http from 'libs/http'; | ||||
|  | @ -25,22 +26,18 @@ class ComTable extends React.Component { | |||
|     title: '应用名称', | ||||
|     dataIndex: 'name', | ||||
|   }, { | ||||
|     title: '模式', | ||||
|     dataIndex: 'extend', | ||||
|     render: value => value === '1' ? <Icon style={{fontSize: 20, color: '#1890ff'}} type="ordered-list"/> : | ||||
|       <Icon style={{fontSize: 20, color: '#1890ff'}} type="build"/> | ||||
|     title: '标识符', | ||||
|     dataIndex: 'key' | ||||
|   }, { | ||||
|     title: '发布环境', | ||||
|     dataIndex: 'env_id', | ||||
|     render: value => lds.get(envStore.idMap, `${value}.name`) | ||||
|   }, { | ||||
|     title: '发布审核', | ||||
|     dataIndex: 'is_audit', | ||||
|     render: value => value ? <Tag color="green">开启</Tag> : <Tag color="red">关闭</Tag> | ||||
|     title: '描述信息', | ||||
|     dataIndex: 'desc', | ||||
|     ellipsis: true | ||||
|   }, { | ||||
|     title: '操作', | ||||
|     render: info => ( | ||||
|       <span> | ||||
|         <LinkButton onClick={() => store.showExtForm(info.id)}>新建发布</LinkButton> | ||||
|         <Divider type="vertical"/> | ||||
|         <LinkButton onClick={() => store.showForm(info)}>编辑</LinkButton> | ||||
|         <Divider type="vertical"/> | ||||
|         <LinkButton onClick={() => this.handleDelete(info)}>删除</LinkButton> | ||||
|  | @ -51,9 +48,9 @@ class ComTable extends React.Component { | |||
|   handleDelete = (text) => { | ||||
|     Modal.confirm({ | ||||
|       title: '删除确认', | ||||
|       content: `确定要删除【${text['name']}】?`, | ||||
|       content: `确定要删除应用【${text['name']}】?`, | ||||
|       onOk: () => { | ||||
|         return http.delete('/api/exec/template/', {params: {id: text.id}}) | ||||
|         return http.delete('/api/app/', {params: {id: text.id}}) | ||||
|           .then(() => { | ||||
|             message.success('删除成功'); | ||||
|             store.fetchRecords() | ||||
|  | @ -62,14 +59,75 @@ class ComTable extends React.Component { | |||
|     }) | ||||
|   }; | ||||
| 
 | ||||
|   handleDeployDelete = (text) => { | ||||
|     Modal.confirm({ | ||||
|       title: '删除确认', | ||||
|       content: `确定要删除【${lds.get(envStore.idMap, `${text.env_id}.name`)}】的发布配置?`, | ||||
|       onOk: () => { | ||||
|         return http.delete('/api/app/deploy/', {params: {id: text.id}}) | ||||
|           .then(() => { | ||||
|             message.success('删除成功'); | ||||
|             store.loadDeploys(text.app_id) | ||||
|           }) | ||||
|       } | ||||
|     }) | ||||
|   }; | ||||
| 
 | ||||
|   expandedRowRender = (record) => { | ||||
|     const columns = [{ | ||||
|       title: '模式', | ||||
|       dataIndex: 'extend', | ||||
|       render: value => value === '1' ? <Icon style={{fontSize: 20, color: '#1890ff'}} type="ordered-list"/> : | ||||
|         <Icon style={{fontSize: 20, color: '#1890ff'}} type="build"/>, | ||||
|       width: 80 | ||||
|     }, { | ||||
|       title: '发布环境', | ||||
|       dataIndex: 'env_id', | ||||
|       render: value => lds.get(envStore.idMap, `${value}.name`) | ||||
|     }, { | ||||
|       title: '关联主机', | ||||
|       dataIndex: 'host_ids', | ||||
|       render: value => `${value.length} 台` | ||||
|     }, { | ||||
|       title: '发布审核', | ||||
|       dataIndex: 'is_audit', | ||||
|       render: value => value ? <Tag color="green">开启</Tag> : <Tag color="red">关闭</Tag> | ||||
|     }, { | ||||
|       title: '操作', | ||||
|       render: info => ( | ||||
|         <span> | ||||
|         <LinkButton onClick={() => store.showExtForm(record.id, info)}>编辑</LinkButton> | ||||
|         <Divider type="vertical"/> | ||||
|         <LinkButton onClick={() => this.handleDeployDelete(info)}>删除</LinkButton> | ||||
|       </span> | ||||
|       ) | ||||
|     }]; | ||||
| 
 | ||||
|     if (record['deploys'] === undefined) { | ||||
|       store.loadDeploys(record.id) | ||||
|     } | ||||
| 
 | ||||
|     return <Table | ||||
|       rowKey="id" | ||||
|       loading={record['deploys'] === undefined} | ||||
|       columns={columns} | ||||
|       dataSource={record['deploys']} | ||||
|       pagination={false} /> | ||||
|   }; | ||||
| 
 | ||||
|   render() { | ||||
|     console.debug(JSON.stringify(envStore.idMap)); | ||||
|     let data = store.records; | ||||
|     let data = Object.values(toJS(store.records)); | ||||
|     if (store.f_name) { | ||||
|       data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase())) | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|       <Table rowKey="id" loading={store.isFetching} dataSource={data} columns={this.columns}/> | ||||
|       <Table | ||||
|         rowKey="id" | ||||
|         loading={store.isFetching} | ||||
|         dataSource={data} | ||||
|         expandedRowRender={this.expandedRowRender} | ||||
|         columns={this.columns}/> | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ import { observer } from 'mobx-react'; | |||
| import { Card, Input, Button } from 'antd'; | ||||
| import { SearchForm } from 'components'; | ||||
| import ComTable from './Table'; | ||||
| import ComForm from './Form'; | ||||
| import Ext1Form from './Ext1Form'; | ||||
| import Ext2Form from './Ext2Form'; | ||||
| import AddSelect from './AddSelect'; | ||||
|  | @ -23,6 +24,7 @@ export default observer(function () { | |||
|         <Button type="primary" icon="plus" onClick={() => store.showForm()}>新建</Button> | ||||
|       </div> | ||||
|       <ComTable/> | ||||
|       {store.formVisible && <ComForm />} | ||||
|       {store.addVisible && <AddSelect />} | ||||
|       {store.ext1Visible &&  <Ext1Form />} | ||||
|       {store.ext2Visible &&  <Ext2Form />} | ||||
|  |  | |||
|  | @ -2,10 +2,13 @@ import { observable } from "mobx"; | |||
| import http from 'libs/http'; | ||||
| 
 | ||||
| class Store { | ||||
|   @observable records = []; | ||||
|   @observable records = {}; | ||||
|   @observable record = {}; | ||||
|   @observable deploy = {}; | ||||
|   @observable page = 0; | ||||
|   @observable loading = {}; | ||||
|   @observable isFetching = false; | ||||
|   @observable formVisible = false; | ||||
|   @observable addVisible = false; | ||||
|   @observable ext1Visible = false; | ||||
|   @observable ext2Visible = false; | ||||
|  | @ -15,34 +18,51 @@ class Store { | |||
|   fetchRecords = () => { | ||||
|     this.isFetching = true; | ||||
|     http.get('/api/app/') | ||||
|       .then(res => this.records = res) | ||||
|       .then(res => { | ||||
|         const tmp = {}; | ||||
|         for (let item of res) { | ||||
|           tmp[item.id] = item | ||||
|         } | ||||
|         this.records = tmp | ||||
|       }) | ||||
|       .finally(() => this.isFetching = false) | ||||
|   }; | ||||
| 
 | ||||
|   loadDeploys = (id) => { | ||||
|     http.get('/api/app/deploy/', {params: {id}}) | ||||
|       .then(res => this.records[id]['deploys'] = res) | ||||
|   }; | ||||
| 
 | ||||
|   showForm = (info) => { | ||||
|     this.record = info || {}; | ||||
|     this.formVisible = true; | ||||
|   }; | ||||
| 
 | ||||
|   showExtForm = (app_id, info) => { | ||||
|     this.page = 0; | ||||
|     this.app_id = app_id; | ||||
|     if (info) { | ||||
|       if (info.extend === '1') { | ||||
|         this.ext1Visible = true | ||||
|       } else { | ||||
|         this.ext2Visible = true | ||||
|       } | ||||
|       this.record = info | ||||
|       this.deploy = info | ||||
|     } else { | ||||
|       this.addVisible = true; | ||||
|     } | ||||
|   }; | ||||
| 
 | ||||
|   addHost = () => { | ||||
|     this.record['host_ids'].push(undefined) | ||||
|     this.deploy['host_ids'].push(undefined) | ||||
|   }; | ||||
| 
 | ||||
|   editHost = (index, v) => { | ||||
|     this.record['host_ids'][index] = v | ||||
|     this.deploy['host_ids'][index] = v | ||||
|   }; | ||||
| 
 | ||||
|   delHost = (index) => { | ||||
|     this.record['host_ids'].splice(index, 1) | ||||
|     this.deploy['host_ids'].splice(index, 1) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 雷二猛
						雷二猛