es文档开发

This commit is contained in:
暮光:城中城
2019-07-26 23:48:48 +08:00
parent fc02414519
commit 9d7149aa04
8 changed files with 322 additions and 11 deletions

View File

@@ -4,21 +4,28 @@ import com.zyplayer.doc.core.json.DocResponseJson;
import com.zyplayer.doc.core.json.ResponseJson;
import com.zyplayer.doc.data.service.elasticsearch.support.ElasticSearchUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.client.indices.GetMappingsRequest;
import org.elasticsearch.client.indices.GetMappingsResponse;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.script.ScriptType;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateResponse;
import org.elasticsearch.search.SearchHit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
@@ -57,9 +64,43 @@ public class EsMappingController {
return DocResponseJson.warn("获取文档失败");
}
@GetMapping("/list")
public ResponseJson<Object> list(String keywords) throws IOException {
return DocResponseJson.ok();
@PostMapping("/execute")
public ResponseJson<Object> execute(String index, String sql) throws IOException {
SearchTemplateRequest request = new SearchTemplateRequest();
request.setRequest(new SearchRequest().indices(index));
request.setScriptType(ScriptType.INLINE);
request.setScript(sql);
request.setScriptParams(new HashMap<>());
try {
RestHighLevelClient client = elasticSearchUtil.getEsClient("127.0.0.1:9200", "http");
SearchTemplateResponse response = client.searchTemplate(request, RequestOptions.DEFAULT);
List<Map<String, Object>> resultList = new LinkedList<>();
for (SearchHit searchHit : response.getResponse().getHits()) {
resultList.add(searchHit.getSourceAsMap());
}
return DocResponseJson.ok(resultList);
} catch (Exception e) {
return DocResponseJson.warn(e.getMessage());
}
}
@GetMapping("/index")
public ResponseJson<Object> index(String index) throws IOException {
GetIndexRequest request = new GetIndexRequest(index);
request.setMasterTimeout(TimeValue.timeValueMinutes(1));
try {
RestHighLevelClient client = elasticSearchUtil.getEsClient("127.0.0.1:9200", "http");
GetIndexResponse indexResponse = client.indices().get(request, RequestOptions.DEFAULT);
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("mapping", indexResponse.getMappings().get(index));
resultMap.put("setting", indexResponse.getSettings().get(index).keySet());
// return DocResponseJson.ok(indexResponse.getSetting(index, "index.number_of_shards"));
return DocResponseJson.ok(resultMap);
} catch (Exception e) {
e.printStackTrace();
}
return DocResponseJson.warn("获取文档失败");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 331 B

View File

@@ -15,6 +15,7 @@ var URL = {
manageUpdateDatasource: '/zyplayer-doc-db/datasource/update',
esMappings: '/zyplayer-doc-es/es-mapping/mappings',
esExecuter: '/zyplayer-doc-es/es-mapping/execute',
systemUpgradeInfo: '/system/info/upgrade',
};

View File

@@ -5,14 +5,14 @@ var href = window.location.href;
var _fn = {
href: href,
// 本地启动时使用本地接口调试
// HOST: 'http://local.zyplayer.com:8083/zyplayer-doc-manage',
// HOST1: 'http://local.zyplayer.com:8083/zyplayer-doc-manage',
HOST: 'http://local.zyplayer.com:8083/zyplayer-doc-manage',
HOST1: 'http://local.zyplayer.com:8083/zyplayer-doc-manage',
// 也可以直接使用线上的服务调试
// HOST: 'http://doc.zyplayer.com/zyplayer-doc-manage',
// HOST1: 'http://doc.zyplayer.com/zyplayer-doc-manage',
// 打包时使用下面这两行,文件就放在根目录下,所以当前路劲就好
HOST: './',
HOST1: './',
// HOST: './',
// HOST1: './',
mixUrl: function (host, url) {
var p;

View File

@@ -0,0 +1,122 @@
/**
* 将对象处理成json格式化和着色的html
* @author 暮光:城中城
* @since 2017年5月7日
*/
export default {
// 需要在对象或列表后面添加注释的对象,例:{userList: "用户列表"}
// 那么在名字为userList的对象或列表后面都会加上“用户列表” 这个注释
annotationObject: {},
tabStr: " ",
isArray: function (obj) {
return obj && typeof obj === 'object' && typeof obj.length === 'number'
&& !(obj.propertyIsEnumerable('length'));
},
processObjectToHtmlPre: function (obj, indent, addComma, isArray, isPropertyContent, showAnnotation) {
var htmlStr = this.processObject(obj, "", indent, addComma, isArray, isPropertyContent, showAnnotation);
htmlStr = '<pre class="json">' + htmlStr + '</pre>';
return htmlStr;
},
processObject: function (obj, keyName, indent, addComma, isArray, isPropertyContent, showAnnotation) {
var html = "";
var comma = (addComma) ? "<span class='comma'>,</span> " : "";
var type = typeof obj;
if (this.isArray(obj)) {
if (obj.length == 0) {
html += this.getRow(indent, "<span class='array-brace'>[ ]</span>" + comma, isPropertyContent);
} else {// <img class="option-img" src="../../assets/img/expanded.png" />
var clpsHtml = '<span><div class="option-img img-expanded"></div></span><span class="collapsible">';
var annotation = '';
if (showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
annotation = '<span class="annotation">// ' + this.annotationObject[keyName] + '</span>';
}
html += this.getRow(indent, "<span class='array-brace'>[</span>" + clpsHtml + annotation, isPropertyContent);
for (var i = 0; i < obj.length; i++) {
html += this.processObject(obj[i], "", indent + 1, i < (obj.length - 1), true, false, showAnnotation);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='array-brace'>]</span>" + comma);
}
} else if (type == 'object' && obj == null) {
html += this.formatLiteral("null", "", comma, indent, isArray, "null");
} else if (type == 'object') {
var numProps = 0;
for (var prop in obj) {
numProps++;
}
if (numProps == 0) {
html += this.getRow(indent, "<span class='object-brace'>{ }</span>" + comma, isPropertyContent);
} else { //<img class="option-img img-expanded" src="../../assets/img/expanded.png"/>
var clpsHtml = '<span><div class="option-img img-expanded"></div></span><span class="collapsible">';
var annotation = '';
if (showAnnotation && isNotEmpty(keyName) && isNotEmpty(this.annotationObject[keyName])) {
annotation = '<span class="annotation">// ' + this.annotationObject[keyName] + '</span>';
}
html += this.getRow(indent, "<span class='object-brace'>{</span>" + clpsHtml + annotation, isPropertyContent);
var j = 0;
for (var prop in obj) {
var processStr = '<span class="property-name">"' + prop + '"</span>: ' + this.processObject(obj[prop], prop, indent + 1, ++j < numProps, false, true, showAnnotation);
html += this.getRow(indent + 1, processStr);
}
clpsHtml = "</span>";
html += this.getRow(indent, clpsHtml + "<span class='object-brace'>}</span>" + comma);
}
} else if (type == 'number') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "number");
} else if (type == 'boolean') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "boolean");
} else if (type == 'function') {
obj = this.formatFunction(indent, obj);
html += this.formatLiteral(obj, "", comma, indent, isArray, "function");
} else if (type == 'undefined') {
html += this.formatLiteral("undefined", "", comma, indent, isArray, "null");
} else {
html += this.formatLiteral(obj, "\"", comma, indent, isArray, "string");
}
return html;
},
expImgClicked: function (img) {
var container = img.parentNode.nextSibling;
if (!container) return;
var disp = "none";
var cls = "option-img img-collapsed";
if (container.style.display == "none") {
disp = "inline";
cls = "option-img img-expanded";
}
img.className = cls;
container.style.display = disp;
},
formatLiteral: function (literal, quote, comma, indent, isArray, style) {
if (typeof literal == 'string') {
literal = literal.split("<").join("&lt;").split(">").join("&gt;");
}
var str = "<span class='" + style + "'>" + quote + literal + quote + comma + "</span>";
if (isArray) {
str = this.getRow(indent, str);
}
return str;
},
formatFunction: function (indent, obj) {
var tabs = "";
for (var i = 0; i < indent; i++) {
tabs += this.tabStr;
}
var funcStrArray = obj.toString().split("\n");
var str = "";
for (var i = 0; i < funcStrArray.length; i++) {
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
}
return str;
},
getRow: function (indent, data, isPropertyContent) {
var tabs = "";
for (var i = 0; i < indent && !isPropertyContent; i++) {
tabs += this.tabStr;
}
if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
data = data + "\n";
}
return tabs + data;
}
}

View File

@@ -8,6 +8,7 @@ import DataDatasourceManage from './views/data/DatasourceManage.vue'
import DataRouterView from './views/data/RouterView.vue'
import IndexShow from './views/index/Show.vue'
import IndexExecuter from './views/index/Executer.vue'
import IndexRouterView from './views/index/RouterView.vue'
import CommonNoAuth from './views/common/NoAuth.vue'
@@ -34,6 +35,7 @@ let routes = [
component: IndexRouterView,
children: [
{path: 'show', name: '索引信息',component: IndexShow},
{path: 'executer', name: '执行器',component: IndexExecuter},
]
}, {
path: '/data',

View File

@@ -0,0 +1,145 @@
<template>
<div class="index-executer-vue">
<el-card style="margin: 10px;">
<div style="margin: 10px 0;">
<span>选择索引</span>
<el-select v-model="executeParam.index" filterable placeholder="选择索引">
<el-option label="zyplayer_doc_wiki" value="zyplayer_doc_wiki"></el-option>
</el-select>
</div>
<el-input type="textarea" v-model="executeParam.sql" :rows="10" placeholder="请输入"></el-input>
<div style="text-align: center;margin: 10px 0;">
<el-button type="primary" v-on:click="submitExecute">执行</el-button>
</div>
</el-card>
<el-card style="margin: 10px;">
<div style="margin: 10px 0;">
<span>执行结果{{executeResult.errCode == 200 ? '成功' : '失败'}}</span>
</div>
<div style="margin: 10px 0;" v-if="executeResult.errCode == 200">
<div style="margin: 10px 0;">返回结果</div>
<div v-html="executeResult.data" @click="executeResultClick($event)"></div>
</div>
<div style="margin: 10px 0;" v-else>
<div style="margin: 10px 0;">错误信息</div>
<div class="error-text">{{executeResult.errMsg}}</div>
</div>
</el-card>
</div>
</template>
<script>
import global from '../../common/config/global'
import formatjson from '../../common/lib/common/formatjson'
var app;
export default {
data() {
return {
indexMappingListLoading: false,
vueQueryParam: {},
indexMappingList: [],
executeParam: {
sql: '',
index: '',
},
executeResult: {},
};
},
beforeRouteUpdate(to, from, next) {
this.initQueryParam(to);
next();
},
mounted: function () {
app = this;
this.initQueryParam(this.$route);
// 延迟设置展开的目录edit比app先初始化
setTimeout(function () {
//global.vue.$app.initLoadDataList(app.vueQueryParam.host, app.vueQueryParam.dbName);
}, 500);
},
methods: {
submitExecute() {
this.indexMappingListLoading = true;
this.executeResult = {};
this.common.postNonCheck(this.apilist1.esExecuter, this.executeParam, function (json) {
var executeResult = json;
try {
executeResult.data = formatjson.processObjectToHtmlPre(json.data, 0, false, false, false, false);
} catch (e) {
executeResult.data = "结果解析失败";
}
app.executeResult = executeResult;
app.indexMappingListLoading = false;
});
},
executeResultClick(e) {
if (e.target.className.indexOf('option-img') >= 0) {
formatjson.expImgClicked(e.target);
}
},
initQueryParam(to) {
// this.indexMappingListLoading = true;
// this.vueQueryParam = to.query;
// this.common.post(this.apilist1.esMappings, this.vueQueryParam, function (json) {
// var data = json.data || {};
// var properties = data[app.vueQueryParam.index].sourceAsMap.properties;
// var propertiesArr = [];
// for (var propertiesKey in properties) {
// var propertiesItem = properties[propertiesKey];
// var item = {
// name: propertiesKey, type: propertiesItem.type
// };
// propertiesArr.push(item);
// }
// app.indexMappingList = propertiesArr;
// app.indexMappingListLoading = false;
// });
},
}
}
</script>
<style>
.index-executer-vue .el-form-item{margin-bottom: 5px;}
.index-executer-vue .edit-table-desc{cursor: pointer; color: #409EFF;}
.index-executer-vue .description{cursor: pointer;}
.index-executer-vue .error-text{color: #f00;}
.index-executer-vue .el-table td, .table-info-vue .el-table th{padding: 5px 0;}
/* S-JSON展示的样式 */
.index-executer-vue pre.json {
display: block;
padding: 9.5px;
margin: 0 0 0 10px;
font-size: 12px;
line-height: 1.38461538;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: #f5f5f5;
border: 1px solid #ccc;
border-radius: 4px;
}
.index-executer-vue pre.json .option-img{
display: inline-block;cursor: pointer;
background: url('../../assets/img/collapsed.png') no-repeat center;
width: 28px; height: 11px; background-size: 28px 11px;
}
.index-executer-vue pre.json .img-expanded{
background: url('../../assets/img/expanded.png') no-repeat center;
}
.index-executer-vue pre.json .canvas{font:10pt georgia;background-color:#ececec;color:#000000;border:1px solid #cecece;}
.index-executer-vue pre.json .object-brace{color:#00aa00;font-weight:bold;}
.index-executer-vue pre.json .array-brace{color:#0033ff;font-weight:bold;}
.index-executer-vue pre.json .property-name{color:#cc0000;font-weight:bold;}
.index-executer-vue pre.json .string{color:#007777;}
.index-executer-vue pre.json .number{color:#aa00aa;}
.index-executer-vue pre.json .boolean{color:#0000ff;}
.index-executer-vue pre.json .function{color:#aa6633;text-decoration:italic;}
.index-executer-vue pre.json .null{color:#0000ff;}
.index-executer-vue pre.json .comma{color:#000000;font-weight:bold;}
.index-executer-vue pre.json .annotation{color:#aaa;}
.index-executer-vue pre img{cursor: pointer;}
/* E-JSON展示的样式 */
</style>