From e58c66734a24f59da25e8fd99855fc806e48bb37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E4=BA=8C=E7=8C=9B?= Date: Thu, 21 Nov 2019 15:33:46 +0800 Subject: [PATCH] U web add exec template --- spug_web/package.json | 2 + spug_web/src/menus.js | 5 + spug_web/src/pages/exec/routes.js | 7 ++ spug_web/src/pages/exec/template/Form.js | 116 ++++++++++++++++++++++ spug_web/src/pages/exec/template/Table.js | 76 ++++++++++++++ spug_web/src/pages/exec/template/index.js | 32 ++++++ spug_web/src/pages/exec/template/store.js | 30 ++++++ spug_web/src/routes.js | 2 + spug_web/yarn.lock | 31 ++++++ 9 files changed, 301 insertions(+) create mode 100644 spug_web/src/pages/exec/routes.js create mode 100644 spug_web/src/pages/exec/template/Form.js create mode 100644 spug_web/src/pages/exec/template/Table.js create mode 100644 spug_web/src/pages/exec/template/index.js create mode 100644 spug_web/src/pages/exec/template/store.js diff --git a/spug_web/package.json b/spug_web/package.json index ea6094d..5f3c242 100644 --- a/spug_web/package.json +++ b/spug_web/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "ace-builds": "^1.4.7", "antd": "^3.25.0", "axios": "^0.19.0", "history": "^4.10.1", @@ -10,6 +11,7 @@ "mobx": "^5.15.0", "mobx-react": "^6.1.4", "react": "^16.11.0", + "react-ace": "^8.0.0", "react-dom": "^16.11.0", "react-router-dom": "^5.1.2", "react-scripts": "3.2.0" diff --git a/spug_web/src/menus.js b/spug_web/src/menus.js index 3fd57dc..e1f4b78 100644 --- a/spug_web/src/menus.js +++ b/spug_web/src/menus.js @@ -1,6 +1,11 @@ export default [ {icon: 'desktop', title: '工作台', path: '/home'}, {icon: 'cloud-server', title: '主机管理', path: '/host'}, + { + icon: 'deployment-unit', title: '批量执行', child: [ + {title: '执行模板', path: '/exec/template'}, + ] + }, { icon: 'setting', title: '系统管理', child: [ {title: '账户管理', path: '/system/account'}, diff --git a/spug_web/src/pages/exec/routes.js b/spug_web/src/pages/exec/routes.js new file mode 100644 index 0000000..103a0bb --- /dev/null +++ b/spug_web/src/pages/exec/routes.js @@ -0,0 +1,7 @@ +import { makeRoute } from "../../libs/router"; +import Template from './template'; + + +export default [ + makeRoute('/template', Template), +] \ No newline at end of file diff --git a/spug_web/src/pages/exec/template/Form.js b/spug_web/src/pages/exec/template/Form.js new file mode 100644 index 0000000..30ce4c5 --- /dev/null +++ b/spug_web/src/pages/exec/template/Form.js @@ -0,0 +1,116 @@ +import React from 'react'; +import { observer } from 'mobx-react'; +import { Modal, Form, Input, Select, Col, Button, message } from 'antd'; +import Editor from 'react-ace'; +import 'ace-builds/src-noconflict/ext-language_tools'; +import 'ace-builds/src-noconflict/mode-sh'; +import 'ace-builds/src-noconflict/theme-tomorrow'; +import 'ace-builds/src-noconflict/snippets/sh'; +import http from 'libs/http'; +import store from './store'; + +@observer +class ComForm extends React.Component { + constructor(props) { + super(props); + this.state = { + loading: false, + type: null, + body: store.record['body'], + } + } + + handleSubmit = () => { + this.setState({loading: true}); + const formData = this.props.form.getFieldsValue(); + formData['id'] = store.record.id; + formData['body'] = this.state.body; + http.post('/api/exec/template/', formData) + .then(res => { + message.success('操作成功'); + store.formVisible = false; + store.fetchRecords() + }, () => this.setState({loading: false})) + }; + + handleAddZone = () => { + Modal.confirm({ + icon: 'exclamation-circle', + title: '添加模板类型', + content: this.addZoneForm, + onOk: () => { + if (this.state.type) { + store.types.push(this.state.type); + this.props.form.setFieldsValue({'type': this.state.type}) + } + }, + }) + }; + + addZoneForm = ( +
+ + this.setState({type: val.target.value})}/> + +
+ ); + + render() { + const info = store.record; + const {getFieldDecorator} = this.props.form; + const itemLayout = { + labelCol: {span: 6}, + wrapperCol: {span: 14} + }; + return ( + store.formVisible = false} + confirmLoading={this.state.loading} + onOk={this.handleSubmit}> +
+ + + {getFieldDecorator('type', {initialValue: info['type']})( + + )} + + + + + + + {getFieldDecorator('name', {initialValue: info['name']})( + + )} + + + this.setState({body: val})} + enableLiveAutocompletion={true} + enableBasicAutocompletion={true} + enableSnippets={true} + height="300px"/> + + + {getFieldDecorator('desc', {initialValue: info['desc']})( + + )} + +
+
+ ) + } +} + +export default Form.create()(ComForm) \ No newline at end of file diff --git a/spug_web/src/pages/exec/template/Table.js b/spug_web/src/pages/exec/template/Table.js new file mode 100644 index 0000000..99fda65 --- /dev/null +++ b/spug_web/src/pages/exec/template/Table.js @@ -0,0 +1,76 @@ +import React from 'react'; +import { observer } from 'mobx-react'; +import { Table, Divider, Modal, message } from 'antd'; +import ComForm from './Form'; +import http from 'libs/http'; +import store from './store'; +import { LinkButton } from "components"; + +@observer +class ComTable extends React.Component { + componentDidMount() { + store.fetchRecords() + } + + columns = [{ + title: '序号', + key: 'series', + render: (_, __, index) => index + 1, + width: 80, + }, { + title: '模版名称', + dataIndex: 'name', + }, { + title: '模版类型', + dataIndex: 'type', + }, { + title: '模版内容', + render: text => text.body, + ellipsis: true + }, { + title: '描述信息', + dataIndex: 'desc', + ellipsis: true + }, { + title: '操作', + render: info => ( + + store.showForm(info)}>编辑 + + this.handleDelete(info)}>删除 + + ) + }]; + + handleDelete = (text) => { + Modal.confirm({ + title: '删除确认', + content: `确定要删除【${text['name']}】?`, + onOk: () => { + return http.delete('/api/exec/template/', {params: {id: text.id}}) + .then(() => { + message.success('删除成功'); + store.fetchRecords() + }) + } + }) + }; + + render() { + let data = store.records; + if (store.f_name) { + data = data.filter(item => item['name'].toLowerCase().includes(store.f_name.toLowerCase())) + } + if (store.f_type) { + data = data.filter(item => item['type'].toLowerCase().includes(store.f_type.toLowerCase())) + } + return ( + + + {store.formVisible && } + + ) + } +} + +export default ComTable \ No newline at end of file diff --git a/spug_web/src/pages/exec/template/index.js b/spug_web/src/pages/exec/template/index.js new file mode 100644 index 0000000..78fbfd7 --- /dev/null +++ b/spug_web/src/pages/exec/template/index.js @@ -0,0 +1,32 @@ +import React from 'react'; +import { observer } from 'mobx-react'; +import { Card, Input, Select, Button } from 'antd'; +import { SearchForm } from 'components'; +import ComTable from './Table'; +import store from './store'; + +export default observer(function () { + return ( + + + + + + + store.f_name = e.target.value} placeholder="请输入"/> + + + + + +
+ +
+ +
+ ) +}) \ No newline at end of file diff --git a/spug_web/src/pages/exec/template/store.js b/spug_web/src/pages/exec/template/store.js new file mode 100644 index 0000000..6d4ee39 --- /dev/null +++ b/spug_web/src/pages/exec/template/store.js @@ -0,0 +1,30 @@ +import { observable } from "mobx"; +import http from 'libs/http'; + +class Store { + @observable records = []; + @observable types = []; + @observable record = {}; + @observable isFetching = false; + @observable formVisible = false; + + @observable f_name; + @observable f_type; + + fetchRecords = () => { + this.isFetching = true; + http.get('/api/exec/template/') + .then(({types, templates}) => { + this.records = templates; + this.types = types + }) + .finally(() => this.isFetching = false) + }; + + showForm = (info = {}) => { + this.formVisible = true; + this.record = info + } +} + +export default new Store() \ No newline at end of file diff --git a/spug_web/src/routes.js b/spug_web/src/routes.js index 66f9ebc..1b5d76f 100644 --- a/spug_web/src/routes.js +++ b/spug_web/src/routes.js @@ -3,10 +3,12 @@ import { makeModuleRoute } from "./libs/router"; import homeRoutes from './pages/home/routes'; import hostRoutes from './pages/host/routes'; import systemRoutes from './pages/system/routes'; +import execRoutes from './pages/exec/routes'; export default [ makeModuleRoute('/home', homeRoutes), makeModuleRoute('/host', hostRoutes), makeModuleRoute('/system', systemRoutes), + makeModuleRoute('/exec', execRoutes), ] \ No newline at end of file diff --git a/spug_web/yarn.lock b/spug_web/yarn.lock index cf4f336..664d801 100644 --- a/spug_web/yarn.lock +++ b/spug_web/yarn.lock @@ -1670,6 +1670,11 @@ accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +ace-builds@^1.4.6, ace-builds@^1.4.7: + version "1.4.7" + resolved "https://registry.npm.taobao.org/ace-builds/download/ace-builds-1.4.7.tgz#56e5465270b6c48a48d30e70d6b8f6b92fbf2b08" + integrity sha1-VuVGUnC2xIpI0w5w1rj2uS+/Kwg= + acorn-globals@^4.1.0, acorn-globals@^4.3.0: version "4.3.4" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" @@ -3546,6 +3551,11 @@ detect-port-alt@1.1.6: address "^1.0.1" debug "^2.6.0" +diff-match-patch@^1.0.4: + version "1.0.4" + resolved "https://registry.npm.taobao.org/diff-match-patch/download/diff-match-patch-1.0.4.tgz#6ac4b55237463761c4daf0dc603eb869124744b1" + integrity sha1-asS1UjdGN2HE2vDcYD64aRJHRLE= + diff-sequences@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" @@ -6412,6 +6422,11 @@ lodash.flow@^3.5.0: resolved "https://registry.npm.taobao.org/lodash.flow/download/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.npm.taobao.org/lodash.get/download/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + lodash.isarguments@^3.0.0: version "3.1.0" resolved "https://registry.npm.taobao.org/lodash.isarguments/download/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" @@ -6422,6 +6437,11 @@ lodash.isarray@^3.0.0: resolved "https://registry.npm.taobao.org/lodash.isarray/download/lodash.isarray-3.0.4.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.isarray%2Fdownload%2Flodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.npm.taobao.org/lodash.isequal/download/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA= + lodash.keys@^3.1.2: version "3.1.2" resolved "https://registry.npm.taobao.org/lodash.keys/download/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -9019,6 +9039,17 @@ rc@^1.2.7: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-ace@^8.0.0: + version "8.0.0" + resolved "https://registry.npm.taobao.org/react-ace/download/react-ace-8.0.0.tgz#e6fc155ec3cf240e92bdf2e156a50458a78ed0a4" + integrity sha1-5vwVXsPPJA6SvfLhVqUEWKeO0KQ= + dependencies: + ace-builds "^1.4.6" + diff-match-patch "^1.0.4" + lodash.get "^4.4.2" + lodash.isequal "^4.5.0" + prop-types "^15.7.2" + react-app-polyfill@^1.0.4: version "1.0.4" resolved "https://registry.npm.taobao.org/react-app-polyfill/download/react-app-polyfill-1.0.4.tgz#4dd2636846b585c2d842b1e44e1bc29044345874"