parent
a5b2d9c51b
commit
5d436081a5
@ -0,0 +1,24 @@ |
|||||||
|
var Common = (function () { |
||||||
|
|
||||||
|
function initProfiles() { |
||||||
|
var $profileList = $('#profileList'); |
||||||
|
if ($profileList.length > 0) { |
||||||
|
ApiUtil.post('system.profile.list', {}, function (resp) { |
||||||
|
var list = resp.data; |
||||||
|
var html = []; |
||||||
|
for (var i = 0; i < list.length; i++) { |
||||||
|
html.push('<li' + (i == 0 ? ' class="layui-this"' : '') + '>' + list[i] + '</li>'); |
||||||
|
} |
||||||
|
$profileList.html(html.join('')) |
||||||
|
|
||||||
|
$profileList.find('li').on('click', function () { |
||||||
|
window.profile = $(this).text(); |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
initProfiles(); |
||||||
|
|
||||||
|
return {} |
||||||
|
})(); |
@ -0,0 +1,32 @@ |
|||||||
|
layui.use('jquery', function () { |
||||||
|
var $ = layui.jquery; |
||||||
|
var $pageFrame = $('#pageFrame'); |
||||||
|
var $selectLi = null; |
||||||
|
$('.left-nav').on('click', 'li', function (event) { |
||||||
|
var $tagLi = $(this); |
||||||
|
var $tagA = $tagLi.find('a').eq(0); |
||||||
|
var href = $tagA.prop('href'); |
||||||
|
if (href) { |
||||||
|
$pageFrame.prop('src', href + '?q=' + new Date().getTime()); |
||||||
|
if ($selectLi) { |
||||||
|
$selectLi.removeClass('active') |
||||||
|
} |
||||||
|
$selectLi = $tagLi.addClass('active'); |
||||||
|
} |
||||||
|
return false; |
||||||
|
}); |
||||||
|
|
||||||
|
$('.container .left_open i').click(function(event) { |
||||||
|
if($('.left-nav').css('left')=='0px'){ |
||||||
|
$('.left-nav').animate({left: '-221px'}, 100); |
||||||
|
$('.page-content').animate({left: '0px'}, 100); |
||||||
|
$('.page-content-bg').hide(); |
||||||
|
}else{ |
||||||
|
$('.left-nav').animate({left: '0px'}, 100); |
||||||
|
$('.page-content').animate({left: '221px'}, 100); |
||||||
|
if($(window).width()<768){ |
||||||
|
$('.page-content-bg').show(); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,55 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html class="x-admin-sm"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>SOP Admin</title> |
||||||
|
<meta name="renderer" content="webkit"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
||||||
|
<meta name="viewport" |
||||||
|
content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8"/> |
||||||
|
<link rel="stylesheet" href="../../assets/css/font.css"> |
||||||
|
<link rel="stylesheet" href="../../assets/css/xadmin.css"> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="x-nav"> |
||||||
|
<span class="layui-breadcrumb"> |
||||||
|
<a href="../welcome.html">首页</a> |
||||||
|
<a><cite>服务管理</cite></a> |
||||||
|
<a><cite>路由管理</cite></a> |
||||||
|
</span> |
||||||
|
<a class="layui-btn layui-btn-small layui-btn-normal" style="line-height:1.6em;margin-top:4px;float:right" |
||||||
|
href="javascript:location.replace(location.href);" title="刷新"> |
||||||
|
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a> |
||||||
|
</div> |
||||||
|
<div class="x-body"> |
||||||
|
<div class="layui-tab" style="margin-top: 0px;" lay-filter="docDemoTabBrief"> |
||||||
|
<ul id="profileList" class="layui-tab-title"> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="layui-col-md2"> |
||||||
|
<ul id="leftTree"></ul> |
||||||
|
</div> |
||||||
|
<div class="layui-col-md10"> |
||||||
|
<div class="layui-row"> |
||||||
|
<form class="layui-form layui-col-md12 x-so" action="" lay-filter="searchFrm"> |
||||||
|
路由名称: |
||||||
|
<input name="id" class="layui-input" style="width: 200px;" placeholder="输入接口名或版本号"> |
||||||
|
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="searchFilter"> |
||||||
|
<i class="layui-icon layui-icon-search"></i>搜索 |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
|
||||||
|
<div class="layui-btn-group demoTable"> |
||||||
|
<button class="layui-btn layui-btn-ms layui-btn-normal" lay-event="addRoute">添加路由</button> |
||||||
|
</div> |
||||||
|
<table class="layui-hide" id="table"></table> |
||||||
|
<script type="text/html" id="optBar"> |
||||||
|
<a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="edit">修改</a> |
||||||
|
</script> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<script type="text/javascript" src="../../assets/js/lib.js"></script> |
||||||
|
<script type="text/javascript" src="routeManager.js"></script> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,95 @@ |
|||||||
|
lib.use(['element', 'table', 'tree', 'form'], function () { |
||||||
|
var form = layui.form; |
||||||
|
var table = layui.table; |
||||||
|
var currentServiceId; |
||||||
|
|
||||||
|
var serverTable = table.render({ |
||||||
|
elem: '#table' |
||||||
|
, url: ApiUtil.createUrl('route.list') |
||||||
|
, cellMinWidth: 80 //全局定义常规单元格的最小宽度,layui 2.2.1 新增
|
||||||
|
, cols: [[ |
||||||
|
{field: 'id', title: 'id(接口名+版本号)'} |
||||||
|
, {field: 'uri', title: 'uri'} |
||||||
|
, { |
||||||
|
field: 'ignoreValidate', width: 80, title: '忽略验证', templet: function (row) { |
||||||
|
return row.ignoreValidate |
||||||
|
? '<span class="x-red">是</span>' |
||||||
|
: '<span>否</span>'; |
||||||
|
} |
||||||
|
} |
||||||
|
, { |
||||||
|
field: 'disabled', title: '状态', width: 80, templet: function (row) { |
||||||
|
return row.disabled |
||||||
|
? '<span class="x-red">禁用</span>' |
||||||
|
: '<span class="x-green">启用</span>'; |
||||||
|
} |
||||||
|
} |
||||||
|
, {fixed: 'right', title: '操作', toolbar: '#optBar', width: 100} |
||||||
|
]] |
||||||
|
}); |
||||||
|
|
||||||
|
$('#profileList').find('li').on('click', function () { |
||||||
|
initTree($(this).text()); |
||||||
|
}) |
||||||
|
|
||||||
|
function initTree(profile) { |
||||||
|
ApiUtil.post('service.list', {profile: profile}, function (resp) { |
||||||
|
var serviceList = resp.data; |
||||||
|
var children = []; |
||||||
|
for (var i = 0; i < serviceList.length; i++) { |
||||||
|
var serviceInfo = serviceList[i]; |
||||||
|
children.push({ |
||||||
|
id: i + 1, |
||||||
|
name: serviceInfo.serviceId |
||||||
|
}) |
||||||
|
} |
||||||
|
// 清空表格
|
||||||
|
reloadRightPart({name: ''}) |
||||||
|
// 清空树
|
||||||
|
$('#leftTree').text(''); |
||||||
|
layui.tree({ |
||||||
|
elem: '#leftTree' //传入元素选择器
|
||||||
|
, nodes: [{ //节点
|
||||||
|
name: '服务列表(' + profile + ')' |
||||||
|
, spread: true // 展开
|
||||||
|
, children: children |
||||||
|
}] |
||||||
|
, click: function (node) { |
||||||
|
if (node.id) { |
||||||
|
reloadRightPart(node) |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新右边部分 |
||||||
|
* @param node 树节点 |
||||||
|
*/ |
||||||
|
function reloadRightPart(node) { |
||||||
|
var serviceId = node.name; |
||||||
|
currentServiceId = serviceId; |
||||||
|
searchTable({ |
||||||
|
serviceId: serviceId |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
form.on('submit(searchFilter)', function (data) { |
||||||
|
var param = data.field; |
||||||
|
param.serviceId = currentServiceId; |
||||||
|
searchTable(param) |
||||||
|
return false; |
||||||
|
}); |
||||||
|
|
||||||
|
function searchTable(param) { |
||||||
|
serverTable.reload({ |
||||||
|
where: { |
||||||
|
data: JSON.stringify(param) |
||||||
|
, profile: window.profile |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
initTree('default'); |
||||||
|
}); |
@ -0,0 +1,78 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html class="x-admin-sm"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>SOP Admin</title> |
||||||
|
<meta name="renderer" content="webkit"> |
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
||||||
|
<meta name="viewport" |
||||||
|
content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8"/> |
||||||
|
<link rel="stylesheet" href="../../assets/css/font.css"> |
||||||
|
<link rel="stylesheet" href="../../assets/css/xadmin.css"> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
<div class="x-nav"> |
||||||
|
<span class="layui-breadcrumb"> |
||||||
|
<a href="../welcome.html">首页</a> |
||||||
|
<a><cite>服务管理</cite></a> |
||||||
|
<a><cite>服务列表</cite></a> |
||||||
|
</span> |
||||||
|
<a class="layui-btn layui-btn-small layui-btn-normal" style="line-height:1.6em;margin-top:4px;float:right" |
||||||
|
href="javascript:location.replace(location.href);" title="刷新"> |
||||||
|
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a> |
||||||
|
</div> |
||||||
|
<div class="x-body"> |
||||||
|
<div class="layui-tab" style="margin-top: 0px;" lay-filter="docDemoTabBrief"> |
||||||
|
<ul id="profileList" class="layui-tab-title"> |
||||||
|
</ul> |
||||||
|
</div> |
||||||
|
<div class="layui-row"> |
||||||
|
<form class="layui-form layui-col-md12 x-so" action="" lay-filter="searchFrm"> |
||||||
|
服务名称: |
||||||
|
<input name="serviceId" class="layui-input" style="width: 200px;" placeholder="输入服务名称(serviceId)"> |
||||||
|
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="searchFilter"> |
||||||
|
<i class="layui-icon layui-icon-search"></i>搜索 |
||||||
|
</button> |
||||||
|
</form> |
||||||
|
</div> |
||||||
|
|
||||||
|
<table class="layui-hide" id="table"></table> |
||||||
|
<script type="text/html" id="optBar"> |
||||||
|
<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> |
||||||
|
</script> |
||||||
|
|
||||||
|
</div> |
||||||
|
<script type="text/javascript" src="../../assets/js/lib.js"></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> |
||||||
|
</body> |
||||||
|
</html> |
@ -0,0 +1,10 @@ |
|||||||
|
<!DOCTYPE html> |
||||||
|
<html lang="en"> |
||||||
|
<head> |
||||||
|
<meta charset="UTF-8"> |
||||||
|
<title>todo</title> |
||||||
|
</head> |
||||||
|
<body> |
||||||
|
待实现... |
||||||
|
</body> |
||||||
|
</html> |
@ -1,165 +1,35 @@ |
|||||||
<!DOCTYPE html> |
<!DOCTYPE html> |
||||||
<html class="x-admin-sm"> |
<html class="x-admin-sm"> |
||||||
<head> |
<head> |
||||||
<meta charset="UTF-8"> |
<meta charset="UTF-8"> |
||||||
<title>欢迎页面-X-admin2.1</title> |
<title>SOP Admin</title> |
||||||
<meta name="renderer" content="webkit"> |
<meta name="renderer" content="webkit"> |
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
||||||
<meta name="viewport" content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8,target-densitydpi=low-dpi" /> |
<meta name="viewport" |
||||||
<link rel="stylesheet" href="../assets/css/font.css"> |
content="width=device-width,user-scalable=yes, minimum-scale=0.4, initial-scale=0.8"/> |
||||||
<link rel="stylesheet" href="../assets/css/xadmin.css"> |
<link rel="stylesheet" href="../assets/css/font.css"> |
||||||
</head> |
<link rel="stylesheet" href="../assets/css/xadmin.css"> |
||||||
<body> |
|
||||||
<div class="x-body"> |
</head> |
||||||
<blockquote class="layui-elem-quote">欢迎管理员: |
<body> |
||||||
<span class="x-red">test</span>!当前时间:2018-04-25 20:50:53</blockquote> |
<div class="x-nav"> |
||||||
<fieldset class="layui-elem-field"> |
<span class="layui-breadcrumb"> |
||||||
<legend>数据统计</legend> |
<a><cite>首页</cite></a> |
||||||
<div class="layui-field-box"> |
</span> |
||||||
<div class="layui-col-md12"> |
<a class="layui-btn layui-btn-small layui-btn-normal" style="line-height:1.6em;margin-top:4px;float:right" |
||||||
<div class="layui-card"> |
href="javascript:location.replace(location.href);" title="刷新"> |
||||||
<div class="layui-card-body"> |
<i class="layui-icon layui-icon-refresh" style="line-height:30px"></i></a> |
||||||
<div class="layui-carousel x-admin-carousel x-admin-backlog" lay-anim="" lay-indicator="inside" lay-arrow="none" style="width: 100%; height: 90px;"> |
</div> |
||||||
<div carousel-item=""> |
<div class="x-body"> |
||||||
<ul class="layui-row layui-col-space10 layui-this"> |
<blockquote class="layui-elem-quote">欢迎管理员: |
||||||
<li class="layui-col-xs2"> |
<span class="x-red">admin</span>! |
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
</blockquote> |
||||||
<h3>文章数</h3> |
</div> |
||||||
<p> |
|
||||||
<cite>66</cite></p> |
<script type="text/javascript" src="../assets/lib/layui/layui.js" charset="utf-8"></script> |
||||||
</a> |
<script> |
||||||
</li> |
layui.use('element', function () { |
||||||
<li class="layui-col-xs2"> |
}); |
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
</script> |
||||||
<h3>会员数</h3> |
</body> |
||||||
<p> |
|
||||||
<cite>12</cite></p> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li class="layui-col-xs2"> |
|
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
|
||||||
<h3>回复数</h3> |
|
||||||
<p> |
|
||||||
<cite>99</cite></p> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li class="layui-col-xs2"> |
|
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
|
||||||
<h3>商品数</h3> |
|
||||||
<p> |
|
||||||
<cite>67</cite></p> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li class="layui-col-xs2"> |
|
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
|
||||||
<h3>文章数</h3> |
|
||||||
<p> |
|
||||||
<cite>67</cite></p> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
<li class="layui-col-xs2"> |
|
||||||
<a href="javascript:;" class="x-admin-backlog-body"> |
|
||||||
<h3>文章数</h3> |
|
||||||
<p> |
|
||||||
<cite>6766</cite></p> |
|
||||||
</a> |
|
||||||
</li> |
|
||||||
</ul> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
</fieldset> |
|
||||||
<fieldset class="layui-elem-field"> |
|
||||||
<legend>系统通知</legend> |
|
||||||
<div class="layui-field-box"> |
|
||||||
<table class="layui-table" lay-skin="line"> |
|
||||||
<tbody> |
|
||||||
<tr> |
|
||||||
<td > |
|
||||||
<a class="x-a" href="/" target="_blank">新版x-admin 2.0上线了</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<td > |
|
||||||
<a class="x-a" href="/" target="_blank">交流qq群:(519492808)</a> |
|
||||||
</td> |
|
||||||
</tr> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
</fieldset> |
|
||||||
<fieldset class="layui-elem-field"> |
|
||||||
<legend>系统信息</legend> |
|
||||||
<div class="layui-field-box"> |
|
||||||
<table class="layui-table"> |
|
||||||
<tbody> |
|
||||||
<tr> |
|
||||||
<th>xxx版本</th> |
|
||||||
<td>1.0.180420</td></tr> |
|
||||||
<tr> |
|
||||||
<th>服务器地址</th> |
|
||||||
<td>x.xuebingsi.com</td></tr> |
|
||||||
<tr> |
|
||||||
<th>操作系统</th> |
|
||||||
<td>WINNT</td></tr> |
|
||||||
<tr> |
|
||||||
<th>运行环境</th> |
|
||||||
<td>Apache/2.4.23 (Win32) OpenSSL/1.0.2j mod_fcgid/2.3.9</td></tr> |
|
||||||
<tr> |
|
||||||
<th>PHP版本</th> |
|
||||||
<td>5.6.27</td></tr> |
|
||||||
<tr> |
|
||||||
<th>PHP运行方式</th> |
|
||||||
<td>cgi-fcgi</td></tr> |
|
||||||
<tr> |
|
||||||
<th>MYSQL版本</th> |
|
||||||
<td>5.5.53</td></tr> |
|
||||||
<tr> |
|
||||||
<th>ThinkPHP</th> |
|
||||||
<td>5.0.18</td></tr> |
|
||||||
<tr> |
|
||||||
<th>上传附件限制</th> |
|
||||||
<td>2M</td></tr> |
|
||||||
<tr> |
|
||||||
<th>执行时间限制</th> |
|
||||||
<td>30s</td></tr> |
|
||||||
<tr> |
|
||||||
<th>剩余空间</th> |
|
||||||
<td>86015.2M</td></tr> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
</fieldset> |
|
||||||
<fieldset class="layui-elem-field"> |
|
||||||
<legend>开发团队</legend> |
|
||||||
<div class="layui-field-box"> |
|
||||||
<table class="layui-table"> |
|
||||||
<tbody> |
|
||||||
<tr> |
|
||||||
<th>版权所有</th> |
|
||||||
<td>xuebingsi(xuebingsi) |
|
||||||
<a href="http://x.xuebingsi.com/" class='x-a' target="_blank">访问官网</a></td> |
|
||||||
</tr> |
|
||||||
<tr> |
|
||||||
<th>开发者</th> |
|
||||||
<td>马志斌(113664000@qq.com)</td></tr> |
|
||||||
</tbody> |
|
||||||
</table> |
|
||||||
</div> |
|
||||||
</fieldset> |
|
||||||
<blockquote class="layui-elem-quote layui-quote-nm">感谢layui,百度Echarts,jquery,本系统由x-admin提供技术支持。</blockquote> |
|
||||||
</div> |
|
||||||
<script> |
|
||||||
var _hmt = _hmt || []; |
|
||||||
(function() { |
|
||||||
var hm = document.createElement("script"); |
|
||||||
hm.src = "https://hm.baidu.com/hm.js?b393d153aeb26b46e9431fabaf0f6190"; |
|
||||||
var s = document.getElementsByTagName("script")[0]; |
|
||||||
s.parentNode.insertBefore(hm, s); |
|
||||||
})(); |
|
||||||
</script> |
|
||||||
</body> |
|
||||||
</html> |
</html> |
@ -1,13 +0,0 @@ |
|||||||
package com.gitee.sop.adminserver.api; |
|
||||||
|
|
||||||
import com.gitee.easyopen.annotation.ApiService; |
|
||||||
import com.gitee.easyopen.doc.annotation.ApiDoc; |
|
||||||
|
|
||||||
/** |
|
||||||
* @author tanghc |
|
||||||
*/ |
|
||||||
@ApiService |
|
||||||
@ApiDoc("路由列表") |
|
||||||
public class RouteListApi { |
|
||||||
|
|
||||||
} |
|
@ -1,4 +1,4 @@ |
|||||||
package com.gitee.sop.adminserver.api; |
package com.gitee.sop.adminserver.api.config; |
||||||
|
|
||||||
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; |
@ -1,12 +1,12 @@ |
|||||||
package com.gitee.sop.adminserver.api; |
package com.gitee.sop.adminserver.api.demo; |
||||||
|
|
||||||
import com.gitee.easyopen.annotation.Api; |
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.ApiDocField; |
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||||
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||||
import com.gitee.sop.adminserver.api.param.GoodsParam; |
import com.gitee.sop.adminserver.api.demo.param.GoodsParam; |
||||||
import com.gitee.sop.adminserver.api.result.Goods; |
import com.gitee.sop.adminserver.api.demo.result.Goods; |
||||||
|
|
||||||
import java.math.BigDecimal; |
import java.math.BigDecimal; |
||||||
import java.util.Arrays; |
import java.util.Arrays; |
@ -1,4 +1,4 @@ |
|||||||
package com.gitee.sop.adminserver.api.param; |
package com.gitee.sop.adminserver.api.demo.param; |
||||||
|
|
||||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||||
import org.hibernate.validator.constraints.Length; |
import org.hibernate.validator.constraints.Length; |
@ -1,4 +1,4 @@ |
|||||||
package com.gitee.sop.adminserver.api.result; |
package com.gitee.sop.adminserver.api.demo.result; |
||||||
|
|
||||||
import com.gitee.easyopen.doc.DataType; |
import com.gitee.easyopen.doc.DataType; |
||||||
import com.gitee.easyopen.doc.annotation.ApiDocField; |
import com.gitee.easyopen.doc.annotation.ApiDocField; |
@ -0,0 +1,57 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.service; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.gitee.easyopen.annotation.Api; |
||||||
|
import com.gitee.easyopen.annotation.ApiService; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDoc; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||||
|
import com.gitee.sop.adminserver.api.service.param.RouteSearchParam; |
||||||
|
import com.gitee.sop.adminserver.bean.GatewayRouteDefinition; |
||||||
|
import com.gitee.sop.adminserver.bean.SopAdminConstants; |
||||||
|
import com.gitee.sop.adminserver.bean.ZookeeperContext; |
||||||
|
import org.apache.commons.lang.StringUtils; |
||||||
|
import org.apache.curator.framework.recipes.cache.ChildData; |
||||||
|
|
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@ApiService |
||||||
|
@ApiDoc("服务管理") |
||||||
|
public class RouteListApi { |
||||||
|
|
||||||
|
@Api(name = "route.list") |
||||||
|
@ApiDocMethod(description = "路由列表", elementClass = GatewayRouteDefinition.class) |
||||||
|
List<GatewayRouteDefinition> listRoute(RouteSearchParam param) throws Exception { |
||||||
|
if (StringUtils.isBlank(param.getServiceId())) { |
||||||
|
return Collections.emptyList(); |
||||||
|
} |
||||||
|
|
||||||
|
String searchPath = ZookeeperContext.getSopRouteRootPath(param.getProfile()) + "/" + param.getServiceId(); |
||||||
|
|
||||||
|
List<ChildData> childDataList = ZookeeperContext.getChildrenData(searchPath); |
||||||
|
|
||||||
|
List<GatewayRouteDefinition> routeDefinitionList = childDataList.stream() |
||||||
|
.map(childData -> { |
||||||
|
String serviceNodeData = new String(childData.getData()); |
||||||
|
GatewayRouteDefinition routeDefinition = JSON.parseObject(serviceNodeData, GatewayRouteDefinition.class); |
||||||
|
return routeDefinition; |
||||||
|
}) |
||||||
|
.filter(gatewayRouteDefinition -> { |
||||||
|
boolean isRoute = gatewayRouteDefinition.getOrder() != Integer.MIN_VALUE; |
||||||
|
String id = param.getId(); |
||||||
|
if (StringUtils.isBlank(id)) { |
||||||
|
return isRoute; |
||||||
|
}else { |
||||||
|
return isRoute && gatewayRouteDefinition.getId().contains(id); |
||||||
|
} |
||||||
|
}) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
|
||||||
|
return routeDefinitionList; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.service; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON; |
||||||
|
import com.gitee.easyopen.annotation.Api; |
||||||
|
import com.gitee.easyopen.annotation.ApiService; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDoc; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||||
|
import com.gitee.sop.adminserver.api.service.param.ServiceSearchParam; |
||||||
|
import com.gitee.sop.adminserver.api.service.result.ServiceInfo; |
||||||
|
import com.gitee.sop.adminserver.bean.ZookeeperContext; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.apache.commons.lang.StringUtils; |
||||||
|
import org.apache.curator.framework.recipes.cache.ChildData; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.core.env.Environment; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
import static com.gitee.sop.adminserver.bean.SopAdminConstants.SOP_SERVICE_ROUTE_PATH; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@ApiService |
||||||
|
@ApiDoc("服务管理") |
||||||
|
@Slf4j |
||||||
|
public class ServiceApi { |
||||||
|
|
||||||
|
|
||||||
|
@Autowired |
||||||
|
private Environment environment; |
||||||
|
|
||||||
|
@Api(name = "service.list") |
||||||
|
@ApiDocMethod(description = "服务列表", elementClass = ServiceInfo.class) |
||||||
|
List<ServiceInfo> listServiceInfo(ServiceSearchParam param) throws Exception { |
||||||
|
String routeRootPath = ZookeeperContext.getSopRouteRootPath(param.getProfile()); |
||||||
|
List<ChildData> childDataList = ZookeeperContext.getChildrenData(routeRootPath); |
||||||
|
List<ServiceInfo> serviceInfoList = childDataList.stream() |
||||||
|
.map(childData -> { |
||||||
|
String serviceNodeData = new String(childData.getData()); |
||||||
|
ServiceInfo serviceInfo = JSON.parseObject(serviceNodeData, ServiceInfo.class); |
||||||
|
return serviceInfo; |
||||||
|
}) |
||||||
|
.filter(serviceInfo -> { |
||||||
|
if (StringUtils.isBlank(param.getServiceId())) { |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return serviceInfo.getServiceId().contains(param.getServiceId()); |
||||||
|
} |
||||||
|
}) |
||||||
|
.collect(Collectors.toList()); |
||||||
|
|
||||||
|
return serviceInfoList; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,13 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.service.param; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
import lombok.Setter; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
@Setter |
||||||
|
public class RouteSearchParam extends ServiceSearchParam { |
||||||
|
private String id; |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.service.param; |
||||||
|
|
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ServiceSearchParam { |
||||||
|
|
||||||
|
@ApiDocField(description = "profile") |
||||||
|
private String profile; |
||||||
|
|
||||||
|
@ApiDocField(description = "serviceId") |
||||||
|
private String serviceId; |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.service.result; |
||||||
|
|
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocField; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ServiceInfo { |
||||||
|
@ApiDocField(description = "serviceId") |
||||||
|
private String serviceId; |
||||||
|
|
||||||
|
@ApiDocField(description = "创建时间") |
||||||
|
private String createTime; |
||||||
|
|
||||||
|
@ApiDocField(description = "修改时间") |
||||||
|
private String updateTime; |
||||||
|
|
||||||
|
@ApiDocField(description = "描述") |
||||||
|
private String description; |
||||||
|
} |
@ -0,0 +1,34 @@ |
|||||||
|
package com.gitee.sop.adminserver.api.system; |
||||||
|
|
||||||
|
import com.gitee.easyopen.annotation.Api; |
||||||
|
import com.gitee.easyopen.annotation.ApiService; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDoc; |
||||||
|
import com.gitee.easyopen.doc.annotation.ApiDocMethod; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
import java.util.stream.Stream; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@ApiService |
||||||
|
@ApiDoc("系统接口") |
||||||
|
public class SystemApi { |
||||||
|
|
||||||
|
@Value("${sop-admin.profiles}") |
||||||
|
private String profiles; |
||||||
|
|
||||||
|
private List<String> profileList; |
||||||
|
|
||||||
|
@ApiDocMethod(description = "获取profile列表") |
||||||
|
@Api(name = "system.profile.list") |
||||||
|
public List<String> listProfiles() { |
||||||
|
if (profileList == null) { |
||||||
|
String[] arr = profiles.split("\\,"); |
||||||
|
profileList = Stream.of(arr).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
return profileList; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class GatewayFilterDefinition { |
||||||
|
/** Filter Name */ |
||||||
|
private String name; |
||||||
|
/** 对应的路由规则 */ |
||||||
|
private Map<String, String> args = new LinkedHashMap<>(); |
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import org.springframework.util.StringUtils; |
||||||
|
|
||||||
|
import javax.validation.ValidationException; |
||||||
|
import java.util.LinkedHashMap; |
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author thc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class GatewayPredicateDefinition { |
||||||
|
public static final String GEN_KEY = "_genkey_"; |
||||||
|
/** 断言对应的Name */ |
||||||
|
private String name; |
||||||
|
/** 配置的断言规则 */ |
||||||
|
private Map<String, String> args = new LinkedHashMap<>(); |
||||||
|
|
||||||
|
public GatewayPredicateDefinition() { |
||||||
|
} |
||||||
|
|
||||||
|
public GatewayPredicateDefinition(String text) { |
||||||
|
int eqIdx = text.indexOf(61); |
||||||
|
if (eqIdx <= 0) { |
||||||
|
throw new ValidationException("Unable to parse GatewayPredicateDefinition text '" + text + "', must be of the form name=value"); |
||||||
|
} else { |
||||||
|
this.setName(text.substring(0, eqIdx)); |
||||||
|
String[] args = StringUtils.tokenizeToStringArray(text.substring(eqIdx + 1), ","); |
||||||
|
|
||||||
|
for(int i = 0; i < args.length; ++i) { |
||||||
|
this.args.put(generateName(i), args[i]); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String generateName(int i) { |
||||||
|
return GEN_KEY + i; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class GatewayRouteDefinition { |
||||||
|
/** 路由的Id */ |
||||||
|
private String id = ""; |
||||||
|
/** 路由断言集合配置 */ |
||||||
|
private List<GatewayPredicateDefinition> predicates = new ArrayList<>(); |
||||||
|
/** 路由过滤器集合配置 */ |
||||||
|
private List<GatewayFilterDefinition> filters = new ArrayList<>(); |
||||||
|
/** 路由规则转发的目标uri */ |
||||||
|
private String uri; |
||||||
|
/** 路由执行的顺序 */ |
||||||
|
private int order = 0; |
||||||
|
/** 是否忽略验证,业务参数验证除外 */ |
||||||
|
private boolean ignoreValidate; |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField; |
||||||
|
import lombok.Data; |
||||||
|
|
||||||
|
import java.util.Date; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author thc |
||||||
|
*/ |
||||||
|
@Data |
||||||
|
public class ServiceRouteInfo { |
||||||
|
/** 服务名称,对应spring.application.name */ |
||||||
|
private String serviceId; |
||||||
|
|
||||||
|
@JSONField(format = "yyyy-MM-dd HH:mm:ss") |
||||||
|
private Date createTime = new Date(); |
||||||
|
|
||||||
|
@JSONField(format = "yyyy-MM-dd HH:mm:ss") |
||||||
|
private Date updateTime = new Date(); |
||||||
|
|
||||||
|
private String description; |
||||||
|
|
||||||
|
@JSONField(serialize = false) |
||||||
|
private List<GatewayRouteDefinition> routeDefinitionList; |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
public class SopAdminConstants { |
||||||
|
/** |
||||||
|
* zookeeper存放接口路由信息的根目录 |
||||||
|
*/ |
||||||
|
public static final String SOP_SERVICE_ROUTE_PATH = "/com.gitee.sop.route"; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
package com.gitee.sop.adminserver.bean; |
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils; |
||||||
|
import org.apache.commons.lang.math.NumberUtils; |
||||||
|
import org.apache.curator.framework.CuratorFramework; |
||||||
|
import org.apache.curator.framework.CuratorFrameworkFactory; |
||||||
|
import org.apache.curator.framework.recipes.cache.ChildData; |
||||||
|
import org.apache.curator.framework.recipes.cache.PathChildrenCache; |
||||||
|
import org.apache.curator.retry.ExponentialBackoffRetry; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
|
||||||
|
import javax.annotation.PostConstruct; |
||||||
|
import java.util.Collections; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author tanghc |
||||||
|
*/ |
||||||
|
@Configuration |
||||||
|
public class ZookeeperContext { |
||||||
|
|
||||||
|
public static final String SOP_ROUTE_ROOT_PATH = SopAdminConstants.SOP_SERVICE_ROUTE_PATH + "-%s"; |
||||||
|
|
||||||
|
private static CuratorFramework client; |
||||||
|
|
||||||
|
@Value("${spring.cloud.zookeeper.connect-string}") |
||||||
|
private String zookeeperServerAddr; |
||||||
|
|
||||||
|
@Value("${spring.cloud.zookeeper.baseSleepTimeMs}") |
||||||
|
private String baseSleepTimeMs; |
||||||
|
|
||||||
|
@Value("${spring.cloud.zookeeper.maxRetries}") |
||||||
|
private String maxRetries; |
||||||
|
|
||||||
|
@PostConstruct |
||||||
|
protected void after() { |
||||||
|
CuratorFramework client = CuratorFrameworkFactory.builder() |
||||||
|
.connectString(zookeeperServerAddr) |
||||||
|
.retryPolicy(new ExponentialBackoffRetry(NumberUtils.toInt(baseSleepTimeMs, 3000), NumberUtils.toInt(maxRetries, 3))) |
||||||
|
.build(); |
||||||
|
|
||||||
|
client.start(); |
||||||
|
|
||||||
|
setClient(client); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getSopRouteRootPath(String profile) { |
||||||
|
if (StringUtils.isBlank(profile)) { |
||||||
|
profile = "default"; |
||||||
|
} |
||||||
|
return String.format(SOP_ROUTE_ROOT_PATH, profile); |
||||||
|
} |
||||||
|
|
||||||
|
public static CuratorFramework getClient() { |
||||||
|
return client; |
||||||
|
} |
||||||
|
|
||||||
|
public static void setClient(CuratorFramework client) { |
||||||
|
ZookeeperContext.client = client; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isPathExist(String path) { |
||||||
|
try { |
||||||
|
return client.checkExists().forPath(path) != null; |
||||||
|
} catch (Exception e) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取子节点数据 |
||||||
|
* @param parentPath 父节点 |
||||||
|
* @return |
||||||
|
* @throws Exception |
||||||
|
*/ |
||||||
|
public static List<ChildData> getChildrenData(String parentPath) throws Exception { |
||||||
|
PathChildrenCache pathChildrenCache = buildPathChildrenCache(parentPath); |
||||||
|
if (pathChildrenCache == null) { |
||||||
|
return Collections.emptyList(); |
||||||
|
} |
||||||
|
return pathChildrenCache.getCurrentData(); |
||||||
|
} |
||||||
|
|
||||||
|
public static PathChildrenCache buildPathChildrenCache(String path) throws Exception { |
||||||
|
if (!isPathExist(path)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
// PathChildrenCache: 监听数据节点的增删改,可以设置触发的事件
|
||||||
|
// 且第三个参数要设置为true,不然ChildData对象中的getData返回null
|
||||||
|
PathChildrenCache childrenCache = new PathChildrenCache(client, path, true); |
||||||
|
// 列出子节点数据列表,需要使用BUILD_INITIAL_CACHE同步初始化模式才能获得,异步是获取不到的
|
||||||
|
childrenCache.start(PathChildrenCache.StartMode.BUILD_INITIAL_CACHE); |
||||||
|
return childrenCache; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -1,38 +0,0 @@ |
|||||||
server.port=8082 |
|
||||||
|
|
||||||
#################easyopen基础配置################# |
|
||||||
# 显示文档 |
|
||||||
easyopen.show-doc=true |
|
||||||
# 本地秘钥 |
|
||||||
easyopen.app-secret.test=123456 |
|
||||||
|
|
||||||
# 关闭跨域,默认开启 |
|
||||||
#easyopen.cors=false |
|
||||||
|
|
||||||
# 开启webflux |
|
||||||
easyopen.mono=false |
|
||||||
|
|
||||||
## 拦截器 |
|
||||||
#easyopen.interceptors[0]=com.gitee.easyopen.support.LimitInterceptor |
|
||||||
#easyopen.interceptors[1]=com.gitee.easyopen.support.PermissionInterceptor |
|
||||||
|
|
||||||
# 配置中心,config-server-port对应easyopen-config中的netty.server.port |
|
||||||
#easyopen.app-name=app-normal |
|
||||||
#easyopen.config-server-ip=127.0.0.1 |
|
||||||
#easyopen.config-server-port=8071 |
|
||||||
#easyopen.doc-url=http://127.0.0.1:8081/api/doc |
|
||||||
|
|
||||||
|
|
||||||
#################redis基础配置################# |
|
||||||
spring.redis.database=1 |
|
||||||
spring.redis.host=10.1.11.48 |
|
||||||
spring.redis.password=0987654321rfvujmtgbyhn |
|
||||||
spring.redis.port=6379 |
|
||||||
# 连接超时时间 单位 ms(毫秒) |
|
||||||
spring.redis.timeout=3000 |
|
||||||
|
|
||||||
|
|
||||||
logging.file=D:/logs/server/server |
|
||||||
logging.level.com.gitee=debug |
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@ |
|||||||
|
server: |
||||||
|
port: 8082 |
||||||
|
|
||||||
|
spring: |
||||||
|
application: |
||||||
|
name: sop-admin |
||||||
|
|
||||||
|
cloud: |
||||||
|
zookeeper: |
||||||
|
connect-string: localhost:2181 |
||||||
|
baseSleepTimeMs: 3000 |
||||||
|
maxRetries: 3 |
||||||
|
|
||||||
|
easyopen: |
||||||
|
show-doc: true |
||||||
|
mono: false |
||||||
|
ignore-validate: true |
||||||
|
|
||||||
|
sop-admin: |
||||||
|
profiles: default,prod,dev,test |
||||||
|
|
||||||
|
|
||||||
|
logging: |
||||||
|
level: |
||||||
|
com: |
||||||
|
gitee: debug |
||||||
|
|
@ -1 +0,0 @@ |
|||||||
spring.profiles.active=dev |
|
@ -0,0 +1,3 @@ |
|||||||
|
spring: |
||||||
|
profiles: |
||||||
|
active: dev |
@ -1,6 +1,7 @@ |
|||||||
spring: |
spring: |
||||||
application: |
application: |
||||||
name: story-service |
name: story-service |
||||||
|
description: story服务 |
||||||
|
|
||||||
cloud: |
cloud: |
||||||
zookeeper: |
zookeeper: |
||||||
|
Loading…
Reference in new issue