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"