mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 21:57:56 +08:00
服务列表
This commit is contained in:
@@ -13,12 +13,12 @@ var lib = (function () {
|
|||||||
'../../assets/lib/jquery/3.2.1/jquery.min.js'
|
'../../assets/lib/jquery/3.2.1/jquery.min.js'
|
||||||
,'../../assets/lib/layui/layui.js'
|
,'../../assets/lib/layui/layui.js'
|
||||||
,'../../assets/lib/easyopen/sdk.js'
|
,'../../assets/lib/easyopen/sdk.js'
|
||||||
|
,'../../assets/lib/layuiext/Form.js'
|
||||||
,'../../assets/js/ApiUtil.js'
|
,'../../assets/js/ApiUtil.js'
|
||||||
,'../../assets/js/Form.js'
|
|
||||||
,'../../assets/js/profile.js'
|
|
||||||
]
|
]
|
||||||
|
|
||||||
var jsArr = [];
|
var jsArr = [];
|
||||||
|
var layuiConfig, layuiExtend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载js
|
* 加载js
|
||||||
@@ -26,7 +26,7 @@ var lib = (function () {
|
|||||||
* @param require layui依赖模块
|
* @param require layui依赖模块
|
||||||
* @param loadSuccess 加载成功后触发
|
* @param loadSuccess 加载成功后触发
|
||||||
*/
|
*/
|
||||||
function layuiInit(jsArr, require, loadSuccess) {
|
function loadJs(jsArr, loadSuccess) {
|
||||||
// 接着加载自定义的js
|
// 接着加载自定义的js
|
||||||
jsArr = addVersion(jsArr);
|
jsArr = addVersion(jsArr);
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ var lib = (function () {
|
|||||||
.script(jsArr) // 接着加载自定义的js
|
.script(jsArr) // 接着加载自定义的js
|
||||||
// 全部加载成后执行
|
// 全部加载成后执行
|
||||||
.wait(function () {
|
.wait(function () {
|
||||||
layui.use(require, loadSuccess);
|
loadSuccess && loadSuccess();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,16 +62,37 @@ var lib = (function () {
|
|||||||
* @returns {lib}
|
* @returns {lib}
|
||||||
*/
|
*/
|
||||||
importJs: function (jsPath) {
|
importJs: function (jsPath) {
|
||||||
jsArr = jsPath || [];
|
if (jsPath) {
|
||||||
|
if (typeof jsPath === 'string') {
|
||||||
|
jsPath = [jsPath];
|
||||||
|
}
|
||||||
|
jsArr = jsArr.concat(jsPath);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
, config: function (cfg) {
|
||||||
|
layuiConfig = cfg;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
, extend: function (ext) {
|
||||||
|
layuiExtend = ext;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* layui初始化,同layui.use()
|
* layui初始化,同layui.use()
|
||||||
* @param require
|
* @param require
|
||||||
* @param loadSuccess
|
* @param layuiInitFun
|
||||||
*/
|
*/
|
||||||
, use: function (require, loadSuccess) {
|
, use: function (require, layuiInitFun) {
|
||||||
layuiInit(jsArr, require, loadSuccess);
|
loadJs(jsArr, function () {
|
||||||
|
if (layuiConfig) {
|
||||||
|
layui.config(layuiConfig);
|
||||||
|
}
|
||||||
|
if (layuiExtend) {
|
||||||
|
layui.extend(layuiExtend);
|
||||||
|
}
|
||||||
|
layui.use(require, layuiInitFun);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@@ -0,0 +1,18 @@
|
|||||||
|
.treeTable-empty {
|
||||||
|
width: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeTable-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeTable-icon .layui-icon-triangle-d:before {
|
||||||
|
content: "\e623";
|
||||||
|
}
|
||||||
|
|
||||||
|
.treeTable-icon.open .layui-icon-triangle-d:before {
|
||||||
|
content: "\e625";
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
@@ -0,0 +1,206 @@
|
|||||||
|
layui.define(['layer', 'table'], function (exports) {
|
||||||
|
var $ = layui.jquery;
|
||||||
|
var layer = layui.layer;
|
||||||
|
var table = layui.table;
|
||||||
|
|
||||||
|
var treetable = {
|
||||||
|
// 渲染树形表格
|
||||||
|
render: function (param) {
|
||||||
|
// 检查参数
|
||||||
|
if (!treetable.checkParam(param)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 获取数据
|
||||||
|
if (param.data) {
|
||||||
|
treetable.init(param, param.data);
|
||||||
|
} else {
|
||||||
|
$.getJSON(param.url, param.where, function (res) {
|
||||||
|
treetable.init(param, res.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 渲染表格
|
||||||
|
init: function (param, data) {
|
||||||
|
var mData = [];
|
||||||
|
var doneCallback = param.done;
|
||||||
|
var tNodes = data;
|
||||||
|
// 补上id和pid字段
|
||||||
|
for (var i = 0; i < tNodes.length; i++) {
|
||||||
|
var tt = tNodes[i];
|
||||||
|
if (!tt.id) {
|
||||||
|
if (!param.treeIdName) {
|
||||||
|
layer.msg('参数treeIdName不能为空', {icon: 5});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tt.id = tt[param.treeIdName];
|
||||||
|
}
|
||||||
|
if (!tt.pid) {
|
||||||
|
if (!param.treePidName) {
|
||||||
|
layer.msg('参数treePidName不能为空', {icon: 5});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tt.pid = tt[param.treePidName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对数据进行排序
|
||||||
|
var sort = function (s_pid, data) {
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (data[i].pid == s_pid) {
|
||||||
|
var len = mData.length;
|
||||||
|
if (len > 0 && mData[len - 1].id == s_pid) {
|
||||||
|
mData[len - 1].isParent = true;
|
||||||
|
}
|
||||||
|
mData.push(data[i]);
|
||||||
|
sort(data[i].id, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sort(param.treeSpid, tNodes);
|
||||||
|
|
||||||
|
// 重写参数
|
||||||
|
param.url = undefined;
|
||||||
|
param.data = mData;
|
||||||
|
param.page = {
|
||||||
|
count: param.data.length,
|
||||||
|
limit: param.data.length
|
||||||
|
};
|
||||||
|
param.cols[0][param.treeColIndex].templet = function (d) {
|
||||||
|
var mId = d.id;
|
||||||
|
var mPid = d.pid;
|
||||||
|
var isDir = d.isParent;
|
||||||
|
var emptyNum = treetable.getEmptyNum(mPid, mData);
|
||||||
|
var iconHtml = '';
|
||||||
|
for (var i = 0; i < emptyNum; i++) {
|
||||||
|
iconHtml += '<span class="treeTable-empty"></span>';
|
||||||
|
}
|
||||||
|
if (isDir) {
|
||||||
|
iconHtml += '<i class="layui-icon layui-icon-triangle-d"></i> <i class="layui-icon layui-icon-layer"></i>';
|
||||||
|
} else {
|
||||||
|
iconHtml += '<i class="layui-icon layui-icon-file"></i>';
|
||||||
|
}
|
||||||
|
iconHtml += ' ';
|
||||||
|
var ttype = isDir ? 'dir' : 'file';
|
||||||
|
var vg = '<span class="treeTable-icon open" lay-tid="' + mId + '" lay-tpid="' + mPid + '" lay-ttype="' + ttype + '">';
|
||||||
|
return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '</span>'
|
||||||
|
};
|
||||||
|
|
||||||
|
param.done = function (res, curr, count) {
|
||||||
|
$(param.elem).next().addClass('treeTable');
|
||||||
|
$('.treeTable .layui-table-page').css('display', 'none');
|
||||||
|
$(param.elem).next().attr('treeLinkage', param.treeLinkage);
|
||||||
|
// 绑定事件换成对body绑定
|
||||||
|
/*$('.treeTable .treeTable-icon').click(function () {
|
||||||
|
treetable.toggleRows($(this), param.treeLinkage);
|
||||||
|
});*/
|
||||||
|
if (param.treeDefaultClose) {
|
||||||
|
treetable.foldAll(param.elem);
|
||||||
|
}
|
||||||
|
if (doneCallback) {
|
||||||
|
doneCallback(res, curr, count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 渲染表格
|
||||||
|
table.render(param);
|
||||||
|
},
|
||||||
|
// 计算缩进的数量
|
||||||
|
getEmptyNum: function (pid, data) {
|
||||||
|
var num = 0;
|
||||||
|
if (!pid) {
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
var tPid;
|
||||||
|
for (var i = 0; i < data.length; i++) {
|
||||||
|
if (pid == data[i].id) {
|
||||||
|
num += 1;
|
||||||
|
tPid = data[i].pid;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num + treetable.getEmptyNum(tPid, data);
|
||||||
|
},
|
||||||
|
// 展开/折叠行
|
||||||
|
toggleRows: function ($dom, linkage) {
|
||||||
|
var type = $dom.attr('lay-ttype');
|
||||||
|
if ('file' == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var mId = $dom.attr('lay-tid');
|
||||||
|
var isOpen = $dom.hasClass('open');
|
||||||
|
if (isOpen) {
|
||||||
|
$dom.removeClass('open');
|
||||||
|
} else {
|
||||||
|
$dom.addClass('open');
|
||||||
|
}
|
||||||
|
$dom.closest('tbody').find('tr').each(function () {
|
||||||
|
var $ti = $(this).find('.treeTable-icon');
|
||||||
|
var pid = $ti.attr('lay-tpid');
|
||||||
|
var ttype = $ti.attr('lay-ttype');
|
||||||
|
var tOpen = $ti.hasClass('open');
|
||||||
|
if (mId == pid) {
|
||||||
|
if (isOpen) {
|
||||||
|
$(this).hide();
|
||||||
|
if ('dir' == ttype && tOpen == isOpen) {
|
||||||
|
$ti.trigger('click');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(this).show();
|
||||||
|
if (linkage && 'dir' == ttype && tOpen == isOpen) {
|
||||||
|
$ti.trigger('click');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 检查参数
|
||||||
|
checkParam: function (param) {
|
||||||
|
if (!param.treeSpid && param.treeSpid != 0) {
|
||||||
|
layer.msg('参数treeSpid不能为空', {icon: 5});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!param.treeColIndex && param.treeColIndex != 0) {
|
||||||
|
layer.msg('参数treeColIndex不能为空', {icon: 5});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
// 展开所有
|
||||||
|
expandAll: function (dom) {
|
||||||
|
$(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () {
|
||||||
|
var $ti = $(this).find('.treeTable-icon');
|
||||||
|
var ttype = $ti.attr('lay-ttype');
|
||||||
|
var tOpen = $ti.hasClass('open');
|
||||||
|
if ('dir' == ttype && !tOpen) {
|
||||||
|
$ti.trigger('click');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 折叠所有
|
||||||
|
foldAll: function (dom) {
|
||||||
|
$(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () {
|
||||||
|
var $ti = $(this).find('.treeTable-icon');
|
||||||
|
var ttype = $ti.attr('lay-ttype');
|
||||||
|
var tOpen = $ti.hasClass('open');
|
||||||
|
if ('dir' == ttype && tOpen) {
|
||||||
|
$ti.trigger('click');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
layui.link(layui.cache.base + 'treetable-lay/treetable.css');
|
||||||
|
|
||||||
|
// 给图标列绑定事件
|
||||||
|
$('body').on('click', '.treeTable .treeTable-icon', function () {
|
||||||
|
var treeLinkage = $(this).parents('.treeTable').attr('treeLinkage');
|
||||||
|
if ('true' == treeLinkage) {
|
||||||
|
treetable.toggleRows($(this), true);
|
||||||
|
} else {
|
||||||
|
treetable.toggleRows($(this), false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
exports('treetable', treetable);
|
||||||
|
});
|
@@ -1,4 +1,4 @@
|
|||||||
lib.use(['element', 'table', 'tree', 'form'], function () {
|
lib.importJs('../../assets/js/profile.js').use(['element', 'table', 'tree', 'form'], function () {
|
||||||
var ROUTE_STATUS = {
|
var ROUTE_STATUS = {
|
||||||
'0': '待审核'
|
'0': '待审核'
|
||||||
,'1': '<span class="x-green">已启用</span>'
|
,'1': '<span class="x-green">已启用</span>'
|
||||||
|
@@ -32,43 +32,17 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="layui-hide" id="table"></table>
|
<table class="layui-hide" id="treeTable"></table>
|
||||||
<script type="text/html" id="optBar">
|
<script type="text/html" id="optCol">
|
||||||
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="edit">修改</a>
|
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="edit">修改</a>
|
||||||
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">下线</a>
|
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">下线</a>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="../../assets/js/lib.js"></script>
|
<script type="text/javascript" src="../../assets/js/lib.js"></script>
|
||||||
|
<script type="text/javascript" src="serviceList.js"></script>
|
||||||
<script>
|
<script>
|
||||||
lib.use(['element', 'table', 'form'], function () {
|
|
||||||
var table = layui.table;
|
|
||||||
var form = layui.form;
|
|
||||||
|
|
||||||
var serverTable = table.render({
|
|
||||||
elem: '#table'
|
|
||||||
, url: ApiUtil.createUrl('service.list')
|
|
||||||
, cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增
|
|
||||||
, cols: [[
|
|
||||||
{field: 'serviceId', title: '服务名称', sort: true}
|
|
||||||
, {field: 'description', title: '描述'}
|
|
||||||
, {field: 'createTime', title: '添加时间', sort: true}
|
|
||||||
, {field: 'updateTime', title: '修改时间', sort: true}
|
|
||||||
, {fixed: 'right', title:'操作', toolbar: '#optBar', width:150}
|
|
||||||
]]
|
|
||||||
});
|
|
||||||
|
|
||||||
form.on('submit(searchFilter)', function(data){
|
|
||||||
var param = data.field;
|
|
||||||
serverTable.reload({
|
|
||||||
where: {
|
|
||||||
data: JSON.stringify(param)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@@ -0,0 +1,53 @@
|
|||||||
|
lib.config({
|
||||||
|
base: '../../assets/lib/layuiext/module/'
|
||||||
|
}).extend({
|
||||||
|
treetable: 'treetable-lay/treetable'
|
||||||
|
}).use(['element', 'table', 'form', 'treetable'], function () {
|
||||||
|
var layer = layui.layer;
|
||||||
|
var form = layui.form;
|
||||||
|
var treetable = layui.treetable;
|
||||||
|
var serverTable;
|
||||||
|
|
||||||
|
// 渲染表格
|
||||||
|
var renderTable = function () {
|
||||||
|
layer.load(2);
|
||||||
|
serverTable = treetable.render({
|
||||||
|
treeColIndex: 1,
|
||||||
|
treeSpid: 0,
|
||||||
|
treeIdName: 'id',
|
||||||
|
treePidName: 'parentId',
|
||||||
|
treeDefaultClose: true,
|
||||||
|
treeLinkage: false,
|
||||||
|
elem: '#treeTable',
|
||||||
|
url: ApiUtil.createUrl('service.instance.list'),
|
||||||
|
page: false,
|
||||||
|
cols: [[
|
||||||
|
{type: 'numbers'},
|
||||||
|
{field: 'name', title: '服务名称', width: 200},
|
||||||
|
{field: 'instanceId', title: 'instanceId', width: 220},
|
||||||
|
{field: 'ipAddr', title: 'IP地址', width: 150},
|
||||||
|
{field: 'serverPort', title: '端口号', width: 100},
|
||||||
|
{field: 'status', title: 'status', width: 100},
|
||||||
|
{field: 'updateTime', title: '最后更新时间', width: 150},
|
||||||
|
{fixed: 'right', templet: '#optCol', title: '操作', width: 200}
|
||||||
|
]],
|
||||||
|
done: function () {
|
||||||
|
layer.closeAll('loading');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderTable();
|
||||||
|
|
||||||
|
|
||||||
|
form.on('submit(searchFilter)', function(data){
|
||||||
|
var param = data.field;
|
||||||
|
serverTable.reload({
|
||||||
|
where: {
|
||||||
|
data: JSON.stringify(param)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -23,6 +23,7 @@
|
|||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<zookeeper.version>3.4.12</zookeeper.version>
|
<zookeeper.version>3.4.12</zookeeper.version>
|
||||||
<curator-recipes.version>4.0.1</curator-recipes.version>
|
<curator-recipes.version>4.0.1</curator-recipes.version>
|
||||||
|
<okhttp.version>3.11.0</okhttp.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -65,6 +66,12 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>${okhttp.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
@@ -5,16 +5,30 @@ import com.gitee.easyopen.annotation.Api;
|
|||||||
import com.gitee.easyopen.annotation.ApiService;
|
import com.gitee.easyopen.annotation.ApiService;
|
||||||
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
import com.gitee.easyopen.doc.annotation.ApiDoc;
|
||||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
import com.gitee.easyopen.doc.annotation.ApiDocMethod;
|
||||||
|
import com.gitee.easyopen.exception.ApiException;
|
||||||
import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam;
|
import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam;
|
||||||
import com.gitee.sop.adminserver.api.service.result.ServiceInfo;
|
import com.gitee.sop.adminserver.api.service.result.ServiceInfo;
|
||||||
|
import com.gitee.sop.adminserver.api.service.result.ServiceInfoVo;
|
||||||
|
import com.gitee.sop.adminserver.bean.EurekaApplication;
|
||||||
|
import com.gitee.sop.adminserver.bean.EurekaApps;
|
||||||
|
import com.gitee.sop.adminserver.bean.EurekaInstance;
|
||||||
|
import com.gitee.sop.adminserver.bean.EurekaUri;
|
||||||
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
import com.gitee.sop.adminserver.bean.ZookeeperContext;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.curator.framework.recipes.cache.ChildData;
|
import org.apache.curator.framework.recipes.cache.ChildData;
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,12 +40,22 @@ import java.util.stream.Collectors;
|
|||||||
public class ServiceApi {
|
public class ServiceApi {
|
||||||
|
|
||||||
|
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private Environment environment;
|
private Environment environment;
|
||||||
|
|
||||||
|
private String eurekaUrl;
|
||||||
|
|
||||||
|
// eureka.client.serviceUrl.defaultZone
|
||||||
|
|
||||||
@Api(name = "service.list")
|
@Api(name = "service.list")
|
||||||
@ApiDocMethod(description = "服务列表", elementClass = ServiceInfo.class)
|
@ApiDocMethod(description = "服务列表", elementClass = ServiceInfo.class)
|
||||||
List<ServiceInfo> listServiceInfo(ServiceSearchParam param) throws Exception {
|
List<ServiceInfo> listServiceInfo(ServiceSearchParam param) throws Exception {
|
||||||
|
String json = this.requestEurekaServer(EurekaUri.QUERY_APPS);
|
||||||
|
EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class);
|
||||||
|
|
||||||
|
|
||||||
String routeRootPath = ZookeeperContext.getSopRouteRootPath(param.getProfile());
|
String routeRootPath = ZookeeperContext.getSopRouteRootPath(param.getProfile());
|
||||||
List<ChildData> childDataList = ZookeeperContext.getChildrenData(routeRootPath);
|
List<ChildData> childDataList = ZookeeperContext.getChildrenData(routeRootPath);
|
||||||
List<ServiceInfo> serviceInfoList = childDataList.stream()
|
List<ServiceInfo> serviceInfoList = childDataList.stream()
|
||||||
@@ -53,4 +77,70 @@ public class ServiceApi {
|
|||||||
return serviceInfoList;
|
return serviceInfoList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Api(name = "service.instance.list")
|
||||||
|
@ApiDocMethod(description = "服务列表", elementClass = ServiceInfo.class)
|
||||||
|
List<ServiceInfoVo> listService(ServiceSearchParam param) throws Exception {
|
||||||
|
String json = this.requestEurekaServer(EurekaUri.QUERY_APPS);
|
||||||
|
EurekaApps eurekaApps = JSON.parseObject(json, EurekaApps.class);
|
||||||
|
|
||||||
|
List<ServiceInfoVo> serviceInfoVoList = new ArrayList<>();
|
||||||
|
List<EurekaApplication> applicationList = eurekaApps.getApplications().getApplication();
|
||||||
|
AtomicInteger idGen = new AtomicInteger(1);
|
||||||
|
applicationList.stream()
|
||||||
|
.forEach(eurekaApplication -> {
|
||||||
|
int pid = idGen.getAndIncrement();
|
||||||
|
String name = eurekaApplication.getName();
|
||||||
|
ServiceInfoVo parent = new ServiceInfoVo();
|
||||||
|
parent.setId(pid);
|
||||||
|
parent.setName(name);
|
||||||
|
parent.setParentId(0);
|
||||||
|
serviceInfoVoList.add(parent);
|
||||||
|
List<EurekaInstance> instanceList = eurekaApplication.getInstance();
|
||||||
|
for (EurekaInstance instance : instanceList) {
|
||||||
|
ServiceInfoVo vo = new ServiceInfoVo();
|
||||||
|
BeanUtils.copyProperties(instance, vo);
|
||||||
|
int id = idGen.getAndIncrement();
|
||||||
|
vo.setId(id);
|
||||||
|
vo.setName(name);
|
||||||
|
vo.setParentId(pid);
|
||||||
|
vo.setServerPort(instance.fetchPort());
|
||||||
|
serviceInfoVoList.add(vo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return serviceInfoVoList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String requestEurekaServer(EurekaUri uri) throws IOException {
|
||||||
|
Request request = this.buildRequest(EurekaUri.QUERY_APPS);
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
return response.body().string();
|
||||||
|
} else {
|
||||||
|
return "{}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Request buildRequest(EurekaUri uri) {
|
||||||
|
String apiUrl = this.eurekaUrl + uri.getUri();
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(apiUrl)
|
||||||
|
.addHeader("Content-Type", "application/json")
|
||||||
|
.addHeader("Accept", "application/json")
|
||||||
|
.build();
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
protected void after() {
|
||||||
|
String eurekaUrls = environment.getProperty("eureka.client.serviceUrl.defaultZone");
|
||||||
|
if (StringUtils.isBlank(eurekaUrls)) {
|
||||||
|
throw new ApiException("未指定eureka.client.serviceUrl.defaultZone参数");
|
||||||
|
}
|
||||||
|
String url = eurekaUrls.split("\\,")[0];
|
||||||
|
if (url.endsWith("/")) {
|
||||||
|
url = eurekaUrls.substring(0, eurekaUrls.length() - 1);
|
||||||
|
}
|
||||||
|
this.eurekaUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,52 @@
|
|||||||
|
package com.gitee.sop.adminserver.api.service.result;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocField;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ServiceInfoVo {
|
||||||
|
@ApiDocField(description = "id")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ApiDocField(description = "服务名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiDocField(description = "instanceId")
|
||||||
|
private String instanceId;
|
||||||
|
|
||||||
|
@ApiDocField(description = "ip")
|
||||||
|
private String ipAddr;
|
||||||
|
|
||||||
|
@ApiDocField(description = "端口")
|
||||||
|
private String serverPort;
|
||||||
|
|
||||||
|
@ApiDocField(description = "status")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@ApiDocField(description = "statusPageUrl")
|
||||||
|
private String statusPageUrl;
|
||||||
|
|
||||||
|
@ApiDocField(description = "healthCheckUrl")
|
||||||
|
private String healthCheckUrl;
|
||||||
|
|
||||||
|
@ApiDocField(description = "最后更新时间")
|
||||||
|
private String lastUpdatedTimestamp;
|
||||||
|
|
||||||
|
@ApiDocField(description = "parentId")
|
||||||
|
private Integer parentId;
|
||||||
|
|
||||||
|
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||||
|
public Date getUpdateTime() {
|
||||||
|
if (StringUtils.isBlank(lastUpdatedTimestamp)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new Date(Long.valueOf(lastUpdatedTimestamp));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,14 @@
|
|||||||
|
package com.gitee.sop.adminserver.bean;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class EurekaApplication {
|
||||||
|
private String name;
|
||||||
|
private List<EurekaInstance> instance;
|
||||||
|
}
|
@@ -0,0 +1,13 @@
|
|||||||
|
package com.gitee.sop.adminserver.bean;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class EurekaApplications {
|
||||||
|
private List<EurekaApplication> application;
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
package com.gitee.sop.adminserver.bean;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class EurekaApps {
|
||||||
|
private EurekaApplications applications;
|
||||||
|
}
|
@@ -0,0 +1,29 @@
|
|||||||
|
package com.gitee.sop.adminserver.bean;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class EurekaInstance {
|
||||||
|
private String instanceId;
|
||||||
|
private String ipAddr;
|
||||||
|
private Map<String, Object> port;
|
||||||
|
|
||||||
|
private String status;
|
||||||
|
private String statusPageUrl;
|
||||||
|
private String healthCheckUrl;
|
||||||
|
private String lastUpdatedTimestamp;
|
||||||
|
|
||||||
|
public String fetchPort() {
|
||||||
|
if (CollectionUtils.isEmpty(port)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return String.valueOf(port.getOrDefault("$", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
package com.gitee.sop.adminserver.bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https://github.com/Netflix/eureka/wiki/Eureka-REST-operations
|
||||||
|
* @author tanghc
|
||||||
|
*/
|
||||||
|
public enum EurekaUri {
|
||||||
|
|
||||||
|
/** Query for all instances */
|
||||||
|
QUERY_APPS("/apps"),
|
||||||
|
;
|
||||||
|
String uri;
|
||||||
|
|
||||||
|
EurekaUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}}
|
@@ -19,6 +19,7 @@ public class WebConfig extends WebMvcConfigurationSupport {
|
|||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||||
//配置映射关系
|
//配置映射关系
|
||||||
registry.addResourceHandler("/conf/**").addResourceLocations("classpath:/META-INF/resources/webjars/sop-admin-front/1.0.0-SNAPSHOT/");
|
registry.addResourceHandler("/conf/**").addResourceLocations("classpath:/META-INF/resources/webjars/sop-admin-front/1.0.0-SNAPSHOT/");
|
||||||
|
registry.addResourceHandler("/opendoc/**").addResourceLocations("classpath:/META-INF/resources/opendoc/");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
|
@@ -22,6 +22,13 @@ easyopen:
|
|||||||
sop-admin:
|
sop-admin:
|
||||||
profiles: default,prod,dev,test
|
profiles: default,prod,dev,test
|
||||||
|
|
||||||
|
# 注册中心地址,这里只是参数,并不会去注册
|
||||||
|
eureka:
|
||||||
|
port: 1111
|
||||||
|
host: localhost
|
||||||
|
client:
|
||||||
|
serviceUrl:
|
||||||
|
defaultZone: http://${eureka.host}:${eureka.port}/eureka/
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
|
Reference in New Issue
Block a user