Initial commit (code only without large binaries)
This commit is contained in:
1
EdgeUser/web/views/@default/@blank.html
Normal file
1
EdgeUser/web/views/@default/@blank.html
Normal file
@@ -0,0 +1 @@
|
||||
{$layout}
|
||||
9
EdgeUser/web/views/@default/@code_editor.html
Normal file
9
EdgeUser/web/views/@default/@code_editor.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{$var "header"}
|
||||
<!-- code editor -->
|
||||
<script src="/codemirror/lib/codemirror.js" type="text/javascript"></script>
|
||||
<script src="/codemirror/mode/meta.js" type="text/javascript"></script>
|
||||
<script src="/codemirror/addon/edit/matchbrackets.js" type="text/javascript"></script>
|
||||
<script src="/codemirror/addon/mode/loadmode.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="/codemirror/lib/codemirror.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="/codemirror/theme/idea.css" type="text/css"/>
|
||||
{$end}
|
||||
4
EdgeUser/web/views/@default/@echarts.html
Normal file
4
EdgeUser/web/views/@default/@echarts.html
Normal file
@@ -0,0 +1,4 @@
|
||||
{$var "header"}
|
||||
<!-- echart -->
|
||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
|
||||
{$end}
|
||||
42
EdgeUser/web/views/@default/@grids.css
Normal file
42
EdgeUser/web/views/@default/@grids.css
Normal file
@@ -0,0 +1,42 @@
|
||||
.grid.counter-chart {
|
||||
margin-top: 1em !important;
|
||||
margin-left: 0.4em !important;
|
||||
}
|
||||
.grid.counter-chart .column {
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.85em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
border: 1px rgba(0, 0, 0, 0.1) solid;
|
||||
border-right: 0;
|
||||
}
|
||||
.grid.counter-chart .column div.value {
|
||||
margin-top: 1.5em;
|
||||
font-weight: normal;
|
||||
}
|
||||
.grid.counter-chart .column div.value span {
|
||||
font-size: 1.5em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
.grid.counter-chart .column.with-border {
|
||||
border-right: 1px rgba(0, 0, 0, 0.1) solid;
|
||||
}
|
||||
.grid.counter-chart h4 {
|
||||
color: grey;
|
||||
position: relative;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
.grid.counter-chart h4 a {
|
||||
position: absolute;
|
||||
right: 0.1em;
|
||||
font-size: 1.26em;
|
||||
display: none;
|
||||
}
|
||||
.grid.counter-chart .column:hover {
|
||||
background: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
.grid.counter-chart .column:hover a {
|
||||
display: inline;
|
||||
}
|
||||
/*# sourceMappingURL=@grids.css.map */
|
||||
1
EdgeUser/web/views/@default/@grids.css.map
Normal file
1
EdgeUser/web/views/@default/@grids.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["@grids.less"],"names":[],"mappings":"AAAA,KAAK;EACJ,0BAAA;EACA,kBAAA;;AAFD,KAAK,cAIJ;EACC,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;EACA,oCAAA;EACA,eAAA;;AAVF,KAAK,cAIJ,QAQC,IAAG;EACF,iBAAA;EACA,mBAAA;;AAdH,KAAK,cAIJ,QAQC,IAAG,MAIF;EACC,gBAAA;EACA,mBAAA;;AAlBJ,KAAK,cAuBJ,QAAO;EACN,0CAAA;;AAxBF,KAAK,cA2BJ;EACC,WAAA;EACA,kBAAA;EASA,cAAA;EACA,gBAAA;;AAvCF,KAAK,cA2BJ,GAIC;EACC,kBAAA;EACA,YAAA;EACA,iBAAA;EACA,aAAA;;AAnCH,KAAK,cA0CJ,QAAO;EACN,+BAAA;;AA3CF,KAAK,cA0CJ,QAAO,MAGN;EACC,eAAA","file":"@grids.css"}
|
||||
50
EdgeUser/web/views/@default/@grids.less
Normal file
50
EdgeUser/web/views/@default/@grids.less
Normal file
@@ -0,0 +1,50 @@
|
||||
.grid.counter-chart {
|
||||
margin-top: 1em !important;
|
||||
margin-left: 0.4em !important;
|
||||
|
||||
.column {
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.85em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
border: 1px rgba(0, 0, 0, .1) solid;
|
||||
border-right: 0;
|
||||
|
||||
div.value {
|
||||
margin-top: 1.5em;
|
||||
font-weight: normal;
|
||||
|
||||
span {
|
||||
font-size: 1.5em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.column.with-border {
|
||||
border-right: 1px rgba(0, 0, 0, .1) solid;
|
||||
}
|
||||
|
||||
h4 {
|
||||
color: grey;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
position: absolute;
|
||||
right: 0.1em;
|
||||
font-size: 1.26em;
|
||||
display: none;
|
||||
}
|
||||
|
||||
font-size: 1.0em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.column:hover {
|
||||
background: rgba(0, 0, 0, .03)!important;
|
||||
|
||||
a {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
}
|
||||
898
EdgeUser/web/views/@default/@layout.css
Normal file
898
EdgeUser/web/views/@default/@layout.css
Normal file
@@ -0,0 +1,898 @@
|
||||
.left-box {
|
||||
width: 8.5em;
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 2.4em;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-right: 1px #ddd solid;
|
||||
}
|
||||
.left-box .menu {
|
||||
width: 95% !important;
|
||||
}
|
||||
.left-box .menu .item {
|
||||
line-height: 1.2;
|
||||
position: relative;
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
.left-box .menu .item .icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -0.4em !important;
|
||||
}
|
||||
.left-box .menu .item .sub-name {
|
||||
font-size: 0.7em;
|
||||
font-style: normal;
|
||||
color: grey;
|
||||
}
|
||||
.left-box .menu .item.separator {
|
||||
border-bottom: 1px #eee solid !important;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.left-box .menu .item.on span {
|
||||
border-bottom: 1px #666 dashed;
|
||||
}
|
||||
.left-box .menu .item.off span var {
|
||||
font-style: normal;
|
||||
background: #db2828;
|
||||
color: white;
|
||||
font-size: 8px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
.left-box .menu .item.active {
|
||||
background: rgba(230, 230, 230, 0.35) !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.left-box .menu .header {
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-left: 0 !important;
|
||||
padding-bottom: 1em !important;
|
||||
}
|
||||
.left-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.left-box.disabled {
|
||||
opacity: 0.1;
|
||||
}
|
||||
.left-box.tiny {
|
||||
top: 10.5em;
|
||||
}
|
||||
.left-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
.left-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
.left-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
.right-box {
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 1.3em;
|
||||
right: 0;
|
||||
left: 18em;
|
||||
padding-right: 2em;
|
||||
padding-bottom: 2em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.right-box {
|
||||
left: 13em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
body.expanded .right-box {
|
||||
left: 10em;
|
||||
}
|
||||
.right-box.tiny {
|
||||
top: 10.4em;
|
||||
left: 26.5em;
|
||||
}
|
||||
.right-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.right-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
.right-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
.right-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
.main.without-footer .left-box {
|
||||
bottom: 0.2em;
|
||||
}
|
||||
.narrow-scrollbar::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.grid.counter-chart {
|
||||
margin-top: 1em !important;
|
||||
margin-left: 0.4em !important;
|
||||
}
|
||||
.grid.counter-chart .column {
|
||||
margin-bottom: 1em;
|
||||
font-size: 0.85em;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
border: 1px rgba(0, 0, 0, 0.1) solid;
|
||||
border-right: 0;
|
||||
}
|
||||
.grid.counter-chart .column div.value {
|
||||
margin-top: 1.5em;
|
||||
font-weight: normal;
|
||||
}
|
||||
.grid.counter-chart .column div.value span {
|
||||
font-size: 1.5em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
.grid.counter-chart .column.with-border {
|
||||
border-right: 1px rgba(0, 0, 0, 0.1) solid;
|
||||
}
|
||||
.grid.counter-chart h4 {
|
||||
color: grey;
|
||||
position: relative;
|
||||
font-size: 1em;
|
||||
text-align: left;
|
||||
}
|
||||
.grid.counter-chart h4 a {
|
||||
position: absolute;
|
||||
right: 0.1em;
|
||||
font-size: 1.26em;
|
||||
display: none;
|
||||
}
|
||||
.grid.counter-chart .column:hover {
|
||||
background: rgba(0, 0, 0, 0.03) !important;
|
||||
}
|
||||
.grid.counter-chart .column:hover a {
|
||||
display: inline;
|
||||
}
|
||||
/** 通用 **/
|
||||
* {
|
||||
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
a.disabled,
|
||||
a.disabled:hover,
|
||||
a.disabled:active,
|
||||
span.disabled {
|
||||
color: #ccc !important;
|
||||
}
|
||||
a.enabled,
|
||||
span.enabled,
|
||||
span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
a.grey,
|
||||
span.grey,
|
||||
label.grey,
|
||||
p.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
p.grey {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
span.red,
|
||||
pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
span.blue {
|
||||
color: #4183c4;
|
||||
}
|
||||
span.orange {
|
||||
color: #ff851b;
|
||||
}
|
||||
pre:not(.CodeMirror-line) {
|
||||
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
|
||||
}
|
||||
tbody {
|
||||
background: transparent;
|
||||
}
|
||||
.table.width30 {
|
||||
width: 30em !important;
|
||||
}
|
||||
.table.width35 {
|
||||
width: 35em !important;
|
||||
}
|
||||
.table.width40 {
|
||||
width: 40em !important;
|
||||
}
|
||||
.table th,
|
||||
.table td {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
.table tr.active td {
|
||||
background: rgba(0, 0, 0, 0.01) !important;
|
||||
}
|
||||
p.comment,
|
||||
div.comment {
|
||||
color: #959da6;
|
||||
padding-top: 0.4em;
|
||||
font-size: 1em;
|
||||
}
|
||||
p.comment em,
|
||||
div.comment em {
|
||||
font-style: italic !important;
|
||||
}
|
||||
.truncate {
|
||||
white-space: nowrap;
|
||||
-ms-text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
div.margin,
|
||||
p.margin {
|
||||
margin-top: 1em;
|
||||
}
|
||||
/** 操作按钮容器 **/
|
||||
.op.one {
|
||||
width: 4em;
|
||||
}
|
||||
.op.two {
|
||||
width: 7.4em;
|
||||
}
|
||||
.op.three {
|
||||
width: 9em;
|
||||
}
|
||||
.op.four {
|
||||
width: 10em;
|
||||
}
|
||||
/** 主菜单 **/
|
||||
.main-menu {
|
||||
width: 8em !important;
|
||||
}
|
||||
.main-menu .ui.menu {
|
||||
width: 100% !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.main-menu .ui.menu .item.separator {
|
||||
border-top: 1px rgba(0, 0, 0, 0.2) solid;
|
||||
height: 1px;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main-menu {
|
||||
width: auto !important;
|
||||
}
|
||||
.main-menu .ui.menu {
|
||||
width: 3.6em !important;
|
||||
}
|
||||
.main-menu .ui.menu .item.separator {
|
||||
display: none;
|
||||
}
|
||||
.main-menu .ui.menu .item {
|
||||
padding-top: 2em;
|
||||
padding-bottom: 2.4em;
|
||||
}
|
||||
}
|
||||
.main-menu .ui.labeled.icon.menu .item {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.main-menu .ui.menu {
|
||||
padding-bottom: 3em;
|
||||
}
|
||||
.main-menu .ui.menu .item .subtitle {
|
||||
display: none;
|
||||
}
|
||||
.main-menu .ui.menu .item.expend .subtitle {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
padding-left: 2em;
|
||||
margin-top: 0.5em;
|
||||
color: grey;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main-menu .ui.menu .item.expend .subtitle {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.main-menu .ui.menu .sub-items .item {
|
||||
padding-left: 2.8em !important;
|
||||
padding-right: 0.4em !important;
|
||||
}
|
||||
.main-menu .ui.menu .sub-items .item .icon {
|
||||
position: absolute;
|
||||
left: 1.1em;
|
||||
top: 0.93em;
|
||||
}
|
||||
.main-menu .ui.menu .sub-items .item .label {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding-left: 0.4em;
|
||||
padding-right: 0.4em;
|
||||
min-width: 2em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main-menu .ui.menu .sub-items .item {
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
}
|
||||
.main-menu .ui.menu .item.active {
|
||||
background: rgba(230, 230, 230, 0.45) !important;
|
||||
}
|
||||
.main-menu .ui.menu .sub-items .item.active {
|
||||
background: rgba(230, 230, 230, 0.55) !important;
|
||||
}
|
||||
/** 扩展UI **/
|
||||
.field.text {
|
||||
padding: 0.5em;
|
||||
}
|
||||
/** body **/
|
||||
@keyframes blink {
|
||||
from {
|
||||
opacity: 0.1;
|
||||
}
|
||||
to {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
body .ui.menu .item .blink {
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
body.expanded .main-menu {
|
||||
display: none;
|
||||
}
|
||||
body.expanded .sub-menu {
|
||||
display: none;
|
||||
}
|
||||
body.expanded .main {
|
||||
left: 1em;
|
||||
}
|
||||
/** 布局相关 */
|
||||
.top-nav {
|
||||
border-radius: 0 !important;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
overflow-x: auto;
|
||||
background: #14539A !important;
|
||||
}
|
||||
.top-nav::-webkit-scrollbar {
|
||||
height: 2px;
|
||||
}
|
||||
.top-nav img.avatar {
|
||||
width: 1.6em !important;
|
||||
height: 1.6em !important;
|
||||
padding: 0.2em;
|
||||
background: #fff;
|
||||
border-radius: 0.9em;
|
||||
margin-right: 0.5em !important;
|
||||
}
|
||||
.top-nav em {
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
.top-nav .item.red {
|
||||
color: red !important;
|
||||
}
|
||||
.top-nav .item .hover-span span {
|
||||
display: none;
|
||||
}
|
||||
.top-nav .item:hover .hover-span span {
|
||||
display: inline;
|
||||
}
|
||||
/** 顶部菜单 **/
|
||||
.top-secondary-menu {
|
||||
position: fixed;
|
||||
top: 2.6em;
|
||||
left: 8.2em;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: white;
|
||||
}
|
||||
.top-secondary-menu .menu {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
.top-secondary-menu .menu var {
|
||||
font-style: normal;
|
||||
}
|
||||
.top-secondary-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.top-secondary-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
/** 右侧主操作区 **/
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 22em;
|
||||
top: 5.6em;
|
||||
padding-bottom: 5em;
|
||||
padding-right: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
.main.without-menu {
|
||||
left: 9em;
|
||||
}
|
||||
.main.without-secondary-menu {
|
||||
top: 2.9em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main.without-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
.main table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
.main table td.middle-title {
|
||||
width: 14em;
|
||||
}
|
||||
.main table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.main table td.color-border {
|
||||
border-left: 1px #276ac6 solid !important;
|
||||
}
|
||||
.main table td.vertical-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
.main table td.vertical-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.main table td[colspan="2"] a {
|
||||
font-weight: normal;
|
||||
}
|
||||
.main table td em {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.main h3 {
|
||||
font-weight: normal;
|
||||
margin-top: 1em !important;
|
||||
position: relative;
|
||||
}
|
||||
.main h3 span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.main h3 span.label {
|
||||
color: #6435c9;
|
||||
}
|
||||
.main h3 a {
|
||||
margin-left: 1em;
|
||||
font-size: 14px !important;
|
||||
right: 1em;
|
||||
}
|
||||
.main h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
.main form h4 {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
.main td span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.main .button.mini {
|
||||
font-size: 0.8em;
|
||||
padding: 0.2em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
.main-menu {
|
||||
position: fixed;
|
||||
/**top: 1.05em;**/
|
||||
top: 2em;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
background: #14539A !important;
|
||||
z-index: 10;
|
||||
}
|
||||
.main-menu .menu {
|
||||
background: #14539A !important;
|
||||
}
|
||||
.main-menu::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
}
|
||||
.main .tab-menu {
|
||||
margin-top: 1em !important;
|
||||
margin-bottom: 0 !important;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
.main .tab-menu .item {
|
||||
padding: 1em !important;
|
||||
}
|
||||
.main .tab-menu .item var {
|
||||
font-style: normal;
|
||||
}
|
||||
.main .tab-menu .item span {
|
||||
font-size: 0.8em;
|
||||
padding-left: 0.3em;
|
||||
}
|
||||
.main .tab-menu .item .icon {
|
||||
margin-left: 0.6em;
|
||||
}
|
||||
.main .tab-menu .item.active {
|
||||
background: #f8f8f9 !important;
|
||||
}
|
||||
.main .tab-menu::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
.main .go-top-btn {
|
||||
position: fixed;
|
||||
right: 2.6em;
|
||||
bottom: 2em;
|
||||
font-size: 2em;
|
||||
line-height: 1.4em;
|
||||
border-radius: 1em;
|
||||
z-index: 999999;
|
||||
background: white;
|
||||
}
|
||||
/** 子菜单 **/
|
||||
.main.without-menu .sub-menu {
|
||||
display: none;
|
||||
}
|
||||
.sub-menu {
|
||||
position: fixed;
|
||||
left: 8em;
|
||||
width: 12.5em;
|
||||
top: 3em;
|
||||
bottom: 2.8em;
|
||||
}
|
||||
.sub-menu .menus-box {
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding-right: 0.4em !important;
|
||||
}
|
||||
.sub-menu .menus-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
.sub-menu .menu {
|
||||
max-width: 12em !important;
|
||||
border-right: 0 !important;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.sub-menu {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
.sub-menu .menus-box {
|
||||
position: relative !important;
|
||||
}
|
||||
.sub-menu .menu {
|
||||
width: 100% !important;
|
||||
max-width: 30em !important;
|
||||
}
|
||||
.sub-menu .menus-box .menu .item {
|
||||
width: 100% !important;
|
||||
max-width: 30em !important;
|
||||
}
|
||||
}
|
||||
.sub-menu .menu .item.active {
|
||||
font-weight: normal !important;
|
||||
outline: none !important;
|
||||
}
|
||||
.sub-menu .menu .item:not(.header) {
|
||||
padding-top: 0.7em !important;
|
||||
padding-bottom: 0.7em !important;
|
||||
}
|
||||
.sub-menu .menu .item:not(.header) span {
|
||||
font-size: 0.8em;
|
||||
display: block;
|
||||
margin-top: 0.6em !important;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.sub-menu .menu .item:not(.active):hover {
|
||||
background: rgba(0, 0, 0, 0.05) !important;
|
||||
border-top: 1px white solid !important;
|
||||
border-bottom: 1px white solid !important;
|
||||
margin-top: -1px !important;
|
||||
margin-bottom: -1px !important;
|
||||
}
|
||||
.sub-menu .menu .item.active {
|
||||
background: rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
.sub-menu .menu .item var {
|
||||
font-style: normal;
|
||||
}
|
||||
.sub-menu .menu .item:not(.active) var.grey {
|
||||
color: grey;
|
||||
}
|
||||
.sub-menu .menu .item span:not(.green) {
|
||||
color: grey;
|
||||
}
|
||||
.sub-menu .menu .item span.red {
|
||||
color: #db2828 !important;
|
||||
}
|
||||
.sub-menu .menus-box .menu .item.header {
|
||||
padding-right: 0.2em !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
.sub-menu .menus-box .menu .item.header span {
|
||||
font-weight: normal;
|
||||
color: grey;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.sub-menu .menus-box .menu a {
|
||||
display: block;
|
||||
word-break: break-all;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
.sub-menu .menus-box .menu .item .menu {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.sub-menu .fourth-menu {
|
||||
margin-left: 1.2em;
|
||||
}
|
||||
.sub-menu .fourth-menu .icon,
|
||||
.sub-menu .third-menu .icon {
|
||||
float: left !important;
|
||||
}
|
||||
/** 右侧文本子菜单 **/
|
||||
.text.menu {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.text.menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
/** 脚部相关样式 **/
|
||||
#footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
text-align: left;
|
||||
color: gray;
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
z-index: 10;
|
||||
overflow-x: auto;
|
||||
}
|
||||
#footer::-webkit-scrollbar {
|
||||
height: 2px;
|
||||
}
|
||||
#footer a {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
#footer a form {
|
||||
display: none;
|
||||
}
|
||||
#footer a:hover span,
|
||||
#footer a:active span {
|
||||
display: none;
|
||||
}
|
||||
#footer a:hover form,
|
||||
#footer a:active form {
|
||||
display: block;
|
||||
}
|
||||
#footer form input {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
#footer-outer-box {
|
||||
z-index: 999999;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
bottom: 2.6em;
|
||||
}
|
||||
#footer-outer-box .qrcode {
|
||||
width: 20em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -14em;
|
||||
margin-left: -10em;
|
||||
}
|
||||
#footer-outer-box .qrcode img {
|
||||
width: 100%;
|
||||
}
|
||||
#footer-outer-box .qrcode a {
|
||||
position: absolute;
|
||||
right: 0.5em;
|
||||
top: 0.5em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
#footer-outer-box .qrcode {
|
||||
margin-left: 0;
|
||||
left: 3.5em;
|
||||
}
|
||||
}
|
||||
/** Vue **/
|
||||
[v-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
/** auto complete **/
|
||||
.autocomplete-box .menu {
|
||||
background: #eee !important;
|
||||
}
|
||||
.autocomplete-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.autocomplete-box .menu .item {
|
||||
border-top: none !important;
|
||||
}
|
||||
select.auto-width {
|
||||
width: auto !important;
|
||||
}
|
||||
/** column **/
|
||||
@media screen and (max-width: 512px) {
|
||||
.column:not(.one) {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
label[for] {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
label.blue {
|
||||
color: #2185d0 !important;
|
||||
}
|
||||
/** Menu **/
|
||||
.first-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.first-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.second-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.second-menu .menu.text em {
|
||||
font-style: normal;
|
||||
}
|
||||
.second-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.menu a {
|
||||
outline: none;
|
||||
}
|
||||
/** var **/
|
||||
span.olive,
|
||||
var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
span.hover:hover {
|
||||
background: #eee;
|
||||
}
|
||||
/** checkbox **/
|
||||
.checkbox label a,
|
||||
.checkbox label {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
/** page **/
|
||||
.page {
|
||||
margin-top: 1em;
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
.page a {
|
||||
display: inline-block;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
padding: 6px 12px;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
border: 1px solid #ddd;
|
||||
border-left: 0;
|
||||
}
|
||||
.page a.active {
|
||||
background: #2185d0 !important;
|
||||
color: white;
|
||||
}
|
||||
.page a:hover {
|
||||
background: #eee;
|
||||
}
|
||||
.page select {
|
||||
padding-top: 0.3em !important;
|
||||
padding-bottom: 0.3em !important;
|
||||
}
|
||||
/** popup **/
|
||||
.swal2-html-container {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.swal2-close,
|
||||
.swal2-close:focus {
|
||||
border: 0;
|
||||
}
|
||||
.swal2-confirm:focus,
|
||||
.swal2-cancel:focus {
|
||||
border: 3px #ddd solid !important;
|
||||
}
|
||||
.swal2-confirm,
|
||||
.swal2-cancel {
|
||||
border: 3px #fff solid !important;
|
||||
}
|
||||
.swal2-cancel {
|
||||
margin-left: 2em !important;
|
||||
}
|
||||
/** 排序 **/
|
||||
.sortable-ghost {
|
||||
background: #ddd !important;
|
||||
opacity: 0.1;
|
||||
}
|
||||
.sortable-drag {
|
||||
opacity: 1;
|
||||
}
|
||||
.icon.handle {
|
||||
cursor: pointer;
|
||||
}
|
||||
.label.port-label {
|
||||
margin-top: 0.4em !important;
|
||||
margin-bottom: 0.4em !important;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
}
|
||||
.label {
|
||||
word-break: break-all;
|
||||
}
|
||||
td .label.small {
|
||||
margin-bottom: 0.2em !important;
|
||||
}
|
||||
td {
|
||||
word-break: break-all;
|
||||
}
|
||||
.combo-box .menu {
|
||||
max-height: 17em;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
border: rgba(129, 177, 210, 0.81) 1px solid;
|
||||
border-top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.methods-box {
|
||||
background: white;
|
||||
}
|
||||
.methods-box .method-box {
|
||||
margin-bottom: 1em;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px #eee solid;
|
||||
}
|
||||
.methods-box .method-box.active {
|
||||
border: 1px #eee solid;
|
||||
background: #eee;
|
||||
}
|
||||
.methods-box .method-box:hover {
|
||||
background: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
.scroll-box {
|
||||
overflow-y: auto;
|
||||
}
|
||||
.scroll-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
/*# sourceMappingURL=@layout.css.map */
|
||||
1
EdgeUser/web/views/@default/@layout.css.map
Normal file
1
EdgeUser/web/views/@default/@layout.css.map
Normal file
File diff suppressed because one or more lines are too long
163
EdgeUser/web/views/@default/@layout.html
Normal file
163
EdgeUser/web/views/@default/@layout.html
Normal file
@@ -0,0 +1,163 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
|
||||
<head>
|
||||
<title>{$ htmlEncode .teaTitle}</title>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
{$if eq .teaFaviconFileId 0}
|
||||
<link rel="shortcut icon" href="/images/favicon.png" />
|
||||
{$else}
|
||||
<link rel="shortcut icon" href="/ui/image/{$.teaFaviconFileId}" />
|
||||
{$end}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout.css" media="all" />
|
||||
{$TEA.SEMANTIC}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout_override.css" media="all" />
|
||||
|
||||
{$TEA.VUE}
|
||||
{$echo "header"}
|
||||
<!-- 品牌配置 -->
|
||||
<script type="text/javascript">
|
||||
window.BRAND_OFFICIAL_SITE = { $ jsonEncode .brandConfig.officialSite };
|
||||
window.BRAND_DOCS_SITE = { $ jsonEncode .brandConfig.docsSite };
|
||||
window.BRAND_DOCS_PREFIX = { $ jsonEncode .brandConfig.docsPathPrefix };
|
||||
window.BRAND_PRODUCT_NAME = { $ jsonEncode .brandConfig.productName };
|
||||
</script>
|
||||
<script type="text/javascript" src="/js/config/brand.js"></script>
|
||||
<script type="text/javascript" src="/_/@default/@layout.js"></script>
|
||||
<script type="text/javascript" src="/js/components.js?v=v{$.teaVersion}"></script>
|
||||
<script type="text/javascript" src="/js/utils.min.js"></script>
|
||||
<script type="text/javascript" src="/js/sweetalert2/dist/sweetalert2.all.min.js"></script>
|
||||
<script type="text/javascript" src="/js/date.tea.js"></script>
|
||||
|
||||
{$if not (eq .teaThemeBackgroundColor "")}
|
||||
<style>
|
||||
.top-nav.user-theme-enabled,
|
||||
.main-menu.user-theme-enabled,
|
||||
.main-menu.user-theme-enabled .menu {
|
||||
background: #{$.teaThemeBackgroundColor} !important;
|
||||
}
|
||||
</style>
|
||||
{$end}
|
||||
<!-- 应用保存的主题颜色 -->
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
try {
|
||||
var savedColor = null;
|
||||
if (savedColor) {
|
||||
var styleId = "theme-color-custom";
|
||||
var styleEl = document.getElementById(styleId);
|
||||
if (!styleEl) {
|
||||
styleEl = document.createElement("style");
|
||||
styleEl.id = styleId;
|
||||
document.head.appendChild(styleEl);
|
||||
}
|
||||
styleEl.textContent = ".top-nav, .main-menu, .main-menu .menu { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu.vertical.blue.inverted.tiny.borderless { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu.vertical.blue.inverted.tiny.borderless .item { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu.vertical.blue.inverted.tiny.borderless .sub-items { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu.vertical.blue.inverted.tiny.borderless .sub-items .item { background: " + savedColor + " !important; } .main-menu .ui.menu .sub-items { background: " + savedColor + " !important; } .main-menu .ui.menu .sub-items .item { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu .sub-items { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu .sub-items .item { background: " + savedColor + " !important; } .main-menu .sub-items { background: " + savedColor + " !important; } .main-menu .sub-items .item { background: " + savedColor + " !important; } .ui.menu.blue.inverted { background: " + savedColor + " !important; } .ui.menu.blue.inverted .item { background: " + savedColor + " !important; } .ui.menu.vertical.blue.inverted { background: " + savedColor + " !important; } .ui.menu.vertical.blue.inverted .item { background: " + savedColor + " !important; } .ui.labeled.menu.vertical.blue.inverted { background: " + savedColor + " !important; } .ui.labeled.menu.vertical.blue.inverted .item { background: " + savedColor + " !important; } .main-menu .ui.labeled.menu.vertical.blue.inverted .item.active { background: rgba(230, 230, 230, 0.45) !important; } .main-menu .ui.menu .sub-items .item.active { background: rgba(230, 230, 230, 0.55) !important; }";
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Failed to apply saved theme color:", e);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div>
|
||||
<!-- 顶部导航 -->
|
||||
<div class="ui menu top-nav blue inverted small borderless" v-cloak="">
|
||||
<a href="/dashboard" class="item">
|
||||
<i class="ui icon leaf" v-if="teaLogoFileId == 0"></i><img v-if="teaLogoFileId > 0"
|
||||
:src="'/ui/image/' + teaLogoFileId" style="width: auto;height: 1.6em" />
|
||||
{{teaTitle}} <sup v-if="teaShowVersion">v{{teaVersion}}</sup>
|
||||
</a>
|
||||
|
||||
<div class="right menu">
|
||||
<a href="/messages" class="item" :class="{active:teaMenu == 'message'}">
|
||||
<span v-if="globalMessageBadge > 0" class="blink hover-span"><i
|
||||
class="icon bell"></i><span>消息({{globalMessageBadge}})</span></span>
|
||||
<span v-if="globalMessageBadge == 0" class="hover-span"><i class="icon bell disabled"></i><span
|
||||
class="disabled">消息(0)</span></span>
|
||||
</a>
|
||||
<a href="/settings/profile" class="item">
|
||||
<i class="icon user" v-if="teaUserAvatar.length == 0"></i>
|
||||
<img class="avatar" alt="" :src="teaUserAvatar" v-if="teaUserAvatar.length > 0" />
|
||||
<span class="hover-span"><span class="disabled">{{teaUsername}}</span></span>
|
||||
</a>
|
||||
<a href="/docs" class="item" :class="{active: teaMenu == 'docs'}"><i class="icon file"></i><span
|
||||
class="hover-span"><span>文档</span></span></a>
|
||||
<!-- 自定义主题颜色 -->
|
||||
<theme-color-picker v-if="false"></theme-color-picker>
|
||||
<a href="/" class="item" v-show="teaShowIndexPage">
|
||||
<i class="icon home"></i><span class="hover-span"><span>首页</span></span>
|
||||
</a>
|
||||
<a :href="Tea.url('logout')" class="item" title="安全退出登录"><i class="icon sign out"></i>
|
||||
<span class="hover-span"><span class="disabled">退出</span></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 左侧主菜单 -->
|
||||
<div class="main-menu" v-cloak="">
|
||||
<div class="ui labeled menu vertical blue inverted tiny borderless">
|
||||
<div class="item"></div>
|
||||
<!--<a :href="Tea.url('dashboard')" class="item" :class="{active:teaMenu == 'dashboard'}">
|
||||
<i class="ui dashboard icon"></i>
|
||||
<span>仪表板</span>
|
||||
</a>-->
|
||||
|
||||
<!-- 模块 -->
|
||||
<div v-for="module in teaModules">
|
||||
<a class="item" :href="Tea.url(module.code)"
|
||||
:class="{active:teaMenu == module.code && teaSubMenu.length == 0, separator:module.code.length == 0}"
|
||||
:style="(teaMenu == module.code && teaSubMenu.length == 0) ? 'background: rgba(230, 230, 230, 0.45) !important;' : ''">
|
||||
<span v-if="module.code.length > 0">
|
||||
<i class="window restore outline icon" v-if="module.icon == null"></i>
|
||||
<i class="ui icon" v-if="module.icon != null" :class="module.icon"></i>
|
||||
<span>{{module.name}}</span>
|
||||
</span>
|
||||
</a>
|
||||
<div v-if="teaMenu == module.code" class="sub-items">
|
||||
<a class="item" v-for="subItem in module.subItems" :href="subItem.url"
|
||||
:class="{active:subItem.code == teaSubMenu}"
|
||||
:style="(subItem.code == teaSubMenu) ? 'background: rgba(230, 230, 230, 0.55) !important;' : ''"
|
||||
v-if="subItem.isOn == null || subItem.isOn === true">{{subItem.name}}<i
|
||||
class="icon angle right"
|
||||
v-if="subItem.name != '-' && subItem.code == teaSubMenu"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右侧主操作栏 -->
|
||||
<div class="main"
|
||||
:class="{'without-menu':teaSubMenus.menus == null || teaSubMenus.menus.length == 0 || (teaSubMenus.menus.length == 1 && teaSubMenus.menus[0].alwaysActive), 'without-secondary-menu':teaSubMenus.alwaysMenu == null || teaSubMenus.alwaysMenu.items.length <= 1, 'without-footer':!teaShowPageFooter}"
|
||||
v-cloak="">
|
||||
<!-- 操作菜单 -->
|
||||
<div class="ui top menu tabular tab-menu small" v-if="teaTabbar.length > 0">
|
||||
<a class="item" v-for="item in teaTabbar" :class="{'active':item.active,right:item.right}"
|
||||
:href="item.url">
|
||||
<var>{{item.name}}<span v-if="item.subName.length > 0">({{item.subName}})</span><i
|
||||
class="icon small" :class="item.icon" v-if="item.icon != null && item.icon.length > 0"></i>
|
||||
</var>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- 功能区 -->
|
||||
{$TEA.VIEW}
|
||||
</div>
|
||||
|
||||
<!-- 底部 -->
|
||||
<div id="footer" class="ui menu inverted light-blue borderless small"
|
||||
v-if="teaShowPageFooter && teaPageFooterHTML.length == 0" v-cloak>
|
||||
<a class="item" title="点击进入检查版本更新页面">{{teaName}} v{{teaVersion}}</a>
|
||||
</div>
|
||||
<div id="footer" class="ui menu inverted light-blue borderless small"
|
||||
v-if="teaShowPageFooter && teaPageFooterHTML.length > 0" v-html="teaPageFooterHTML" v-cloak> </div>
|
||||
</div>
|
||||
|
||||
{$echo "footer"}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
131
EdgeUser/web/views/@default/@layout.js
Normal file
131
EdgeUser/web/views/@default/@layout.js
Normal file
@@ -0,0 +1,131 @@
|
||||
Tea.context(function () {
|
||||
this.moreOptionsVisible = false
|
||||
this.globalMessageBadge = 0
|
||||
|
||||
if (typeof this.leftMenuItemIsDisabled == "undefined") {
|
||||
this.leftMenuItemIsDisabled = false
|
||||
}
|
||||
|
||||
this.$delay(function () {
|
||||
if (this.$refs.focus != null) {
|
||||
this.$refs.focus.focus()
|
||||
}
|
||||
|
||||
// 检查消息
|
||||
this.checkMessages()
|
||||
})
|
||||
|
||||
/**
|
||||
* 左侧子菜单
|
||||
*/
|
||||
this.showSubMenu = function (menu) {
|
||||
if (menu.alwaysActive) {
|
||||
return
|
||||
}
|
||||
if (this.teaSubMenus.menus != null && this.teaSubMenus.menus.length > 0) {
|
||||
this.teaSubMenus.menus.$each(function (k, v) {
|
||||
if (menu.id == v.id) {
|
||||
return
|
||||
}
|
||||
v.isActive = false
|
||||
})
|
||||
}
|
||||
menu.isActive = !menu.isActive
|
||||
};
|
||||
|
||||
/**
|
||||
* 检查消息
|
||||
*/
|
||||
this.checkMessages = function () {
|
||||
this.$post("/messages/badge")
|
||||
.params({})
|
||||
.success(function (resp) {
|
||||
this.globalMessageBadge = resp.data.count
|
||||
|
||||
// add dot to title
|
||||
let dots = "••• "
|
||||
if (typeof document.title == "string") {
|
||||
if (resp.data.count > 0) {
|
||||
if (!document.title.startsWith(dots)) {
|
||||
document.title = dots + document.title
|
||||
}
|
||||
} else if (document.title.startsWith(dots)) {
|
||||
document.title = document.title.substring(dots.length)
|
||||
}
|
||||
}
|
||||
})
|
||||
.done(function () {
|
||||
let delay = 30000
|
||||
if (this.globalMessageBadge > 0) {
|
||||
delay = 60000
|
||||
}
|
||||
this.$delay(function () {
|
||||
this.checkMessages()
|
||||
}, delay)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 底部伸展框
|
||||
*/
|
||||
this.showQQGroupQrcode = function () {
|
||||
teaweb.popup("/about/qq", {
|
||||
width: "21em",
|
||||
height: "24em"
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 弹窗中默认成功回调
|
||||
*/
|
||||
if (window.IS_POPUP === true) {
|
||||
this.success = window.NotifyPopup
|
||||
}
|
||||
});
|
||||
|
||||
window.NotifySuccess = function (message, url, params) {
|
||||
if (typeof (url) == "string" && url.length > 0) {
|
||||
if (url[0] != "/") {
|
||||
url = Tea.url(url, params);
|
||||
}
|
||||
}
|
||||
return function () {
|
||||
teaweb.success(message, function () {
|
||||
window.location = url;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
window.NotifyReloadSuccess = function (message) {
|
||||
return function () {
|
||||
teaweb.success(message, function () {
|
||||
window.location.reload()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
window.NotifyDelete = function (message, url, params) {
|
||||
teaweb.confirm(message, function () {
|
||||
Tea.Vue.$post(url)
|
||||
.params(params)
|
||||
.refresh();
|
||||
});
|
||||
};
|
||||
|
||||
window.NotifyPopup = function (resp) {
|
||||
window.parent.teaweb.popupFinish(resp);
|
||||
};
|
||||
|
||||
window.ChangePageSize = function (size) {
|
||||
let url = window.location.toString();
|
||||
if (url.indexOf("pageSize") > 0) {
|
||||
url = url.replace(/pageSize=\d+/g, "pageSize=" + size);
|
||||
} else {
|
||||
if (url.indexOf("?") > 0) {
|
||||
url += "&pageSize=" + size;
|
||||
} else {
|
||||
url += "?pageSize=" + size;
|
||||
}
|
||||
}
|
||||
window.location = url;
|
||||
};
|
||||
911
EdgeUser/web/views/@default/@layout.less
Normal file
911
EdgeUser/web/views/@default/@layout.less
Normal file
@@ -0,0 +1,911 @@
|
||||
@import "./@left_menu";
|
||||
@import "./@grids";
|
||||
|
||||
/** 通用 **/
|
||||
* {
|
||||
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
a.disabled, a.disabled:hover, a.disabled:active, span.disabled {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
a.enabled, span.enabled, span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
|
||||
a.grey, span.grey, label.grey, p.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
|
||||
p.grey {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
span.red, pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
|
||||
span.blue {
|
||||
color: #4183c4;
|
||||
}
|
||||
|
||||
span.orange {
|
||||
color: #ff851b;
|
||||
}
|
||||
|
||||
pre:not(.CodeMirror-line) {
|
||||
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
|
||||
}
|
||||
|
||||
tbody {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.table.width30 {
|
||||
width: 30em !important;
|
||||
}
|
||||
|
||||
.table.width35 {
|
||||
width: 35em !important;
|
||||
}
|
||||
|
||||
.table.width40 {
|
||||
width: 40em !important;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
|
||||
.table tr.active td {
|
||||
background: rgba(0, 0, 0, 0.01) !important;
|
||||
}
|
||||
|
||||
p.comment, div.comment {
|
||||
color: #959da6;
|
||||
padding-top: 0.4em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
p.comment em, div.comment em {
|
||||
font-style: italic !important;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
white-space: nowrap;
|
||||
-ms-text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
div.margin, p.margin {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
/** 操作按钮容器 **/
|
||||
.op.one {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.op.two {
|
||||
width: 7.4em;
|
||||
}
|
||||
|
||||
.op.three {
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
.op.four {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
/** 主菜单 **/
|
||||
.main-menu {
|
||||
width: 8em !important;
|
||||
|
||||
.ui.menu {
|
||||
width: 100% !important;
|
||||
border-radius: 0 !important;
|
||||
|
||||
// menu
|
||||
.item.separator {
|
||||
border-top: 1px rgba(0, 0, 0, 0.2) solid;
|
||||
height: 1px;
|
||||
min-height: 0;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.main-menu {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.main-menu .ui.menu {
|
||||
width: 3.6em !important;
|
||||
|
||||
.item.separator {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.main-menu .ui.menu .item {
|
||||
padding-top: 2em;
|
||||
padding-bottom: 2.4em;
|
||||
}
|
||||
|
||||
.main-menu .ui.menu .item span {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.main-menu .ui.labeled.icon.menu .item {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
.ui.menu {
|
||||
padding-bottom: 3em;
|
||||
|
||||
|
||||
.item {
|
||||
.subtitle {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item.expend .subtitle {
|
||||
display: block;
|
||||
font-size: 10px;
|
||||
padding-left: 2.0em;
|
||||
margin-top: 0.5em;
|
||||
color: grey;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.item.expend .subtitle {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-items {
|
||||
.item {
|
||||
padding-left: 2.8em !important;
|
||||
padding-right: 0.4em !important;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
left: 1.1em;
|
||||
top: 0.93em;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
padding-left: 0.4em;
|
||||
padding-right: 0.4em;
|
||||
min-width: 2em;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.item {
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
}
|
||||
|
||||
.item.active {
|
||||
background-color: #2185d0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 扩展UI **/
|
||||
.field.text {
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
/** body **/
|
||||
@keyframes blink {
|
||||
from {
|
||||
opacity: 0.1;
|
||||
}
|
||||
to {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
body .ui.menu .item .blink {
|
||||
animation: blink 1s infinite;
|
||||
}
|
||||
|
||||
body.expanded .main-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.expanded .sub-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body.expanded .main {
|
||||
left: 1em;
|
||||
}
|
||||
|
||||
/** 布局相关 */
|
||||
.top-nav {
|
||||
border-radius: 0 !important;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
overflow-x: auto;
|
||||
background: #14539A !important;
|
||||
}
|
||||
|
||||
.top-nav::-webkit-scrollbar {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
.top-nav img.avatar {
|
||||
width: 1.6em !important;
|
||||
height: 1.6em !important;
|
||||
padding: 0.2em;
|
||||
background: #fff;
|
||||
border-radius: 0.9em;
|
||||
margin-right: 0.5em !important;
|
||||
}
|
||||
|
||||
.top-nav em {
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
padding-left: 0.2em;
|
||||
}
|
||||
|
||||
.top-nav .item.red {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
/** 顶部菜单 **/
|
||||
.top-secondary-menu {
|
||||
position: fixed;
|
||||
top: 2.6em;
|
||||
left: 8.2em;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.top-secondary-menu .menu {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
|
||||
.top-secondary-menu .menu var {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.top-secondary-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.top-secondary-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
/** 右侧主操作区 **/
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 22em;
|
||||
top: 5.6em;
|
||||
padding-bottom: 5em;
|
||||
padding-right: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.main {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
.main.without-menu {
|
||||
left: 9em;
|
||||
}
|
||||
|
||||
.main.without-secondary-menu {
|
||||
top: 2.9em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.main.without-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
.main table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.main table td.middle-title {
|
||||
width: 14em;
|
||||
}
|
||||
|
||||
.main table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.main table td.color-border {
|
||||
border-left: 1px #276ac6 solid !important;
|
||||
}
|
||||
|
||||
.main table td.vertical-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.main table td.vertical-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.main table td[colspan="2"] a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.main table td em {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.main h3 {
|
||||
font-weight: normal;
|
||||
margin-top: 1em !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main h3 span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.main h3 span.label {
|
||||
color: #6435c9;
|
||||
}
|
||||
|
||||
.main h3 a {
|
||||
margin-left: 1em;
|
||||
font-size: 14px !important;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.main h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.main form h4 {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
.main td span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.main .button.mini {
|
||||
font-size: 0.8em;
|
||||
padding: 0.2em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.main-menu {
|
||||
position: fixed;
|
||||
/**top: 1.05em;**/
|
||||
top: 2em;
|
||||
bottom: 0;
|
||||
overflow-y: auto;
|
||||
background: #14539A !important;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.main-menu .menu {
|
||||
background: #14539A !important;
|
||||
}
|
||||
|
||||
.main-menu::-webkit-scrollbar {
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
.main {
|
||||
.tab-menu {
|
||||
margin-top: 1em !important;
|
||||
margin-bottom: 0 !important;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
|
||||
.item {
|
||||
padding: 1em !important;
|
||||
|
||||
var {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 0.8em;
|
||||
padding-left: 0.3em;
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 0.6em;
|
||||
}
|
||||
}
|
||||
|
||||
.item.active {
|
||||
background: #f8f8f9 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-menu::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.main .go-top-btn {
|
||||
position: fixed;
|
||||
right: 2.6em;
|
||||
bottom: 2em;
|
||||
font-size: 2em;
|
||||
line-height: 1.4em;
|
||||
border-radius: 1em;
|
||||
z-index: 999999;
|
||||
background: white;
|
||||
}
|
||||
|
||||
/** 子菜单 **/
|
||||
.main.without-menu .sub-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sub-menu {
|
||||
position: fixed;
|
||||
left: 8em;
|
||||
width: 12.5em;
|
||||
top: 3em;
|
||||
bottom: 2.8em;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box {
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
padding-right: 0.4em !important;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.sub-menu .menu {
|
||||
max-width: 12em !important;
|
||||
border-right: 0 !important;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.sub-menu {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box {
|
||||
position: relative !important;
|
||||
}
|
||||
|
||||
.sub-menu .menu {
|
||||
width: 100% !important;
|
||||
max-width: 30em !important;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box .menu .item {
|
||||
width: 100% !important;
|
||||
max-width: 30em !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sub-menu .menu .item.active {
|
||||
font-weight: normal !important;
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item:not(.header) {
|
||||
padding-top: 0.7em !important;
|
||||
padding-bottom: 0.7em !important;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item:not(.header) span {
|
||||
font-size: 0.8em;
|
||||
display: block;
|
||||
margin-top: 0.6em !important;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item:not(.active):hover {
|
||||
background: rgba(0, 0, 0, 0.05) !important;
|
||||
border-top: 1px white solid !important;
|
||||
border-bottom: 1px white solid !important;
|
||||
margin-top: -1px !important;
|
||||
margin-bottom: -1px !important;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item.active {
|
||||
background: rgba(0, 0, 0, 0.05) !important;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item var {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item:not(.active) var.grey {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item span:not(.green) {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.sub-menu .menu .item span.red {
|
||||
color: #db2828 !important;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box .menu .item.header {
|
||||
padding-right: 0.2em !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box .menu .item.header span {
|
||||
font-weight: normal;
|
||||
color: grey;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box .menu a {
|
||||
display: block;
|
||||
word-break: break-all;
|
||||
line-height: 1.6 !important;
|
||||
}
|
||||
|
||||
.sub-menu .menus-box .menu .item .menu {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.sub-menu .fourth-menu {
|
||||
margin-left: 1.2em;
|
||||
}
|
||||
|
||||
.sub-menu .fourth-menu .icon, .sub-menu .third-menu .icon {
|
||||
float: left !important;
|
||||
}
|
||||
|
||||
/** 右侧文本子菜单 **/
|
||||
.text.menu {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.text.menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/** 脚部相关样式 **/
|
||||
#footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
text-align: left;
|
||||
color: gray;
|
||||
width: 100%;
|
||||
border-radius: 0 !important;
|
||||
z-index: 10;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
#footer::-webkit-scrollbar {
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
#footer a {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
#footer a form {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#footer a:hover span, #footer a:active span {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#footer a:hover form, #footer a:active form {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#footer form input {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#footer-outer-box {
|
||||
z-index: 999999;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
right: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
bottom: 2.6em;
|
||||
}
|
||||
|
||||
#footer-outer-box .qrcode {
|
||||
width: 20em;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-top: -14em;
|
||||
margin-left: -10em;
|
||||
}
|
||||
|
||||
#footer-outer-box .qrcode img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#footer-outer-box .qrcode a {
|
||||
position: absolute;
|
||||
right: 0.5em;
|
||||
top: 0.5em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
#footer-outer-box .qrcode {
|
||||
margin-left: 0;
|
||||
left: 3.5em;
|
||||
}
|
||||
}
|
||||
|
||||
/** Vue **/
|
||||
[v-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/** auto complete **/
|
||||
.autocomplete-box .menu {
|
||||
background: #eee !important;
|
||||
}
|
||||
|
||||
.autocomplete-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.autocomplete-box .menu .item {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
select.auto-width {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/** column **/
|
||||
@media screen and (max-width: 512px) {
|
||||
.column:not(.one) {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
// label
|
||||
label[for] {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
label.blue {
|
||||
color: #2185d0 !important;
|
||||
}
|
||||
|
||||
/** Menu **/
|
||||
.first-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.first-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.second-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.second-menu .menu.text em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.second-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/** var **/
|
||||
span.olive, var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
|
||||
span.hover:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
/** checkbox **/
|
||||
.checkbox label a, .checkbox label {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
|
||||
.checkbox label {
|
||||
|
||||
}
|
||||
|
||||
/** page **/
|
||||
.page {
|
||||
margin-top: 1em;
|
||||
|
||||
border-left: 1px solid #ddd;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
padding: 6px 12px;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
border: 1px solid #ddd;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
a.active {
|
||||
background: #2185d0 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
select {
|
||||
padding-top: 0.3em !important;
|
||||
padding-bottom: 0.3em !important;
|
||||
}
|
||||
}
|
||||
|
||||
/** popup **/
|
||||
.swal2-html-container {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.swal2-close, .swal2-close:focus {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.swal2-confirm:focus, .swal2-cancel:focus {
|
||||
border: 3px #ddd solid !important;
|
||||
}
|
||||
|
||||
.swal2-confirm, .swal2-cancel {
|
||||
border: 3px #fff solid !important;
|
||||
}
|
||||
|
||||
.swal2-cancel {
|
||||
margin-left: 2em !important;
|
||||
}
|
||||
|
||||
/** 排序 **/
|
||||
.sortable-ghost {
|
||||
background: #ddd !important;
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.sortable-drag {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.icon.handle {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.label.port-label {
|
||||
margin-top: 0.4em !important;
|
||||
margin-bottom: 0.4em !important;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// .label
|
||||
.label {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
td .label.small {
|
||||
margin-bottom: 0.2em !important;
|
||||
}
|
||||
|
||||
// td
|
||||
td {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
// combo-box
|
||||
.combo-box .menu {
|
||||
max-height: 17em;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
border: rgba(129, 177, 210, 0.81) 1px solid;
|
||||
border-top: 0;
|
||||
z-index: 100
|
||||
}
|
||||
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
// 支付方式
|
||||
.methods-box {
|
||||
background: white;
|
||||
|
||||
.method-box {
|
||||
margin-bottom: 1em;
|
||||
padding: 0.5em 1em;
|
||||
border: 1px #eee solid;
|
||||
}
|
||||
|
||||
.method-box.active {
|
||||
border: 1px #eee solid;
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
.method-box:hover {
|
||||
background: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
// scroll
|
||||
.scroll-box {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.scroll-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
117
EdgeUser/web/views/@default/@layout_override.css
Normal file
117
EdgeUser/web/views/@default/@layout_override.css
Normal file
@@ -0,0 +1,117 @@
|
||||
/* 全局字体大小调整 - 增加 10% */
|
||||
html {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
body {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
.ui.toggle.checkbox input:focus:checked ~ .box:before,
|
||||
.ui.toggle.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #21ba45 !important;
|
||||
}
|
||||
.ui.toggle.checkbox input:checked ~ .box:before,
|
||||
.ui.toggle.checkbox input:checked ~ label:before {
|
||||
background-color: #21ba45 !important;
|
||||
}
|
||||
.ui.label.basic {
|
||||
background-color: white !important;
|
||||
}
|
||||
.ui.basic.grey.label.border-grey {
|
||||
border-color: #ddd !important;
|
||||
}
|
||||
form .fields {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
form .warning,
|
||||
form .success,
|
||||
form .error {
|
||||
display: block !important;
|
||||
}
|
||||
.link.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
.link.grey:hover {
|
||||
color: #4183c4 !important;
|
||||
}
|
||||
table th.center,
|
||||
table td.center {
|
||||
text-align: center !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
table th.width10 {
|
||||
width: 10em;
|
||||
}
|
||||
table th.width5 {
|
||||
width: 5em;
|
||||
}
|
||||
table th.width6 {
|
||||
width: 6em;
|
||||
}
|
||||
.ui.table tbody[style*="display: none;"],
|
||||
.ui.table tr[style*="display: none;"],
|
||||
.ui.table tr > td[style*="display: none;"],
|
||||
.ui.table tr > th[style*="display: none;"] {
|
||||
display: none!important;
|
||||
}
|
||||
textarea::-webkit-scrollbar {
|
||||
width: 6px !important;
|
||||
}
|
||||
select.dropdown {
|
||||
height: auto !important;
|
||||
}
|
||||
:root {
|
||||
--admin-top-nav-bg: #0a1f3f;
|
||||
--admin-side-menu-bg: #102a4d;
|
||||
}
|
||||
.top-nav,
|
||||
.top-nav.theme1,
|
||||
.top-nav.theme2,
|
||||
.top-nav.theme3,
|
||||
.top-nav.theme4,
|
||||
.top-nav.theme5,
|
||||
.top-nav.theme6,
|
||||
.top-nav.theme7 {
|
||||
background: var(--admin-top-nav-bg) !important;
|
||||
}
|
||||
.main-menu,
|
||||
.main-menu.theme1,
|
||||
.main-menu.theme2,
|
||||
.main-menu.theme3,
|
||||
.main-menu.theme4,
|
||||
.main-menu.theme5,
|
||||
.main-menu.theme6,
|
||||
.main-menu.theme7,
|
||||
.main-menu .menu,
|
||||
.main-menu.theme1 .menu,
|
||||
.main-menu.theme2 .menu,
|
||||
.main-menu.theme3 .menu,
|
||||
.main-menu.theme4 .menu,
|
||||
.main-menu.theme5 .menu,
|
||||
.main-menu.theme6 .menu,
|
||||
.main-menu.theme7 .menu {
|
||||
background: var(--admin-side-menu-bg) !important;
|
||||
}
|
||||
.main-menu .ui.menu .item.separator,
|
||||
.main-menu .ui.menu .sub-items .item.separator {
|
||||
display: none !important;
|
||||
border: 0 !important;
|
||||
height: 0 !important;
|
||||
min-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
.left-box .menu .item.active {
|
||||
background: rgba(230, 230, 230, 0.35) !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.main-menu .ui.labeled.menu.vertical.blue.inverted .item.active,
|
||||
.main-menu .ui.menu.vertical.blue.inverted .item.active,
|
||||
.main-menu .ui.menu .item.active {
|
||||
background: rgba(230, 230, 230, 0.45) !important;
|
||||
}
|
||||
.main-menu .ui.labeled.menu.vertical.blue.inverted .sub-items .item.active,
|
||||
.main-menu .ui.menu .sub-items .item.active {
|
||||
background: rgba(230, 230, 230, 0.55) !important;
|
||||
}
|
||||
/*# sourceMappingURL=@layout_override.css.map */
|
||||
1
EdgeUser/web/views/@default/@layout_override.css.map
Normal file
1
EdgeUser/web/views/@default/@layout_override.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["@layout_override.less"],"names":[],"mappings":"AACA,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,MAAM,QAAS,QAAO;EACrG,yBAAA;;AAGD,GAAG,OAAO,SAAU,MAAK,QAAS,OAAM;AAAS,GAAG,OAAO,SAAU,MAAK,QAAS,QAAO;EACzF,yBAAA;;AAGD,GAAG,MAAM;EACR,kCAAA;;AAGD,GAAG,MAAM,KAAK,MAAM;EACnB,kBAAA;;AAID,IACC;EACC,2BAAA;;AAFF,IAKC;AALD,IAKW;AALX,IAKqB;EACnB,yBAAA;;AAKF,KAAK;EACJ,sBAAA;;AAGD,KAAK,KAAK;EACT,cAAA;;AAID,KACC,GAAE;AADH,KACY,GAAE;EACZ,6BAAA;EACA,0BAAA;EACA,2BAAA;;AAJF,KAOC,GAAE;EACD,WAAA;;AARF,KAWC,GAAE;EACD,UAAA;;AAZF,KAeC,GAAE;EACD,UAAA;;AAIF,GAAG,MAAO,MAAK;AAA2B,GAAG,MAAO,GAAE;AAA2B,GAAG,MAAO,GAAE,KAAG;AAA2B,GAAG,MAAO,GAAE,KAAG;EACzI,uBAAA;;AAID,QAAQ;EACP,qBAAA;;AAID,MAAM;EACL,uBAAA","file":"@layout_override.css"}
|
||||
126
EdgeUser/web/views/@default/@layout_override.less
Normal file
126
EdgeUser/web/views/@default/@layout_override.less
Normal file
@@ -0,0 +1,126 @@
|
||||
// 全局字体大小调整 - 增加 10%
|
||||
html {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
// labels
|
||||
.ui.toggle.checkbox input:focus:checked ~ .box:before, .ui.toggle.checkbox input:focus:checked ~ label:before {
|
||||
background-color: #21ba45 !important;
|
||||
}
|
||||
|
||||
.ui.toggle.checkbox input:checked ~ .box:before, .ui.toggle.checkbox input:checked ~ label:before {
|
||||
background-color: #21ba45 !important;
|
||||
}
|
||||
|
||||
.ui.label.basic {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
.ui.basic.grey.label.border-grey {
|
||||
border-color: #ddd!important;
|
||||
}
|
||||
|
||||
// fields
|
||||
form {
|
||||
.fields {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.warning, .success, .error {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
|
||||
// links
|
||||
.link.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
|
||||
.link.grey:hover {
|
||||
color: #4183c4 !important;
|
||||
}
|
||||
|
||||
// table
|
||||
table {
|
||||
th.center, td.center {
|
||||
text-align: center !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
th.width10 {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
th.width5 {
|
||||
width: 5em;
|
||||
}
|
||||
|
||||
th.width6 {
|
||||
width: 6em;
|
||||
}
|
||||
}
|
||||
|
||||
.ui.table tbody[style*="display: none;"], .ui.table tr[style*="display: none;"], .ui.table tr>td[style*="display: none;"], .ui.table tr>th[style*="display: none;"] {
|
||||
display: none!important;
|
||||
}
|
||||
|
||||
// textarea
|
||||
textarea::-webkit-scrollbar {
|
||||
width: 6px !important;
|
||||
}
|
||||
|
||||
// dropdown
|
||||
select.dropdown {
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
// Menu background colors and separator cleanup
|
||||
:root {
|
||||
--admin-top-nav-bg: #0a1f3f;
|
||||
--admin-side-menu-bg: #102a4d;
|
||||
}
|
||||
|
||||
.top-nav,
|
||||
.top-nav.theme1,
|
||||
.top-nav.theme2,
|
||||
.top-nav.theme3,
|
||||
.top-nav.theme4,
|
||||
.top-nav.theme5,
|
||||
.top-nav.theme6,
|
||||
.top-nav.theme7 {
|
||||
background: var(--admin-top-nav-bg) !important;
|
||||
}
|
||||
|
||||
.main-menu,
|
||||
.main-menu.theme1,
|
||||
.main-menu.theme2,
|
||||
.main-menu.theme3,
|
||||
.main-menu.theme4,
|
||||
.main-menu.theme5,
|
||||
.main-menu.theme6,
|
||||
.main-menu.theme7,
|
||||
.main-menu .menu,
|
||||
.main-menu.theme1 .menu,
|
||||
.main-menu.theme2 .menu,
|
||||
.main-menu.theme3 .menu,
|
||||
.main-menu.theme4 .menu,
|
||||
.main-menu.theme5 .menu,
|
||||
.main-menu.theme6 .menu,
|
||||
.main-menu.theme7 .menu {
|
||||
background: var(--admin-side-menu-bg) !important;
|
||||
}
|
||||
|
||||
.main-menu .ui.menu .item.separator,
|
||||
.main-menu .ui.menu .sub-items .item.separator {
|
||||
display: none !important;
|
||||
border: 0 !important;
|
||||
height: 0 !important;
|
||||
min-height: 0 !important;
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
326
EdgeUser/web/views/@default/@layout_popup.css
Normal file
326
EdgeUser/web/views/@default/@layout_popup.css
Normal file
@@ -0,0 +1,326 @@
|
||||
/** 通用 **/
|
||||
* {
|
||||
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
a.disabled,
|
||||
a.disabled:hover,
|
||||
a.disabled:active,
|
||||
span.disabled {
|
||||
color: #ccc !important;
|
||||
}
|
||||
a.enabled,
|
||||
span.enabled,
|
||||
span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
span.grey,
|
||||
label.grey,
|
||||
p.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
p.grey {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
span.red,
|
||||
pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
pre:not(.CodeMirror-line) {
|
||||
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
|
||||
}
|
||||
tbody {
|
||||
background: transparent;
|
||||
}
|
||||
.table.width30 {
|
||||
width: 30em !important;
|
||||
}
|
||||
.table.width35 {
|
||||
width: 35em !important;
|
||||
}
|
||||
.table.width40 {
|
||||
width: 40em !important;
|
||||
}
|
||||
.table th,
|
||||
.table td {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
p.comment,
|
||||
div.comment {
|
||||
color: #959da6;
|
||||
padding-top: 0.4em;
|
||||
font-weight: normal;
|
||||
word-break: break-all;
|
||||
line-height: 1.8;
|
||||
}
|
||||
p.comment em,
|
||||
div.comment em {
|
||||
font-style: italic !important;
|
||||
}
|
||||
.truncate {
|
||||
white-space: nowrap;
|
||||
-ms-text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
div.margin,
|
||||
p.margin {
|
||||
margin-top: 1em;
|
||||
}
|
||||
/** 操作按钮容器 **/
|
||||
.op.one {
|
||||
width: 4em;
|
||||
}
|
||||
.op.two {
|
||||
width: 7.4em;
|
||||
}
|
||||
.op.three {
|
||||
width: 9em;
|
||||
}
|
||||
.op.four {
|
||||
width: 10em;
|
||||
}
|
||||
/** 扩展UI **/
|
||||
.field.text {
|
||||
padding: 0.5em;
|
||||
}
|
||||
/** 右侧主操作区 **/
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 22em;
|
||||
top: 5.6em;
|
||||
padding-bottom: 5em;
|
||||
padding-right: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
.main.without-menu {
|
||||
left: 9em;
|
||||
}
|
||||
.main.without-secondary-menu {
|
||||
top: 2.9em;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.main.without-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
.main table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
.main table td.middle-title {
|
||||
width: 14em;
|
||||
}
|
||||
.main table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
.main table td.color-border {
|
||||
border-left: 1px #276ac6 solid !important;
|
||||
}
|
||||
.main table td.vertical-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
.main table td.vertical-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.main table td[colspan="2"] a {
|
||||
font-weight: normal;
|
||||
}
|
||||
.main table td em {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.main h3 {
|
||||
font-weight: normal;
|
||||
margin-top: 0.5em !important;
|
||||
}
|
||||
.main h3 span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.main h3 span.label {
|
||||
color: #6435c9;
|
||||
}
|
||||
.main h3 a {
|
||||
margin-left: 1em;
|
||||
font-size: 14px !important;
|
||||
right: 1em;
|
||||
}
|
||||
.main h3 a::before {
|
||||
content: "[";
|
||||
}
|
||||
.main h3 a::after {
|
||||
content: "]";
|
||||
}
|
||||
.main h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
.main td span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.main .button.mini {
|
||||
font-size: 0.8em;
|
||||
padding: 0.2em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
/** 右侧文本子菜单 **/
|
||||
.text.menu {
|
||||
overflow-x: auto;
|
||||
}
|
||||
.text.menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
/** Vue **/
|
||||
[v-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
/** auto complete **/
|
||||
.autocomplete-box .menu {
|
||||
background: #eee !important;
|
||||
}
|
||||
.autocomplete-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.autocomplete-box .menu .item {
|
||||
border-top: none !important;
|
||||
}
|
||||
select.auto-width {
|
||||
width: auto !important;
|
||||
}
|
||||
/** column **/
|
||||
@media screen and (max-width: 512px) {
|
||||
.column:not(.one) {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
/** label **/
|
||||
label[for] {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
label.blue {
|
||||
color: #2185d0 !important;
|
||||
}
|
||||
span.blue {
|
||||
color: #4183c4;
|
||||
}
|
||||
/** Menu **/
|
||||
.first-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.first-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.second-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.second-menu .menu.text em {
|
||||
font-style: normal;
|
||||
}
|
||||
.second-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
.menu a {
|
||||
outline: none;
|
||||
}
|
||||
/** var **/
|
||||
span.olive,
|
||||
var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
span.hover:hover {
|
||||
background: #eee;
|
||||
}
|
||||
/** Message **/
|
||||
.message .gopher {
|
||||
width: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
/** checkbox **/
|
||||
.checkbox label a,
|
||||
.checkbox label {
|
||||
font-size: 0.8em !important;
|
||||
}
|
||||
/** page **/
|
||||
.page {
|
||||
margin-top: 1em;
|
||||
border-left: 1px solid #ddd;
|
||||
}
|
||||
.page a {
|
||||
display: inline-block;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
padding: 6px 12px;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
border: 1px solid #ddd;
|
||||
border-left: 0;
|
||||
}
|
||||
.page a.active {
|
||||
background: #2185d0 !important;
|
||||
color: white;
|
||||
}
|
||||
.page a:hover {
|
||||
background: #eee;
|
||||
}
|
||||
/** popup **/
|
||||
.swal2-html-container {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.swal2-confirm:focus,
|
||||
.swal2-cancel:focus,
|
||||
.swal2-close:focus {
|
||||
border: 3px #ddd solid !important;
|
||||
}
|
||||
.swal2-confirm,
|
||||
.swal2-cancel,
|
||||
.swal2-close {
|
||||
border: 3px #fff solid !important;
|
||||
}
|
||||
.swal2-cancel {
|
||||
margin-left: 2em !important;
|
||||
}
|
||||
.combo-box .menu {
|
||||
max-height: 17em;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
border: rgba(129, 177, 210, 0.81) 1px solid;
|
||||
border-top: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
code-label {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(34, 36, 38, 0.15);
|
||||
color: rgba(0, 0, 0, 0.87);
|
||||
font-size: 0.71428571rem;
|
||||
padding: 3px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
/*# sourceMappingURL=@layout_popup.css.map */
|
||||
1
EdgeUser/web/views/@default/@layout_popup.css.map
Normal file
1
EdgeUser/web/views/@default/@layout_popup.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["@layout_popup.less"],"names":[],"mappings":";AACA;EACC,+CAAA;EACA,qBAAA;;AAGD;EACC,WAAA;;AAGD;EACC,aAAA;;AAGD;EACC,qBAAA;;AAGD,CAAC;AAAW,CAAC,SAAS;AAAQ,CAAC,SAAS;AAAS,IAAI;EACpD,WAAA;;AAGD,CAAC;AAAU,IAAI;AAAU,IAAI;EAC5B,cAAA;;AAGD,IAAI;AAAO,KAAK;AAAO,CAAC;EACvB,sBAAA;;AAGD,CAAC;EACA,iBAAA;;AAGD,IAAI;AAAM,GAAG;EACZ,cAAA;;AAGD,GAAG,IAAI;EACN,mBAAmB,8CAAnB;;AAGD;EACC,uBAAA;;AAGD,MAAM;EACL,sBAAA;;AAGD,MAAM;EACL,sBAAA;;AAGD,MAAM;EACL,sBAAA;;AAGD,MAAO;AAAI,MAAO;EACjB,gBAAA;;AAGD,CAAC;AAAU,GAAG;EACb,cAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;EACA,gBAAA;;AAGD,CAAC,QAAS;AAAI,GAAG,QAAS;EACzB,6BAAA;;AAGD;EACC,mBAAA;EACA,2BAAA;EACA,gBAAA;EACA,uBAAA;;AAGD,GAAG;AAAS,CAAC;EACZ,eAAA;;;AAID,GAAG;EACF,UAAA;;AAGD,GAAG;EACF,YAAA;;AAGD,GAAG;EACF,UAAA;;AAGD,GAAG;EACF,WAAA;;;AAID,MAAM;EACL,cAAA;;;AAID;EACC,kBAAA;EACA,UAAA;EACA,UAAA;EACA,mBAAA;EACA,kBAAA;EACA,UAAA;;AAGD,mBAAqC;EACpC;IACC,SAAA;;;AAIF,KAAK;EACJ,SAAA;;AAGD,KAAK;EACJ,UAAA;;AAGD,mBAAqC;EACpC,KAAK;IACJ,SAAA;;;AAIF,KAAM,MAAM,GAAE;EACb,WAAA;;AAGD,KAAM,MAAM,GAAE;EACb,WAAA;;AAGD,KAAM,MAAM;EACX,mBAAA;;AAGD,KAAM,MAAM,GAAE;EACb,8BAAA;;AAGD,KAAM,MAAM,GAAE;EACb,mBAAA;;AAGD,KAAM,MAAM,GAAE;EACb,sBAAA;;AAGD,KAAM,MAAM,GAAE,aAAc;EAC3B,mBAAA;;AAGD,KAAM,MAAM,GAAG;EACd,mBAAA;EACA,kBAAA;EACA,gBAAA;;AAGD,KAAM;EACL,mBAAA;EACA,iBAAA;;AAGD,KAAM,GAAG;EACR,gBAAA;;AAGD,KAAM,GAAG,KAAI;EACZ,cAAA;;AAGD,KAAM,GAAG;EACR,gBAAA;EACA,0BAAA;EACA,UAAA;;AAGD,KAAM,GAAG,EAAC;EACT,SAAS,GAAT;;AAGD,KAAM,GAAG,EAAC;EACT,SAAS,GAAT;;AAGD,KAAM;EACL,mBAAA;;AAGD,KAAM,GAAG,KAAI;EACZ,gBAAA;;AAGD,KAAM,QAAO;EACZ,gBAAA;EACA,cAAA;EACA,gBAAA;;;AAID,KAAK;EACJ,gBAAA;;AAGD,KAAK,KAAK;EACT,UAAA;EACA,WAAA;;;AAID;EACC,wBAAA;;;AAID,iBAAkB;EACjB,gBAAA;;AAGD,iBAAkB,MAAK;EACtB,UAAA;;AAGD,iBAAkB,MAAM;EACvB,2BAAA;;AAGD,MAAM;EACL,sBAAA;;;AAID,mBAAqC;EACpC,OAAO,IAAI;IACV,sBAAA;;;;AAKF,KAAK;EACJ,0BAAA;;AAGD,KAAK;EACJ,cAAA;;AAGD,IAAI;EACH,cAAA;;;AAOD,WAAY,MAAK;EAChB,wBAAA;EACA,2BAAA;;AAGD,WAAY;EACX,wBAAA;EACA,2BAAA;;AAGD,YAAa,MAAK;EACjB,wBAAA;EACA,2BAAA;;AAGD,YAAa,MAAK,KAAM;EACvB,kBAAA;;AAGD,YAAa;EACZ,wBAAA;;AAGD,KAAM;EACL,aAAA;;;AAID,IAAI;AAAQ,GAAG;EACd,cAAA;;AAGD,IAAI;EACH,8BAAA;;AAGD,IAAI,MAAM;EACT,gBAAA;;;AAID,QAAS;EACR,WAAA;EACA,kBAAA;;;AAID,SAAU,MAAM;AAAG,SAAU;EAC5B,gBAAA;;;AAID;EACC,eAAA;EAEA,2BAAA;;AAHD,KAKC;EACC,qBAAA;EACA,mBAAA;EACA,WAAA;EACA,iBAAA;EACA,SAAA;EACA,gBAAA;EACA,sBAAA;EACA,cAAA;;AAbF,KAgBC,EAAC;EACA,mBAAA;EACA,YAAA;;AAlBF,KAqBC,EAAC;EACA,gBAAA;;;AAKF;EACC,kBAAA;;AAGD,cAAc;AAAQ,aAAa;AAAQ,YAAY;EACtD,sBAAA;;AAGD;AAAgB;AAAe;EAC9B,sBAAA;;AAGD;EACC,2BAAA;;AAID,UAAW;EACV,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,2CAAA;EACA,aAAA;EACA,YAAA;;AAGD,UAAW,MAAK;EACf,UAAA;;AAID;EACC,gBAAA;EACA,wCAAA;EACA,0BAAA;EACA,wBAAA;EACA,YAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EACA,qBAAA;EACA,gBAAA;EACA,wBAAA","file":"@layout_popup.css"}
|
||||
45
EdgeUser/web/views/@default/@layout_popup.html
Normal file
45
EdgeUser/web/views/@default/@layout_popup.html
Normal file
@@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>{$ htmlEncode .teaTitle}控制台</title>
|
||||
<meta charset="UTF-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout_popup.css" media="all"/>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="/css/semantic.iframe.min.css?v=bRafhK" media="all"/>
|
||||
{$TEA.VUE}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout_override.css" media="all"/>
|
||||
{$echo "header"}
|
||||
<script type="text/javascript" src="/_/@default/@layout.js"></script>
|
||||
<script type="text/javascript" src="/js/components.js?v=v{$.teaVersion}"></script>
|
||||
<script type="text/javascript" src="/js/utils.min.js"></script>
|
||||
<script type="text/javascript" src="/js/sweetalert2/dist/sweetalert2.all.min.js"></script>
|
||||
<script type="text/javascript" src="/js/date.tea.js"></script>
|
||||
<style type="text/css">
|
||||
.main {
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
overflow-y: auto;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.main::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
window.IS_POPUP = true
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="main">
|
||||
<!-- 功能区 -->
|
||||
{$TEA.VIEW}
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
391
EdgeUser/web/views/@default/@layout_popup.less
Normal file
391
EdgeUser/web/views/@default/@layout_popup.less
Normal file
@@ -0,0 +1,391 @@
|
||||
/** 通用 **/
|
||||
* {
|
||||
scrollbar-color: rgba(0, 0, 0, 0.2) transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
a.disabled, a.disabled:hover, a.disabled:active, span.disabled {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
a.enabled, span.enabled, span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
|
||||
span.grey, label.grey, p.grey {
|
||||
color: grey !important;
|
||||
}
|
||||
|
||||
p.grey {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
span.red, pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
|
||||
pre:not(.CodeMirror-line) {
|
||||
font-family: Lato, 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
|
||||
}
|
||||
|
||||
tbody {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.table.width30 {
|
||||
width: 30em !important;
|
||||
}
|
||||
|
||||
.table.width35 {
|
||||
width: 35em !important;
|
||||
}
|
||||
|
||||
.table.width40 {
|
||||
width: 40em !important;
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
font-size: 0.9em !important;
|
||||
}
|
||||
|
||||
p.comment, div.comment {
|
||||
color: #959da6;
|
||||
padding-top: 0.4em;
|
||||
font-weight: normal;
|
||||
word-break: break-all;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
p.comment em, div.comment em {
|
||||
font-style: italic !important;
|
||||
}
|
||||
|
||||
.truncate {
|
||||
white-space: nowrap;
|
||||
-ms-text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
div.margin, p.margin {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
/** 操作按钮容器 **/
|
||||
.op.one {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.op.two {
|
||||
width: 7.4em;
|
||||
}
|
||||
|
||||
.op.three {
|
||||
width: 9em;
|
||||
}
|
||||
|
||||
.op.four {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
/** 扩展UI **/
|
||||
.field.text {
|
||||
padding: .5em;
|
||||
}
|
||||
|
||||
/** 右侧主操作区 **/
|
||||
.main {
|
||||
position: absolute;
|
||||
left: 22em;
|
||||
top: 5.6em;
|
||||
padding-bottom: 5em;
|
||||
padding-right: 1em;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.main {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
.main.without-menu {
|
||||
left: 9em;
|
||||
}
|
||||
|
||||
.main.without-secondary-menu {
|
||||
top: 2.9em;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.main.without-menu {
|
||||
left: 4em;
|
||||
}
|
||||
}
|
||||
|
||||
.main table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
.main table td.middle-title {
|
||||
width: 14em;
|
||||
}
|
||||
|
||||
.main table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.main table td.color-border {
|
||||
border-left: 1px #276ac6 solid !important;
|
||||
}
|
||||
|
||||
.main table td.vertical-top {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.main table td.vertical-middle {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.main table td[colspan="2"] a {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.main table td em {
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.main h3 {
|
||||
font-weight: normal;
|
||||
margin-top: 0.5em !important;
|
||||
}
|
||||
|
||||
.main h3 span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.main h3 span.label {
|
||||
color: #6435c9;
|
||||
}
|
||||
|
||||
.main h3 a {
|
||||
margin-left: 1em;
|
||||
font-size: 14px !important;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.main h3 a::before {
|
||||
content: "[";
|
||||
}
|
||||
|
||||
.main h3 a::after {
|
||||
content: "]";
|
||||
}
|
||||
|
||||
.main h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.main td span.small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
.main .button.mini {
|
||||
font-size: 0.8em;
|
||||
padding: 0.2em;
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
/** 右侧文本子菜单 **/
|
||||
.text.menu {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.text.menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
/** Vue **/
|
||||
[v-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/** auto complete **/
|
||||
.autocomplete-box .menu {
|
||||
background: #eee !important;
|
||||
}
|
||||
|
||||
.autocomplete-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.autocomplete-box .menu .item {
|
||||
border-top: none !important;
|
||||
}
|
||||
|
||||
select.auto-width {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/** column **/
|
||||
@media screen and (max-width: 512px) {
|
||||
.column:not(.one) {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
/** label **/
|
||||
label[for] {
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
label.blue {
|
||||
color: #2185d0 !important;
|
||||
}
|
||||
|
||||
span.blue {
|
||||
color: #4183c4;
|
||||
}
|
||||
|
||||
td .label.tiny {
|
||||
}
|
||||
|
||||
/** Menu **/
|
||||
.first-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.first-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.second-menu .menu.text {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.second-menu .menu.text em {
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.second-menu .divider {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.menu a {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/** var **/
|
||||
span.olive, var.olive {
|
||||
color: #b5cc18 !important;
|
||||
}
|
||||
|
||||
span.dash {
|
||||
border-bottom: 1px dashed grey;
|
||||
}
|
||||
|
||||
span.hover:hover {
|
||||
background: #eee;
|
||||
}
|
||||
|
||||
/** Message **/
|
||||
.message .gopher {
|
||||
width: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
/** checkbox **/
|
||||
.checkbox label a, .checkbox label {
|
||||
font-size: 0.8em !important;
|
||||
}
|
||||
|
||||
/** page **/
|
||||
.page {
|
||||
margin-top: 1em;
|
||||
|
||||
border-left: 1px solid #ddd;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
background: #fafafa;
|
||||
color: #666;
|
||||
padding: 6px 12px;
|
||||
margin: 0;
|
||||
font-size: 0.9em;
|
||||
border: 1px solid #ddd;
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
a.active {
|
||||
background: #2185d0 !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
background: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
/** popup **/
|
||||
.swal2-html-container {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.swal2-confirm:focus, .swal2-cancel:focus, .swal2-close:focus {
|
||||
border: 3px #ddd solid !important;
|
||||
}
|
||||
|
||||
.swal2-confirm, .swal2-cancel, .swal2-close {
|
||||
border: 3px #fff solid !important;
|
||||
}
|
||||
|
||||
.swal2-cancel {
|
||||
margin-left: 2em !important;
|
||||
}
|
||||
|
||||
// combo-box
|
||||
.combo-box .menu {
|
||||
max-height: 17em;
|
||||
overflow-y: auto;
|
||||
position: absolute;
|
||||
border: rgba(129, 177, 210, 0.81) 1px solid;
|
||||
border-top: 0;
|
||||
z-index: 100
|
||||
}
|
||||
|
||||
.combo-box .menu::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
// code-label
|
||||
code-label {
|
||||
background: #fff;
|
||||
border: 1px solid rgba(34, 36, 38, .15);
|
||||
color: rgba(0, 0, 0, .87);
|
||||
font-size: .71428571rem;
|
||||
padding: 3px;
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
line-height: 1;
|
||||
display: inline-block;
|
||||
font-weight: 700;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
112
EdgeUser/web/views/@default/@left_menu.css
Normal file
112
EdgeUser/web/views/@default/@left_menu.css
Normal file
@@ -0,0 +1,112 @@
|
||||
.left-box {
|
||||
width: 8em;
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 2.4em;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-right: 1px #ddd solid;
|
||||
}
|
||||
.left-box .menu {
|
||||
width: 90% !important;
|
||||
}
|
||||
.left-box .menu .item {
|
||||
line-height: 1.2;
|
||||
position: relative;
|
||||
padding-left: 1em !important;
|
||||
}
|
||||
.left-box .menu .item .icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -0.4em !important;
|
||||
}
|
||||
.left-box .menu .item .sub-name {
|
||||
font-size: 0.7em;
|
||||
font-style: normal;
|
||||
color: grey;
|
||||
}
|
||||
.left-box .menu .item.separator {
|
||||
border-bottom: 1px #eee solid !important;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.left-box .menu .item.on span {
|
||||
border-bottom: 1px #666 dashed;
|
||||
}
|
||||
.left-box .menu .item.off span var {
|
||||
font-style: normal;
|
||||
background: #db2828;
|
||||
color: white;
|
||||
font-size: 8px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
.left-box .menu .header {
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-left: 0 !important;
|
||||
padding-bottom: 1em !important;
|
||||
}
|
||||
.left-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.left-box.disabled {
|
||||
opacity: 0.1;
|
||||
}
|
||||
.left-box.tiny {
|
||||
top: 10.5em;
|
||||
}
|
||||
.left-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
.left-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
.left-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
.right-box {
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 1.3em;
|
||||
right: 0;
|
||||
left: 18em;
|
||||
padding-right: 2em;
|
||||
padding-bottom: 2em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.right-box {
|
||||
left: 13em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
body.expanded .right-box {
|
||||
left: 10em;
|
||||
}
|
||||
.right-box.tiny {
|
||||
top: 10.4em;
|
||||
left: 26.5em;
|
||||
}
|
||||
.right-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.right-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
.right-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
.right-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
.main.without-footer .left-box {
|
||||
bottom: 0.2em;
|
||||
}
|
||||
.narrow-scrollbar::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
/*# sourceMappingURL=@left_menu.css.map */
|
||||
1
EdgeUser/web/views/@default/@left_menu.css.map
Normal file
1
EdgeUser/web/views/@default/@left_menu.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["@left_menu.less"],"names":[],"mappings":"AAAA;EACC,UAAA;EACA,eAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,4BAAA;;AAPD,SASC;EACC,qBAAA;;AAVF,SASC,MAGC;EACC,gBAAA;EACA,kBAAA;EACA,4BAAA;;AAfH,SASC,MAGC,MAKC;EACC,kBAAA;EACA,QAAA;EACA,OAAA;EACA,kBAAA;;AArBJ,SASC,MAGC,MAYC;EACC,gBAAA;EACA,kBAAA;EACA,WAAA;;AA3BJ,SASC,MAsBC,MAAK;EACJ,6BAAA;EACA,cAAA;EACA,iBAAA;EACA,wBAAA;EACA,2BAAA;;AApCH,SASC,MA8BC,MAAK,GACJ;EACC,8BAAA;;AAzCJ,SASC,MAoCC,MAAK,IACJ,KACC;EACC,kBAAA;EACA,mBAAA;EACA,YAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,gBAAA;;AAtDL,SASC,MAmDC;EACC,6BAAA;EACA,0BAAA;EACA,8BAAA;;AAQH,SAAS;EACR,UAAA;;AAGD,SAAS;EACR,YAAA;;AAGD,SAAS;EACR,WAAA;;AAGD,SAAS;EACR,QAAA;;AAGD,SAAS;EACR,SAAA;;AAGD,SAAS;EACR,QAAA;;AAGD;EACC,eAAA;EACA,UAAA;EACA,aAAA;EACA,QAAA;EACA,UAAA;EACA,kBAAA;EACA,mBAAA;EACA,gBAAA;;AAGD,mBAAqC;EACpC;IACC,UAAA;IACA,kBAAA;;;AAIF,IAAI,SAAU;EACb,UAAA;;AAGD,UAAU;EACT,WAAA;EACA,YAAA;;AAGD,UAAU;EACT,UAAA;;AAGD,UAAU;EACT,QAAA;;AAGD,UAAU;EACT,SAAA;;AAGD,UAAU;EACT,QAAA;;AAID,KAAK,eAAgB;EACpB,aAAA;;AAID,iBAAiB;EAChB,UAAA","file":"@left_menu.css"}
|
||||
9
EdgeUser/web/views/@default/@left_menu.html
Normal file
9
EdgeUser/web/views/@default/@left_menu.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<div class="margin"></div>
|
||||
|
||||
<div class="left-box" :class="{disabled:leftMenuItemIsDisabled}">
|
||||
<div class="ui menu text blue vertical small">
|
||||
<a class="item" v-for="item in leftMenuItems" :href="item.url" :class="{active:item.isActive, separator:item.name == '-', on:item.isOn, off:item.isOff || item.isImportant, 'has-divider':item.hasDivider}" :style="item.isActive ? 'background: rgba(230, 230, 230, 0.35) !important; border-radius: 3px;' : ''">
|
||||
<span v-if="item.name != '-'"><i class="icon play tiny" :style="{'visibility':item.isActive ? 'visible' : 'hidden'}"></i>{{item.name}}<var v-if="item.isOff">关</var><var v-if="item.isImportant">开</var></span><var v-if="item.subName != null && item.subName.length > 0" class="sub-name"> ({{item.subName}})</var>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
155
EdgeUser/web/views/@default/@left_menu.less
Normal file
155
EdgeUser/web/views/@default/@left_menu.less
Normal file
@@ -0,0 +1,155 @@
|
||||
.left-box {
|
||||
width: 8.5em;
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 2.4em;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
border-right: 1px #ddd solid;
|
||||
|
||||
.menu {
|
||||
width: 95% !important;
|
||||
|
||||
.item {
|
||||
line-height: 1.2;
|
||||
position: relative;
|
||||
padding-left: 1em !important;
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
margin-top: -0.4em !important;
|
||||
}
|
||||
|
||||
.sub-name {
|
||||
font-size: 0.7em;
|
||||
font-style: normal;
|
||||
color: grey;
|
||||
}
|
||||
}
|
||||
|
||||
.item.separator {
|
||||
border-bottom: 1px #eee solid !important;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
|
||||
.item.on {
|
||||
span {
|
||||
border-bottom: 1px #666 dashed;
|
||||
}
|
||||
}
|
||||
|
||||
.item.off {
|
||||
span {
|
||||
var {
|
||||
font-style: normal;
|
||||
background: #db2828;
|
||||
color: white;
|
||||
font-size: 8px;
|
||||
padding: 2px;
|
||||
border-radius: 2px;
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单项底部虚线(参考 separator 的实现)
|
||||
.item.has-divider {
|
||||
border-bottom: 1px dashed #ddd !important;
|
||||
margin-bottom: 0.3em !important;
|
||||
}
|
||||
|
||||
// .header需要在.item下面
|
||||
.header {
|
||||
border-bottom: 1px #ddd solid;
|
||||
padding-left: 0 !important;
|
||||
padding-bottom: 1em !important;
|
||||
}
|
||||
|
||||
.item.active {
|
||||
background: rgba(230, 230, 230, 0.35) !important;
|
||||
border-radius: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.left-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.left-box.disabled {
|
||||
opacity: 0.1;
|
||||
}
|
||||
|
||||
.left-box.tiny {
|
||||
top: 10.5em;
|
||||
}
|
||||
|
||||
.left-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
|
||||
.left-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
|
||||
.left-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
|
||||
.right-box {
|
||||
position: fixed;
|
||||
top: 7.5em;
|
||||
bottom: 1.3em;
|
||||
right: 0;
|
||||
left: 18em;
|
||||
padding-right: 2em;
|
||||
padding-bottom: 2em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.right-box {
|
||||
left: 13em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
body.expanded .right-box {
|
||||
left: 10em;
|
||||
}
|
||||
|
||||
.right-box.tiny {
|
||||
top: 10.4em;
|
||||
left: 26.5em;
|
||||
}
|
||||
|
||||
.right-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.right-box.without-tabbar {
|
||||
top: 3em;
|
||||
}
|
||||
|
||||
.right-box.with-menu {
|
||||
top: 10em;
|
||||
}
|
||||
|
||||
.right-box.without-menu {
|
||||
top: 6em;
|
||||
}
|
||||
|
||||
// main
|
||||
.main.without-footer .left-box {
|
||||
bottom: 0.2em;
|
||||
}
|
||||
|
||||
// scrollbar
|
||||
.narrow-scrollbar::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
9
EdgeUser/web/views/@default/@left_menu_top.html
Normal file
9
EdgeUser/web/views/@default/@left_menu_top.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<div class="margin"></div>
|
||||
|
||||
<div class="left-box without-tabbar" :class="{disabled:leftMenuItemIsDisabled}">
|
||||
<div class="ui menu text blue vertical small">
|
||||
<a class="item" v-for="item in leftMenuItems" :href="item.url" :class="{active:item.isActive, separator:item.name == '-', on:item.isOn, off:item.isOff}">
|
||||
<span v-if="item.name != '-'"><i class="icon play tiny" :style="{'visibility':item.isActive ? 'visible' : 'hidden'}"></i>{{item.name}}<var v-if="item.isOff">关</var></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
9
EdgeUser/web/views/@default/@left_menu_with_menu.html
Normal file
9
EdgeUser/web/views/@default/@left_menu_with_menu.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<div class="margin"></div>
|
||||
|
||||
<div class="left-box with-menu" :class="{disabled:leftMenuItemIsDisabled}">
|
||||
<div class="ui menu text blue vertical small">
|
||||
<a class="item" v-for="item in leftMenuItems" :href="item.url" :class="{active:item.isActive, separator:item.name == '-', on:item.isOn, off:item.isOff||item.isImportant}">
|
||||
<span v-if="item.name != '-'"><i class="icon play tiny" :style="{'visibility':item.isActive ? 'visible' : 'hidden'}"></i>{{item.name}}<var v-if="item.isOff">关</var><var v-if="item.isImportant">开</var><var v-if="item.subName != null && item.subName.length > 0" class="sub-name"> ({{item.subName}})</var></span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
1
EdgeUser/web/views/@default/@menu.html
Normal file
1
EdgeUser/web/views/@default/@menu.html
Normal file
@@ -0,0 +1 @@
|
||||
<!-- 预留的菜单位置 -->
|
||||
40
EdgeUser/web/views/@default/account/reset.css
Normal file
40
EdgeUser/web/views/@default/account/reset.css
Normal file
@@ -0,0 +1,40 @@
|
||||
@media screen and (min-width: 512px) {
|
||||
.form-box {
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
form {
|
||||
position: fixed;
|
||||
width: 30em;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -15em;
|
||||
margin-top: -16em;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 512px) {
|
||||
.form-box {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
p.comment,
|
||||
div.comment {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
padding-top: 0.4em;
|
||||
font-size: 1em;
|
||||
}
|
||||
span.red,
|
||||
pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
/*# sourceMappingURL=reset.css.map */
|
||||
1
EdgeUser/web/views/@default/account/reset.css.map
Normal file
1
EdgeUser/web/views/@default/account/reset.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["reset.less"],"names":[],"mappings":"AAAA,mBAAqC;EACpC;IACC,eAAA;IACA,UAAA;IACA,SAAA;IACA,OAAA;IACA,QAAA;;EAGD;IACC,eAAA;IACA,WAAA;IACA,QAAA;IACA,SAAA;IACA,kBAAA;IACA,iBAAA;;;AAIF,mBAAqC;EACpC;IACC,iBAAA;IACA,kBAAA;;;AAKF,KAAM,GAAE;EACP,WAAA;;AAGD,KAAM;EACL,mBAAA;;AAGD,CAAC;AAAU,GAAG;EACb,yBAAA;EACA,kBAAA;EACA,cAAA;;AAGD,IAAI;AAAM,GAAG;EACZ,cAAA","file":"reset.css"}
|
||||
69
EdgeUser/web/views/@default/account/reset.html
Normal file
69
EdgeUser/web/views/@default/account/reset.html
Normal file
@@ -0,0 +1,69 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
{$if eq .faviconFileId 0}
|
||||
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||
{$else}
|
||||
<link rel="shortcut icon" href="/ui/image/{$ .faviconFileId}"/>
|
||||
{$end}
|
||||
<title>找回密码 - {$ htmlEncode .systemName}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
{$TEA.VUE}
|
||||
{$TEA.SEMANTIC}
|
||||
<link rel="stylesheet" type="text/css" href="/_/@default/@layout_override.css" media="all"/>
|
||||
<script type="text/javascript" src="/js/md5.min.js"></script>
|
||||
<script type="text/javascript" src="/js/utils.min.js"></script>
|
||||
<script type="text/javascript" src="/js/sweetalert2/dist/sweetalert2.all.min.js"></script>
|
||||
<script type="text/javascript" src="/js/components.js?v=1.0.0"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{$template "/menu"}
|
||||
|
||||
<div class="form-box">
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success" data-tea-before="before">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="action" v-model="action"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr v-show="!isSent">
|
||||
<td class="title">用户名或邮箱 *</td>
|
||||
<td>
|
||||
<input type="text" name="usernameOrEmail" placeholder="用户名、邮箱" ref="focus" v-model="nameOrEmail"/>
|
||||
<p class="comment">请输入你的用户名或者已经绑定的邮箱。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tbody v-show="isSent">
|
||||
<tr>
|
||||
<td class="title">用户名或邮箱</td>
|
||||
<td>{{nameOrEmail}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>验证码 *</td>
|
||||
<td>
|
||||
<input type="text" name="code" style="width: 6em" maxlength="6" ref="verifyCodeInput"/>
|
||||
<p class="comment"><span class="red">6位数字验证码已经发送到邮箱{{email}},请查收。</span></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>新登录密码 *</td>
|
||||
<td>
|
||||
<input type="password" name="newPass" maxlength="100"/>
|
||||
<p class="comment">长度不小于6位<span v-if="complexPassword">,且必须包含大写字母和小写字母</span>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>确认新登录密码 *</td>
|
||||
<td>
|
||||
<input type="password" name="newPass2" maxlength="100"/>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<submit-btn v-show="!isSent">下一步</submit-btn>
|
||||
<submit-btn v-show="isSent">保存新密码</submit-btn>
|
||||
<a href="/login">回登录页</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
32
EdgeUser/web/views/@default/account/reset.js
Normal file
32
EdgeUser/web/views/@default/account/reset.js
Normal file
@@ -0,0 +1,32 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
let input = this.$refs.focus
|
||||
if (input != null) {
|
||||
input.focus()
|
||||
}
|
||||
})
|
||||
|
||||
this.nameOrEmail = ""
|
||||
this.isSent = false
|
||||
this.email = ""
|
||||
this.action = "send"
|
||||
|
||||
this.before = function () {
|
||||
|
||||
}
|
||||
|
||||
this.success = function (resp) {
|
||||
if (this.action == "send") {
|
||||
this.isSent = true
|
||||
this.action = "update"
|
||||
this.email = resp.data.email
|
||||
this.$delay(function () {
|
||||
this.$refs.verifyCodeInput.focus()
|
||||
})
|
||||
} else if (this.action == "update") {
|
||||
teaweb.success("你已成功设置了新密码,现在去登录", function () {
|
||||
window.location = "/"
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
44
EdgeUser/web/views/@default/account/reset.less
Normal file
44
EdgeUser/web/views/@default/account/reset.less
Normal file
@@ -0,0 +1,44 @@
|
||||
@media screen and (min-width: 512px) {
|
||||
.form-box {
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
position: fixed;
|
||||
width: 30em;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -15em;
|
||||
margin-top: -16em;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 512px) {
|
||||
.form-box {
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table td.title {
|
||||
width: 10em;
|
||||
}
|
||||
|
||||
table td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
p.comment, div.comment {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
padding-top: 0.4em;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
span.red, pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
19
EdgeUser/web/views/@default/acl/accesskeys/createPopup.html
Normal file
19
EdgeUser/web/views/@default/acl/accesskeys/createPopup.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>创建AccessKey</h3>
|
||||
|
||||
<form class="ui form" method="post" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">备注 *</td>
|
||||
<td>
|
||||
<textarea rows="2" name="description" maxlength="100" ref="focus"></textarea>
|
||||
<p class="comment">描述AccessKey的用途等。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
35
EdgeUser/web/views/@default/acl/accesskeys/index.html
Normal file
35
EdgeUser/web/views/@default/acl/accesskeys/index.html
Normal file
@@ -0,0 +1,35 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item @click.prevent="createAccessKey()">创建AccessKey</menu-item>
|
||||
<span class="item"><tip-icon content="AccessKey可以用来访问API接口。"></tip-icon></span>
|
||||
</first-menu>
|
||||
|
||||
<h4>AccessKey管理</h4>
|
||||
<p class="comment" v-if="accessKeys.length == 0">暂时还没有AccessKey。</p>
|
||||
|
||||
<table class="ui table selectable" v-if="accessKeys.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>AccessKey ID</th>
|
||||
<th>AccessKey密钥</th>
|
||||
<th>备注</th>
|
||||
<th>状态</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="accessKey in accessKeys">
|
||||
<td>{{accessKey.uniqueId}}</td>
|
||||
<td>{{accessKey.secret}}</td>
|
||||
<td>{{accessKey.description}}</td>
|
||||
<td>
|
||||
<span v-if="accessKey.isOn" class="green">已启用</span>
|
||||
<span v-else class="disabled">已禁用</span>
|
||||
</td>
|
||||
<td>
|
||||
<a href="" v-if="accessKey.isOn" @click.prevent="updateAccessKeyIsOn(accessKey.id, false)">禁用</a>
|
||||
<a href="" v-if="!accessKey.isOn" @click.prevent="updateAccessKeyIsOn(accessKey.id, true)">启用</a>
|
||||
<a href="" @click.prevent="deleteAccessKey(accessKey.id)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
41
EdgeUser/web/views/@default/acl/accesskeys/index.js
Normal file
41
EdgeUser/web/views/@default/acl/accesskeys/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
Tea.context(function () {
|
||||
this.createAccessKey = function () {
|
||||
teaweb.popup("/acl/accesskeys/createPopup", {
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.updateAccessKeyIsOn = function (accessKeyId, isOn) {
|
||||
let that = this
|
||||
|
||||
let message = ""
|
||||
if (isOn) {
|
||||
message = "确定要启用此AccessKey吗?"
|
||||
} else {
|
||||
message = "确定要禁用此AccessKey吗?"
|
||||
}
|
||||
teaweb.confirm(message, function () {
|
||||
that.$post(".updateIsOn")
|
||||
.params({
|
||||
accessKeyId: accessKeyId,
|
||||
isOn: isOn ? 1 : 0
|
||||
})
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteAccessKey = function (accessKeyId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此AccessKey吗?", function () {
|
||||
that.$post(".delete")
|
||||
.params({
|
||||
accessKeyId: accessKeyId
|
||||
})
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
})
|
||||
64
EdgeUser/web/views/@default/anti-ddos/instances/index.html
Normal file
64
EdgeUser/web/views/@default/anti-ddos/instances/index.html
Normal file
@@ -0,0 +1,64 @@
|
||||
{$layout}
|
||||
|
||||
<second-menu>
|
||||
<menu-item href="/anti-ddos/packages">[购买实例]</menu-item>
|
||||
</second-menu>
|
||||
|
||||
<p class="comment" v-if="userInstances.length == 0">暂时还没有实例,<a href="/anti-ddos/packages">[点此购买]</a> 。</p>
|
||||
|
||||
<div v-if="userInstances.length > 0">
|
||||
<table class="ui table selectable celled">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>高防产品</th>
|
||||
<th>高防IP</th>
|
||||
<th style="width: 7em">有效期</th>
|
||||
<th style="width: 7em">开始日期</th>
|
||||
<th style="width: 7em">结束日期</th>
|
||||
<th class="width6">防护对象</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="userInstance in userInstances">
|
||||
<td>
|
||||
<span v-if="userInstance.package.id > 0">{{userInstance.package.summary}}</span>
|
||||
<span v-else class="red">已删除</span>
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="userInstance.ipAddresses != null && userInstance.ipAddresses.length > 0">
|
||||
<div v-for="ip in userInstance.ipAddresses">
|
||||
{{ip}}
|
||||
</div>
|
||||
</div>
|
||||
<span v-else class="red">无有效IP</span>
|
||||
</td>
|
||||
<td>{{userInstance.periodCount}}{{userInstance.periodUnitName}}</td>
|
||||
<td>{{userInstance.dayFrom}}</td>
|
||||
<td>{{userInstance.dayTo}}
|
||||
<div v-if="userInstance.isExpired">
|
||||
<span v-if="userInstance.isExpired" class="small red">已过期</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<!-- 防护对象 -->
|
||||
<a href="" v-if="userInstance.isAvailable" @click.prevent="updateObjectsPopup(userInstance.id)">
|
||||
<span v-if="userInstance.countObjects > 0">{{userInstance.countObjects}}个对象</span>
|
||||
<span v-else>设置</span>
|
||||
</a>
|
||||
<span v-else class="disabled">{{userInstance.countObjects}}</span>
|
||||
|
||||
</td>
|
||||
<td>
|
||||
<!-- 续费 -->
|
||||
<span v-if="userInstance.instance.userInstanceId == userInstance.id"><a :href="'/anti-ddos/instances/renew?userInstanceId=' + userInstance.id">续费</a></span>
|
||||
<span v-else class="disabled">续费</span>
|
||||
|
||||
<!-- 删除 -->
|
||||
<a href="" v-if="userInstance.canDelete" @click.prevent="deleteUserInstance(userInstance.id)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<page-box></page-box>
|
||||
</div>
|
||||
|
||||
33
EdgeUser/web/views/@default/anti-ddos/instances/index.js
Normal file
33
EdgeUser/web/views/@default/anti-ddos/instances/index.js
Normal file
@@ -0,0 +1,33 @@
|
||||
Tea.context(function () {
|
||||
this.renewUserInstance = function (userInstanceId) {
|
||||
teaweb.popup(".renewPopup?userInstanceId=" + userInstanceId, {
|
||||
height: "26em",
|
||||
callback: function () {
|
||||
teaweb.successRefresh("续期成功")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.updateObjectsPopup = function (userInstanceId) {
|
||||
teaweb.popup(".updateObjectsPopup?userInstanceId=" + userInstanceId, {
|
||||
width: "60em",
|
||||
height: "40em",
|
||||
callback: function () {
|
||||
teaweb.successRefresh("保存成功")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteUserInstance = function (userInstanceId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除此实例吗?", function () {
|
||||
that.$post(".delete")
|
||||
.params({
|
||||
userInstanceId: userInstanceId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.successRefresh("删除成功")
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
62
EdgeUser/web/views/@default/anti-ddos/instances/renew.html
Normal file
62
EdgeUser/web/views/@default/anti-ddos/instances/renew.html
Normal file
@@ -0,0 +1,62 @@
|
||||
{$layout}
|
||||
|
||||
<!-- 步骤 -->
|
||||
<div class="ui steps fluid">
|
||||
<div class="step active">
|
||||
<a href="/anti-ddos/instances">选择要续费的实例</a>
|
||||
</div>
|
||||
<div class="step">
|
||||
<strong>支付</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="userInstanceId" :value="userInstance.id"/>
|
||||
<input type="hidden" name="periodId" :value="selectedPeriodId"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td>高防产品</td>
|
||||
<td>
|
||||
<div v-if="userInstance.package.id > 0">{{userInstance.package.summary}}</div>
|
||||
<span v-else class="red">已删除</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>高防IP</td>
|
||||
<td>
|
||||
<div v-if="userInstance.instance.id > 0">
|
||||
<div v-for="ip in userInstance.instance.ipAddresses">{{ip}}</div>
|
||||
</div>
|
||||
<span v-else class="red">已删除</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>当前有效期</td>
|
||||
<td>{{userInstance.dayTo}}
|
||||
<p class="comment" v-if="userInstance.isExpired">
|
||||
<span class="red">已过期,续费后新的有效期将会从今天({{userInstance.today}})开始。</span>
|
||||
</p>
|
||||
<p class="comment" v-else>续费后,将会在此基础上增加新的有效期。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>新续有效期 *</td>
|
||||
<td>
|
||||
<div v-if="allPeriods.length > 0">
|
||||
<a v-for="period in allPeriods" class="ui label basic" :class="{blue: period.id == selectedPeriodId}" @click.prevent="selectPeriod(period.id)">{{period.count}}{{period.unitName}}</a>
|
||||
</div>
|
||||
<span v-else class="red">没有可用的有效期</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>价格</td>
|
||||
<td>
|
||||
<span v-if="amount == 0" class="disabled">没有找到对应价格</span>
|
||||
<span v-if="amount > 0">{{amount}}元</span>
|
||||
<p class="comment">管理员操作时,此价格仅供展示,并不会从用户账户中扣款。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button class="ui button primary" type="button" @click.prevent="goNext()" v-if="amount > 0">下一步</button>
|
||||
</form>
|
||||
29
EdgeUser/web/views/@default/anti-ddos/instances/renew.js
Normal file
29
EdgeUser/web/views/@default/anti-ddos/instances/renew.js
Normal file
@@ -0,0 +1,29 @@
|
||||
Tea.context(function () {
|
||||
this.selectedPeriodId = 0
|
||||
this.amount = -1
|
||||
|
||||
this.$delay(function () {
|
||||
if (this.userInstance.periodId > 0) {
|
||||
let that = this
|
||||
if (this.allPeriods.$find(function (k, v) {
|
||||
return that.userInstance.periodId == v.id
|
||||
}) != null) {
|
||||
this.selectPeriod(this.userInstance.periodId)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.selectPeriod = function (periodId) {
|
||||
this.selectedPeriodId = periodId
|
||||
|
||||
this.amount = this.prices.$find(function (k, v) {
|
||||
return v.periodId == periodId
|
||||
}).price
|
||||
}
|
||||
|
||||
this.goNext = function () {
|
||||
if (this.userInstance.id > 0 && this.selectedPeriodId > 0) {
|
||||
window.location = "/anti-ddos/instances/renewConfirm?userInstanceId=" + this.userInstance.id + "&periodId=" + this.selectedPeriodId
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,37 @@
|
||||
{$layout}
|
||||
|
||||
<!-- 步骤 -->
|
||||
<div class="ui steps fluid">
|
||||
<div class="step">
|
||||
<a href="/anti-ddos/instances">选择要续费的实例</a>
|
||||
</div>
|
||||
<div class="step active">
|
||||
<strong>支付</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<input type="hidden" name="userInstanceId" :value="userInstanceId"/>
|
||||
<input type="hidden" name="periodId" :value="periodId"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">高防实例</td>
|
||||
<td>[{{packageSummary}} / <span v-for="(ipAddr, index) in ipAddresses">{{ipAddr}}<span v-if="index != ipAddresses.length -1">,</span></span> / 当前有效期至{{dayTo}} / 新增{{periodName}}]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>价格</td>
|
||||
<td>¥{{amount}}元</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支付方式</td>
|
||||
<td>
|
||||
<pay-method-selector></pay-method-selector>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn v-show="amount > 0">确定购买</submit-btn><span class="red" v-if="amount == 0">参数错误,请返回重新选择。</span> <a href="/anti-ddos/packages">上一步</a>
|
||||
</form>
|
||||
@@ -0,0 +1,23 @@
|
||||
Tea.context(function () {
|
||||
this.goBack = function () {
|
||||
window.history.back()
|
||||
}
|
||||
|
||||
this.success = function (resp) {
|
||||
if (resp.data.success) {
|
||||
teaweb.success("实例续费成功", function () {
|
||||
window.location = "/anti-ddos/instances"
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (resp.data.orderCode.length > 0) {
|
||||
window.location = "/finance/pay?code=" + resp.data.orderCode + "&from=" + window.escape(window.location.toString()) + "&returnURL=/anti-ddos/instances"
|
||||
}
|
||||
}
|
||||
|
||||
this.methodCode = "@balance"
|
||||
this.changePayMethod = function (methodCode) {
|
||||
this.methodCode = methodCode
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,38 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>设置防护对象</h3>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="userInstanceId" :value="userInstance.id"/>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">高防产品</td>
|
||||
<td>
|
||||
<div v-if="userInstance.package.id > 0">{{userInstance.package.summary}}</div>
|
||||
<span v-else class="red">已删除</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>高防IP</td>
|
||||
<td>
|
||||
<div v-if="userInstance.instance.id > 0">
|
||||
<div v-for="ip in userInstance.instance.ipAddresses">{{ip}}</div>
|
||||
</div>
|
||||
<span v-else class="red">已删除</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>防护对象</td>
|
||||
<td>
|
||||
<div v-if="userInstance.isAvailable && userInstance.user.id > 0">
|
||||
<ad-instance-objects-box :v-objects="userInstance.objects" :v-user-id="userInstance.user.id"></ad-instance-objects-box>
|
||||
</div>
|
||||
<span v-else class="red">实例已经失效,无法设置防护对象</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn v-show="userInstance.isAvailable && userInstance.user.id > 0"></submit-btn>
|
||||
</form>
|
||||
38
EdgeUser/web/views/@default/anti-ddos/packages/confirm.html
Normal file
38
EdgeUser/web/views/@default/anti-ddos/packages/confirm.html
Normal file
@@ -0,0 +1,38 @@
|
||||
{$layout}
|
||||
|
||||
<!-- 步骤 -->
|
||||
<div class="ui steps fluid">
|
||||
<div class="step">
|
||||
<a href="/anti-ddos/packages">选择实例规格</a>
|
||||
</div>
|
||||
<div class="step active">
|
||||
<strong>支付</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<input type="hidden" name="packageId" :value="packageId"/>
|
||||
<input type="hidden" name="periodId" :value="periodId"/>
|
||||
<input type="hidden" name="count" :value="count"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">高防实例</td>
|
||||
<td>[{{packageSummary}} / {{periodName}}] x {{count}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>价格</td>
|
||||
<td>¥{{amount}}元</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>支付方式</td>
|
||||
<td>
|
||||
<pay-method-selector></pay-method-selector>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn v-show="amount > 0">确定购买</submit-btn><span class="red" v-if="amount == 0">参数错误,请返回重新选择。</span> <a href="/anti-ddos/packages">上一步</a>
|
||||
</form>
|
||||
23
EdgeUser/web/views/@default/anti-ddos/packages/confirm.js
Normal file
23
EdgeUser/web/views/@default/anti-ddos/packages/confirm.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Tea.context(function () {
|
||||
this.goBack = function () {
|
||||
window.history.back()
|
||||
}
|
||||
|
||||
this.success = function (resp) {
|
||||
if (resp.data.success) {
|
||||
teaweb.success("实例购买成功", function () {
|
||||
window.location = "/anti-ddos/instances"
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (resp.data.orderCode.length > 0) {
|
||||
window.location = "/finance/pay?code=" + resp.data.orderCode + "&from=" + window.escape(window.location.toString()) + "&returnURL=/anti-ddos/instances"
|
||||
}
|
||||
}
|
||||
|
||||
this.methodCode = "@balance"
|
||||
this.changePayMethod = function (methodCode) {
|
||||
this.methodCode = methodCode
|
||||
}
|
||||
})
|
||||
62
EdgeUser/web/views/@default/anti-ddos/packages/index.html
Normal file
62
EdgeUser/web/views/@default/anti-ddos/packages/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
{$layout}
|
||||
|
||||
<!-- 步骤 -->
|
||||
<div class="ui steps fluid">
|
||||
<div class="step active">
|
||||
<a href="/anti-ddos/packages">选择实例规格</a>
|
||||
</div>
|
||||
<div class="step">支付</div>
|
||||
</div>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<input type="hidden" name="packageId" :value="selectedPackageId"/>
|
||||
<input type="hidden" name="periodId" :value="selectedPeriodId"/>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">选择线路 *</td>
|
||||
<td>
|
||||
<a v-for="network in allNetworks" class="ui label basic" :class="{blue: network.id == selectedNetworkId}" @click.prevent="selectNetwork(network.id)">{{network.name}}</a>
|
||||
<p class="comment" v-for="network in allNetworks" v-if="network.id == selectedNetworkId && network.description.length > 0">{{network.name}}:{{network.description}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>选择防护带宽 *</td>
|
||||
<td>
|
||||
<a v-for="protectionBandwidth in allProtectionBandwidthSizes" v-if="hasProtectionBandwidth(protectionBandwidth)" class="ui label basic" :class="{blue: protectionBandwidth == selectedProtectionBandwidth}" @click.prevent="selectProtectionBandwidth(protectionBandwidth)">{{protectionBandwidth}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>选择业务带宽 *</td>
|
||||
<td>
|
||||
<a v-for="serverBandwidth in allServerBandwidthSizes" v-if="hasServerBandwidth(serverBandwidth)" class="ui label basic" :class="{blue: serverBandwidth == selectedServerBandwidth}" @click.prevent="selectServerBandwidth(serverBandwidth)">{{serverBandwidth}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>选择有效期 *</td>
|
||||
<td>
|
||||
<a v-for="period in allPeriods" class="ui label basic" v-if="hasPeriod(period.id)" :class="{blue: period.id == selectedPeriodId}" @click.prevent="selectPeriod(period.id)">{{period.count}}{{period.unitName}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>选择实例数量 *</td>
|
||||
<td>
|
||||
<div class="ui input">
|
||||
<select class="ui dropdown" name="count" v-model="count" @change="changeCount(this.count)">
|
||||
<option v-for="i in max" :value="i">{{i}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>价格</td>
|
||||
<td>
|
||||
<span v-if="amount == 0" class="disabled">没有找到对应价格</span>
|
||||
<span v-if="amount > 0">{{amount}}元</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<button class="ui button primary" type="button" :class="{disabled: amount <= 0}" @click.prevent="goNext()">下一步</button>
|
||||
</form>
|
||||
219
EdgeUser/web/views/@default/anti-ddos/packages/index.js
Normal file
219
EdgeUser/web/views/@default/anti-ddos/packages/index.js
Normal file
@@ -0,0 +1,219 @@
|
||||
Tea.context(function () {
|
||||
this.selectedNetworkId = 0
|
||||
this.selectedProtectionBandwidth = ""
|
||||
this.selectedServerBandwidth = ""
|
||||
this.selectedPackageId = 0
|
||||
this.selectedPeriodId = 0
|
||||
this.amount = -1
|
||||
this.max = 1
|
||||
this.count = 1
|
||||
this.selectedPrice = null
|
||||
|
||||
this.$delay(function () {
|
||||
if (this.allNetworks.length > 0) {
|
||||
this.selectNetwork(this.allNetworks[0].id)
|
||||
}
|
||||
})
|
||||
|
||||
this.selectNetwork = function (networkId) {
|
||||
this.selectedNetworkId = networkId
|
||||
this.selectedProtectionBandwidth = ""
|
||||
this.selectedServerBandwidth = ""
|
||||
this.selectedPeriodId = 0
|
||||
this.amount = -1
|
||||
|
||||
// 选择第一个防护带宽
|
||||
let that = this
|
||||
let found = false
|
||||
this.prices.sort(function (v1, v2) {
|
||||
return that.compareBits(v1.protectionBandwidth, v2.protectionBandwidth)
|
||||
}).forEach(function (v) {
|
||||
if (!found && v.networkId == that.selectedNetworkId) {
|
||||
that.selectProtectionBandwidth(v.protectionBandwidth)
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.selectProtectionBandwidth = function (protectionBandwidth) {
|
||||
this.selectedProtectionBandwidth = protectionBandwidth
|
||||
this.selectedServerBandwidth = ""
|
||||
this.selectedPeriodId = 0
|
||||
this.amount = -1
|
||||
|
||||
// 选择第一个业务带宽
|
||||
let that = this
|
||||
let found = false
|
||||
this.prices.sort(function (v1, v2) {
|
||||
return that.compareBits(v1.serverBandwidth, v2.serverBandwidth)
|
||||
}).forEach(function (v) {
|
||||
if (!found && v.networkId == that.selectedNetworkId && v.protectionBandwidth == protectionBandwidth) {
|
||||
that.selectServerBandwidth(v.serverBandwidth)
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.selectServerBandwidth = function (serverBandwidth) {
|
||||
this.selectedServerBandwidth = serverBandwidth
|
||||
this.selectedPeriodId = 0
|
||||
this.amount = -1
|
||||
|
||||
// 选择第一个有效期
|
||||
let that = this
|
||||
let found = false
|
||||
|
||||
this.prices.sort(function (v1, v2) {
|
||||
let periodId1 = v1.periodId
|
||||
let periodId2 = v2.periodId
|
||||
return (that.toPeriodMonths(that.findPeriodWithId(periodId1)) > that.toPeriodMonths(that.findPeriodWithId(periodId2))) ? 1 : -1
|
||||
}).forEach(function (v) {
|
||||
if (!found && v.networkId == that.selectedNetworkId && v.protectionBandwidth == that.selectedProtectionBandwidth && v.serverBandwidth == serverBandwidth) {
|
||||
that.selectPeriod(v.periodId)
|
||||
found = true
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.selectPeriod = function (periodId) {
|
||||
this.selectedPeriodId = periodId
|
||||
|
||||
let price = null
|
||||
let found = false
|
||||
let that = this
|
||||
this.prices.forEach(function (v) {
|
||||
if (!found && v.networkId == that.selectedNetworkId
|
||||
&& v.protectionBandwidth == that.selectedProtectionBandwidth
|
||||
&& v.serverBandwidth == that.selectedServerBandwidth
|
||||
&& v.periodId == that.selectedPeriodId) {
|
||||
price = v
|
||||
found = true
|
||||
}
|
||||
})
|
||||
if (price == null) {
|
||||
teaweb.warn("数据错误,请刷新页面后重试,如果仍然没有恢复,请联系管理员。")
|
||||
return
|
||||
}
|
||||
|
||||
this.selectedPrice = price
|
||||
|
||||
this.selectedPackageId = price.packageId
|
||||
this.count = 1
|
||||
this.max = price.maxInstances
|
||||
this.changeCount(this.count)
|
||||
}
|
||||
|
||||
this.hasProtectionBandwidth = function (protectionBandwidth) {
|
||||
if (this.prices == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let found = false
|
||||
let that = this
|
||||
this.prices.forEach(function (v) {
|
||||
if (v.networkId == that.selectedNetworkId && v.protectionBandwidth == protectionBandwidth) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
this.hasServerBandwidth = function (serverBandwidth) {
|
||||
if (this.prices == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let found = false
|
||||
let that = this
|
||||
this.prices.forEach(function (v) {
|
||||
if (v.networkId == that.selectedNetworkId
|
||||
&& v.protectionBandwidth == that.selectedProtectionBandwidth
|
||||
&& v.serverBandwidth == serverBandwidth) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
this.hasPeriod = function (periodId) {
|
||||
if (this.prices == null) {
|
||||
return
|
||||
}
|
||||
|
||||
let found = false
|
||||
let that = this
|
||||
this.prices.forEach(function (v) {
|
||||
if (v.networkId == that.selectedNetworkId
|
||||
&& v.protectionBandwidth == that.selectedProtectionBandwidth
|
||||
&& v.serverBandwidth == that.selectedServerBandwidth
|
||||
&& v.periodId == periodId) {
|
||||
found = true
|
||||
}
|
||||
})
|
||||
return found
|
||||
}
|
||||
|
||||
this.changeCount = function () {
|
||||
if (this.selectedPrice == null) {
|
||||
this.amount = -1
|
||||
return
|
||||
}
|
||||
this.amount = this.selectedPrice.price * this.count
|
||||
|
||||
// 从服务器获取最新价格
|
||||
this.$post(".price")
|
||||
.params({
|
||||
packageId: this.selectedPackageId,
|
||||
periodId: this.selectedPeriodId,
|
||||
count: this.count
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.amount = resp.data.amount
|
||||
})
|
||||
}
|
||||
|
||||
this.goNext = function () {
|
||||
if (this.selectedPackageId > 0 && this.selectedPeriodId > 0 && this.count > 0 && this.amount > 0) {
|
||||
window.location = "/anti-ddos/packages/confirm?packageId=" + this.selectedPackageId + "&periodId=" + this.selectedPeriodId + "&count=" + this.count
|
||||
}
|
||||
}
|
||||
|
||||
this.toBits = function (b) {
|
||||
let m = b.match(/^(\d+)(\w+)$/)
|
||||
let n = parseInt(m[1])
|
||||
switch (m[2]) {
|
||||
case "bps":
|
||||
return n
|
||||
case "Kbps":
|
||||
return n * 1024
|
||||
case "Mbps":
|
||||
return n * Math.pow(1024, 2)
|
||||
case "Gbps":
|
||||
return n * Math.pow(1024, 3)
|
||||
case "Tbps":
|
||||
return n * Math.pow(1024, 4)
|
||||
case "Pbps":
|
||||
return n * Math.pow(1024, 5)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
this.compareBits = function (b1, b2) {
|
||||
return (this.toBits(b1) > this.toBits(b2)) ? 1 : -1
|
||||
}
|
||||
|
||||
this.findPeriodWithId = function (periodId) {
|
||||
return this.allPeriods.$find(function (k, v) {
|
||||
return v.id == periodId
|
||||
})
|
||||
}
|
||||
|
||||
this.toPeriodMonths = function (period) {
|
||||
switch (period.unit) {
|
||||
case "year":
|
||||
return period.count * 12
|
||||
default:
|
||||
return period.count
|
||||
}
|
||||
}
|
||||
})
|
||||
4
EdgeUser/web/views/@default/dashboard/index.css
Normal file
4
EdgeUser/web/views/@default/dashboard/index.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.chart-box {
|
||||
height: 20em;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
1
EdgeUser/web/views/@default/dashboard/index.css.map
Normal file
1
EdgeUser/web/views/@default/dashboard/index.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,YAAA","file":"index.css"}
|
||||
52
EdgeUser/web/views/@default/dashboard/index.html
Normal file
52
EdgeUser/web/views/@default/dashboard/index.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{$layout}
|
||||
{$template "/echarts"}
|
||||
|
||||
<p class="ui message warning" v-if="emailVerificationMessage.length > 0"><a href="/settings/email-verify">{{emailVerificationMessage}}</a></p>
|
||||
<p class="ui message warning" v-if="mobileVerificationMessage.length > 0"><a href="/settings/mobile-verify">{{mobileVerificationMessage}}</a></p>
|
||||
<p class="ui message warning" v-if="!isVerified">您的账号正在审核中,请耐心等待完成,暂时不能使用相关功能。</p>
|
||||
<p class="ui message warning" v-if="!isIdentified"><a href="/settings/identity">实名认证</a>后才能使用相关功能。</p>
|
||||
|
||||
<div class="ui message loading" v-if="isLoading">
|
||||
<div class="ui active inline loader small"></div> 数据加载中...
|
||||
</div>
|
||||
|
||||
<columns-grid class="ui columns grid counter-chart" :class="{'three columns': !uiConfig.showTrafficCharts || !uiConfig.showBandwidthCharts, 'four columns': uiConfig.showTrafficCharts && uiConfig.showBandwidthCharts }" v-if="!isLoading">
|
||||
<div class="ui column">
|
||||
<h4>加速网站数量</h4>
|
||||
<div class="value"><span>{{dashboard.countServers}}</span>个</div>
|
||||
</div>
|
||||
|
||||
<div class="ui column" v-if="uiConfig.showTrafficCharts">
|
||||
<h4>本月总流量</h4>
|
||||
<div class="value"><span>{{dashboard.monthlyTrafficBytes}}</span>{{dashboard.monthlyTrafficBytesUnit}}</div>
|
||||
</div>
|
||||
|
||||
<div class="ui column" v-if="uiConfig.showBandwidthCharts">
|
||||
<h4>本月带宽峰值</h4>
|
||||
<div class="value"><span>{{dashboard.monthlyPeekBandwidthBytes}}</span>{{dashboard.monthlyPeekBandwidthBytesUnit}}</div>
|
||||
</div>
|
||||
|
||||
<div class="ui column with-border" v-if="uiConfig.showTrafficCharts">
|
||||
<h4>今日流量</h4>
|
||||
<div class="value"><span>{{dashboard.dailyTrafficBytes}}</span>{{dashboard.dailyTrafficBytesUnit}}</div>
|
||||
</div>
|
||||
|
||||
<div class="ui column with-border" v-if="uiConfig.showBandwidthCharts">
|
||||
<h4>今日带宽峰值</h4>
|
||||
<div class="value"><span>{{dashboard.dailyPeekBandwidthBytes}}</span>{{dashboard.dailyPeekBandwidthBytesUnit}}</div>
|
||||
</div>
|
||||
</columns-grid>
|
||||
|
||||
<div v-if="uiConfig.showTrafficCharts && !isLoading">
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<h4>近 30 日流量趋势 <span>(单位:字节)</span></h4>
|
||||
<div class="chart-box" id="daily-traffic-chart"></div>
|
||||
</div>
|
||||
|
||||
<div v-if="uiConfig.showBandwidthCharts && !isLoading">
|
||||
<div class="ui divider"></div>
|
||||
|
||||
<h4>近 30 日带宽趋势</h4>
|
||||
<div class="chart-box" id="daily-peek-bandwidth-chart"></div>
|
||||
</div>
|
||||
181
EdgeUser/web/views/@default/dashboard/index.js
Normal file
181
EdgeUser/web/views/@default/dashboard/index.js
Normal file
@@ -0,0 +1,181 @@
|
||||
Tea.context(function () {
|
||||
this.splitFormat = function (format) {
|
||||
let result = format.match(/^([0-9.]+)([a-zA-Z]+)$/)
|
||||
return [result[1], result[2]]
|
||||
}
|
||||
|
||||
this.isLoading = true
|
||||
|
||||
this.dashboard = {}
|
||||
|
||||
this.$delay(function () {
|
||||
this.$post("$")
|
||||
.success(function (resp) {
|
||||
this.isLoading = false
|
||||
|
||||
for (let k in resp.data) {
|
||||
this[k] = resp.data[k]
|
||||
}
|
||||
|
||||
let bandwidthUnit = this.uiConfig.bandwidthUnit
|
||||
if (bandwidthUnit == null || bandwidthUnit.length == 0) {
|
||||
bandwidthUnit = "bit"
|
||||
}
|
||||
if (bandwidthUnit == "bit") {
|
||||
this.dashboard.monthlyPeekBandwidthBytes = this.dashboard.monthlyPeekBandwidthBytes.replace("B", "b")
|
||||
this.dashboard.dailyPeekBandwidthBytes = this.dashboard.dailyPeekBandwidthBytes.replace("B", "b")
|
||||
}
|
||||
|
||||
{
|
||||
let pieces = this.splitFormat(this.dashboard.monthlyTrafficBytes)
|
||||
this.dashboard.monthlyTrafficBytes = pieces[0]
|
||||
this.dashboard.monthlyTrafficBytesUnit = pieces[1]
|
||||
}
|
||||
|
||||
{
|
||||
let pieces = this.splitFormat(this.dashboard.monthlyPeekBandwidthBytes)
|
||||
this.dashboard.monthlyPeekBandwidthBytes = pieces[0]
|
||||
this.dashboard.monthlyPeekBandwidthBytesUnit = pieces[1]
|
||||
}
|
||||
|
||||
{
|
||||
let pieces = this.splitFormat(this.dashboard.dailyTrafficBytes)
|
||||
this.dashboard.dailyTrafficBytes = pieces[0]
|
||||
this.dashboard.dailyTrafficBytesUnit = pieces[1]
|
||||
}
|
||||
|
||||
{
|
||||
let pieces = this.splitFormat(this.dashboard.dailyPeekBandwidthBytes)
|
||||
this.dashboard.dailyPeekBandwidthBytes = pieces[0]
|
||||
this.dashboard.dailyPeekBandwidthBytesUnit = pieces[1]
|
||||
}
|
||||
|
||||
this.$delay(function () {
|
||||
this.reloadDailyTrafficChart()
|
||||
this.reloadDailyPeekBandwidthChart()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
this.reloadDailyTrafficChart = function () {
|
||||
let bandwidthUnit = this.uiConfig.bandwidthUnit
|
||||
|
||||
if (!this.uiConfig.showTrafficCharts) {
|
||||
return
|
||||
}
|
||||
|
||||
let stats = this.dailyTrafficStats
|
||||
let hasCacheInfo = false
|
||||
let axis = teaweb.bytesAxis(stats, function (stat) {
|
||||
if (stat.cachedBytes != null) {
|
||||
hasCacheInfo = true
|
||||
}
|
||||
return stat.bytes
|
||||
})
|
||||
let series = []
|
||||
if (hasCacheInfo) {
|
||||
series = [
|
||||
{
|
||||
name: name,
|
||||
type: "line",
|
||||
data: stats.map(function (stat) {
|
||||
return stat.cachedBytes / axis.divider
|
||||
}),
|
||||
itemStyle: {
|
||||
color: "rgba(97,160,168,0.2)"
|
||||
},
|
||||
areaStyle: {
|
||||
//color: "#61A0A8"
|
||||
},
|
||||
smooth: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
teaweb.renderLineChart({
|
||||
id: "daily-traffic-chart",
|
||||
values: stats,
|
||||
axis: axis,
|
||||
x: function (stat) {
|
||||
return stat.day
|
||||
},
|
||||
value: function (stat) {
|
||||
return stat.bytes / axis.divider
|
||||
},
|
||||
tooltip: function (args, values) {
|
||||
let index = args.dataIndex
|
||||
|
||||
let hasCacheInfo = (stats[index].cachedBytes != null)
|
||||
let cachedRatio = 0
|
||||
if (hasCacheInfo) {
|
||||
cachedRatio = Math.round(stats[index].cachedBytes * 10000 / stats[index].bytes) / 100
|
||||
}
|
||||
|
||||
let tooltip = values[index].day + "<br/>流量:" + teaweb.formatBytes(values[index].bytes)
|
||||
if (hasCacheInfo) {
|
||||
tooltip += "<br/>缓存流量:" + teaweb.formatBytes(values[index].cachedBytes)
|
||||
tooltip += "<br/>缓存命中率:" + cachedRatio + "%"
|
||||
}
|
||||
return tooltip
|
||||
},
|
||||
series: series
|
||||
})
|
||||
}
|
||||
|
||||
this.reloadDailyPeekBandwidthChart = function () {
|
||||
let bandwidthUnit = this.uiConfig.bandwidthUnit
|
||||
|
||||
if (!this.uiConfig.showBandwidthCharts) {
|
||||
return
|
||||
}
|
||||
|
||||
let stats = this.dailyPeekBandwidthStats
|
||||
let axis = teaweb.bitsAxis(stats, function (stat) {
|
||||
let value = stat.bytes
|
||||
if (bandwidthUnit == "bit") {
|
||||
value *= 8
|
||||
}
|
||||
return value
|
||||
})
|
||||
teaweb.renderLineChart({
|
||||
id: "daily-peek-bandwidth-chart",
|
||||
values: stats,
|
||||
axis: axis,
|
||||
x: function (stat) {
|
||||
return stat.day
|
||||
},
|
||||
value: function (stat) {
|
||||
let value = stat.bytes
|
||||
if (bandwidthUnit == "bit") {
|
||||
value *= 8
|
||||
}
|
||||
return value / axis.divider
|
||||
},
|
||||
tooltip: function (args, values) {
|
||||
if (args.componentType == "markLine") {
|
||||
return args.name
|
||||
}
|
||||
let index = args.dataIndex
|
||||
let value = values[index].bytes
|
||||
if (bandwidthUnit == "bit") {
|
||||
value *= 8
|
||||
}
|
||||
return values[index].day + "<br/>峰值带宽:" + teaweb.formatBits(value)
|
||||
},
|
||||
left: 30,
|
||||
right: 40,
|
||||
markLine: {
|
||||
precision: 4,
|
||||
data: [{
|
||||
name: this.bandwidthPercentile + "th",
|
||||
yAxis: this.bandwidthPercentileBits / axis.divider
|
||||
}],
|
||||
symbol: "none",
|
||||
lineStyle: {
|
||||
color: teaweb.chartColor("red")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
3
EdgeUser/web/views/@default/dashboard/index.less
Normal file
3
EdgeUser/web/views/@default/dashboard/index.less
Normal file
@@ -0,0 +1,3 @@
|
||||
.chart-box {
|
||||
height: 20em;
|
||||
}
|
||||
9
EdgeUser/web/views/@default/dashboard/ns.css
Normal file
9
EdgeUser/web/views/@default/dashboard/ns.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.ui.message .icon {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1.8em;
|
||||
}
|
||||
.chart-box {
|
||||
height: 14em;
|
||||
}
|
||||
/*# sourceMappingURL=ns.css.map */
|
||||
1
EdgeUser/web/views/@default/dashboard/ns.css.map
Normal file
1
EdgeUser/web/views/@default/dashboard/ns.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["ns.less"],"names":[],"mappings":"AAAA,GAAG,QACF;EACC,kBAAA;EACA,UAAA;EACA,UAAA;;AAIF;EACC,YAAA","file":"ns.css"}
|
||||
29
EdgeUser/web/views/@default/dashboard/ns.html
Normal file
29
EdgeUser/web/views/@default/dashboard/ns.html
Normal file
@@ -0,0 +1,29 @@
|
||||
{$layout}
|
||||
{$template "/echarts"}
|
||||
|
||||
<div class="ui four columns grid counter-chart">
|
||||
<div class="ui column">
|
||||
<h4>域名<link-icon href="/ns/domains"></link-icon></h4>
|
||||
<div class="value"><span>{{board.countDomains}}</span>个</div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>记录<link-icon href="/ns/domains"></link-icon></h4>
|
||||
<div class="value"><span>{{board.countRecords}}</span>个</div>
|
||||
</div>
|
||||
<div class="ui column">
|
||||
<h4>线路<link-icon href="/ns/routes"></link-icon></h4>
|
||||
<div class="value"><span>{{board.countRoutes}}</span>个</div>
|
||||
</div>
|
||||
<div class="ui column with-border">
|
||||
<h4>套餐<link-icon href="/ns/plans"></link-icon></h4>
|
||||
<div class="value"><span>{{board.countNodes}}</span>
|
||||
<span v-if="board.planName.length > 0">{{board.planName}}</span>
|
||||
<span v-if="board.planName.length == 0">未购套餐</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 域名排行 -->
|
||||
<h4>域名访问排行 <span>(24小时)</span></h4>
|
||||
<div class="chart-box" id="top-domains-chart"></div>
|
||||
<div class="ui divider"></div>
|
||||
31
EdgeUser/web/views/@default/dashboard/ns.js
Normal file
31
EdgeUser/web/views/@default/dashboard/ns.js
Normal file
@@ -0,0 +1,31 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
this.reloadTopDomainsChart()
|
||||
})
|
||||
|
||||
// 域名排行
|
||||
this.reloadTopDomainsChart = function () {
|
||||
let that = this
|
||||
let axis = teaweb.countAxis(this.topDomainStats, function (v) {
|
||||
return v.countRequests
|
||||
})
|
||||
teaweb.renderBarChart({
|
||||
id: "top-domains-chart",
|
||||
name: "域名",
|
||||
values: this.topDomainStats,
|
||||
x: function (v) {
|
||||
return v.domainName
|
||||
},
|
||||
tooltip: function (args, stats) {
|
||||
return stats[args.dataIndex].domainName + "<br/>请求数:" + " " + teaweb.formatNumber(stats[args.dataIndex].countRequests) + "<br/>流量:" + teaweb.formatBytes(stats[args.dataIndex].bytes)
|
||||
},
|
||||
value: function (v) {
|
||||
return v.countRequests / axis.divider;
|
||||
},
|
||||
axis: axis,
|
||||
click: function (args, stats) {
|
||||
window.location = "/ns/domains/domain?domainId=" + stats[args.dataIndex].domainId
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
11
EdgeUser/web/views/@default/dashboard/ns.less
Normal file
11
EdgeUser/web/views/@default/dashboard/ns.less
Normal file
@@ -0,0 +1,11 @@
|
||||
.ui.message {
|
||||
.icon {
|
||||
position: absolute;
|
||||
right: 1em;
|
||||
top: 1.8em;
|
||||
}
|
||||
}
|
||||
|
||||
.chart-box {
|
||||
height: 14em;
|
||||
}
|
||||
209
EdgeUser/web/views/@default/dns/clusters/cluster.html
Normal file
209
EdgeUser/web/views/@default/dns/clusters/cluster.html
Normal file
@@ -0,0 +1,209 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<menu-item :href="'/dns'">所有集群</menu-item>
|
||||
<span class="item">|</span>
|
||||
<menu-item :href="'/dns/clusters/cluster?clusterId=' + cluster.id" active="true">{{cluster.name}}</menu-item>
|
||||
</first-menu>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">集群</td>
|
||||
<td><link-icon :href="'/clusters/cluster?clusterId=' + cluster.id">{{cluster.name}}</link-icon></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DNS子域名</td>
|
||||
<td>
|
||||
<span v-if="dnsInfo.domainName.length > 0"><var>{{dnsInfo.dnsName}}</var>.{{dnsInfo.domainName}}</span>
|
||||
<span v-else class="disabled">没有设置</span>
|
||||
|
||||
<a href="" @click.prevent="updateCluster(cluster.id)">[修改]</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>DNS服务商</td>
|
||||
<td>
|
||||
<div v-if="dnsInfo.providerName.length > 0">
|
||||
<link-icon :href="'/dns/providers/provider?providerId=' + dnsInfo.providerId">{{dnsInfo.providerTypeName}} - {{dnsInfo.providerName}}</link-icon>
|
||||
</div>
|
||||
<span v-else-if="dnsInfo.domainName.length == 0" class="disabled">请先设置域名</span>
|
||||
<span v-else class="disabled">没有设置</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>自动设置CNAME记录</td>
|
||||
<td>
|
||||
<span v-if="dnsInfo.cnameRecords.length == 0" class="disabled">暂时还没有设置。</span>
|
||||
<div v-else>
|
||||
<span v-for="record in dnsInfo.cnameRecords" class="ui label basic small">{{record}}</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="dnsInfo.domainName.length > 0">
|
||||
<td>操作</td>
|
||||
<td>
|
||||
<div v-if="!isSyncing">
|
||||
<link-red v-if="dnsHasChanges" @click.prevent="syncCluster(cluster.id)">检测到解析记录有变化,需要同步</link-red>
|
||||
<a href="" @click.prevent="syncCluster(cluster.id)" v-else>DNS服务商同步</a>
|
||||
</div>
|
||||
<span v-else>DNS服务商同步中...</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 当前任务 -->
|
||||
<div v-if="tasks.length > 0">
|
||||
<h3>正在执行的任务</h3>
|
||||
<table class="ui table selectable celled">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>对象</th>
|
||||
<th>任务</th>
|
||||
<th>状态</th>
|
||||
<th>触发时间</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="task in tasks">
|
||||
<td>
|
||||
<span v-if="(task.type == 'clusterChange' || task.type == 'clusterNodesChange') && task.cluster != null">{{task.cluster.name}}
|
||||
<link-icon :href="'/dns/clusters/cluster?clusterId=' + task.cluster.id" target="_top"></link-icon>
|
||||
</span>
|
||||
<span v-if="task.type == 'nodeChange'">{{task.node.name}}</span>
|
||||
<span v-if="task.type == 'serverChange'">{{task.server.name}}</span>
|
||||
<span v-if="task.type == 'domainChange'">{{task.domain.name}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="task.type == 'clusterChange' || task.type == 'clusterNodesChange'">集群</span>
|
||||
<span v-if="task.type == 'nodeChange'">节点</span>
|
||||
<span v-if="task.type == 'serverChange'">网站</span>
|
||||
<span v-if="task.type == 'domainChange'">域名</span>
|
||||
</td>
|
||||
<td style="word-break: break-word; width: 26em">
|
||||
<span v-if="task.isDone" class="red">{{task.error}}</span>
|
||||
<span v-else>正在同步...</span>
|
||||
</td>
|
||||
<td>{{task.updatedTime}}</td>
|
||||
<td>
|
||||
<a href="" title="删除" class="remove-btn" @click.prevent="deleteTask(task.id)"><i class="icon remove small grey"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- 问题合集 -->
|
||||
<div v-if="issues.length > 0">
|
||||
<h3>需要修复的问题</h3>
|
||||
<table class="ui table selectable celled" v-if="issues.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%">问题对象</th>
|
||||
<th>问题描述</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="issue in issues">
|
||||
<td>
|
||||
<div v-if="issue.type == 'cluster'">
|
||||
集群 "{{issue.target}}" <link-icon :href="'/clusters/cluster?clusterId=' + issue.targetId"></link-icon>
|
||||
</div>
|
||||
<div v-if="issue.type == 'node'">
|
||||
集群 "{{issue.params.clusterName}}" 节点 "{{issue.target}}" <link-icon :href="'/clusters/cluster/node?clusterId=' + issue.params.clusterId + '&nodeId=' + issue.targetId"></link-icon>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{issue.description}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="issue.type == 'cluster'">
|
||||
<link-red @click.prevent="updateCluster(issue.targetId)">修复</link-red>
|
||||
</div>
|
||||
<div v-if="issue.type == 'node'">
|
||||
<link-red @click.prevent="updateNode(issue.params.clusterId, issue.targetId)">修复</link-red>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="margin"></div>
|
||||
</div>
|
||||
|
||||
<p class="comment">下面的DNS解析记录也可以手工在DNS服务商提供的管理平台添加。</p>
|
||||
|
||||
<!-- 节点DNS解析记录 -->
|
||||
<h3>节点DNS解析记录 <span> ({{nodes.length}}个)</span></h3>
|
||||
<p class="comment" v-if="nodes.length == 0">暂时没有需要设置的DNS记录。</p>
|
||||
<table class="ui table selectable celled" v-if="nodes.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>节点</th>
|
||||
<th>子域名</th>
|
||||
<th>记录类型</th>
|
||||
<th>记录值</th>
|
||||
<th>线路</th>
|
||||
<th>状态</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="node in nodes">
|
||||
<td><link-icon :href="'/clusters/cluster/node?clusterId=' + node.clusterId + '&nodeId=' + node.id">{{node.name}}</link-icon></td>
|
||||
<td>
|
||||
<span v-if="dnsInfo.dnsName.length > 0">{{dnsInfo.dnsName}}</span>
|
||||
<link-red v-else @click.prevent="updateCluster(cluster.id)">没有设置</link-red>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="node.ipAddr.indexOf(':') > -1">AAAA</span>
|
||||
<span v-else>A</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="node.ipAddr.length > 0">{{node.ipAddr}}</span>
|
||||
<link-red title="点击设置" v-else @click.prevent="updateNode(node.clusterId, node.id, node.ipAddrId)">没有设置</link-red>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="node.route.code.length > 0">{{node.route.name}}</span>
|
||||
<link-red v-else title="点击设置" @click.prevent="updateNode(node.clusterId, node.id, node.ipAddrId)">没有设置</link-red>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="node.isBackup" class="red">备用节点</span>
|
||||
<span v-else-if="node.isOffline" class="red">已下线</span>
|
||||
<div v-else="">
|
||||
<span v-if="node.isInstalled">
|
||||
<span class="green" v-if="node.isResolved">已解析</span>
|
||||
<span v-else class="red">未解析</span>
|
||||
</span>
|
||||
<link-red :href="'/clusters/cluster/node/install?clusterId=' + cluster.id + '&nodeId=' + node.id" v-if="!node.isInstalled" title="节点未安装"><span class="red">未安装</span></link-red>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<link-popup @click.prevent="updateNode(node.clusterId, node.id, node.ipAddrId)">修改</link-popup>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- 网站解析记录 -->
|
||||
<h3>网站解析记录 <span> ({{servers.length}}个)</span></h3>
|
||||
<p class="comment" v-if="servers.length == 0">暂时没有需要设置的DNS记录。</p>
|
||||
<table class="ui table selectable celled" v-if="servers.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>网站</th>
|
||||
<th>子域名</th>
|
||||
<th>记录类型</th>
|
||||
<th>记录值</th>
|
||||
<th>状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="server in servers">
|
||||
<td><link-icon :href="'/servers/server?serverId=' + server.id">{{server.name}}</link-icon> </td>
|
||||
<td>{{server.dnsName}}</td>
|
||||
<td>CNAME</td>
|
||||
<td>
|
||||
<span v-if="dnsInfo.domainName.length > 0"><var>{{dnsInfo.dnsName}}</var>.{{dnsInfo.domainName}}.</span>
|
||||
<link-red title="点击设置" v-else @click.prevent="updateCluster(cluster.id)">没有设置</link-red>
|
||||
</td>
|
||||
<td>
|
||||
<span class="green" v-if="server.isResolved">已解析</span>
|
||||
<span v-else class="red">未解析</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
56
EdgeUser/web/views/@default/dns/clusters/cluster.js
Normal file
56
EdgeUser/web/views/@default/dns/clusters/cluster.js
Normal file
@@ -0,0 +1,56 @@
|
||||
Tea.context(function () {
|
||||
this.updateCluster = function (clusterId) {
|
||||
teaweb.popup("/dns/updateClusterPopup?clusterId=" + clusterId, {
|
||||
height: "25em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.updateNode = function (clusterId, nodeId, ipAddrId) {
|
||||
teaweb.popup("/dns/issues/updateNodePopup?clusterId=" + clusterId + "&nodeId=" + nodeId + "&ipAddrId=" + (ipAddrId ? ipAddrId : 0), {
|
||||
width: "46em",
|
||||
height: "26em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.isSyncing = false
|
||||
this.syncCluster = function (clusterId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要执行数据同步吗?", function () {
|
||||
that.isSyncing = true
|
||||
that.$post(".sync")
|
||||
.params({clusterId: clusterId})
|
||||
.done(function () {
|
||||
that.isSyncing = false
|
||||
that.dnsHasChanges = false
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.success("同步成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteTask = function (taskId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除这个任务吗?", function () {
|
||||
that.$post("/dns/tasks/delete")
|
||||
.params({
|
||||
taskId: taskId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
20
EdgeUser/web/views/@default/dns/domains/clustersPopup.html
Normal file
20
EdgeUser/web/views/@default/dns/domains/clustersPopup.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>使用域名"{{domain}}"的集群</h3>
|
||||
<table class="ui table selectable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>集群</th>
|
||||
<th>域名</th>
|
||||
<th class="width10">解析状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="cluster in clusters">
|
||||
<td>{{cluster.name}}<a :href="'/clusters/cluster?clusterId=' + cluster.id" target="_blank"><link-icon></link-icon></a> </td>
|
||||
<td>{{cluster.dnsName}}.{{domain}}</td>
|
||||
<td>
|
||||
<span class="green" v-if="cluster.isOk">已解析</span>
|
||||
<span class="red" v-else>未解析</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
19
EdgeUser/web/views/@default/dns/domains/createPopup.html
Normal file
19
EdgeUser/web/views/@default/dns/domains/createPopup.html
Normal file
@@ -0,0 +1,19 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加管理域名</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="providerId" :value="providerId"/>
|
||||
<csrf-token></csrf-token>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">域名 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="64" ref="focus"/>
|
||||
<p class="comment">在DNS服务商中可以管理的域名。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
42
EdgeUser/web/views/@default/dns/domains/nodesPopup.html
Normal file
42
EdgeUser/web/views/@default/dns/domains/nodesPopup.html
Normal file
@@ -0,0 +1,42 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>使用域名"{{domain}}"的节点</h3>
|
||||
<form class="ui form" action="/dns/domains/nodesPopup" method="get">
|
||||
<input type="hidden" name="domainId" :value="domainId"/>
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" placeholder="关键词" v-model="keyword"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<select class="ui dropdown auto-width" v-model="status">
|
||||
<option value="">[全部状态]</option>
|
||||
<option value="ok">已解析</option>
|
||||
<option value="notOk">未解析</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="ui divider"></div>
|
||||
<table class="ui table selectable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>集群</th>
|
||||
<th>节点</th>
|
||||
<th>子域名</th>
|
||||
<th>线路</th>
|
||||
<th>IP</th>
|
||||
<th class="width10">解析状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="node in nodes">
|
||||
<td>{{node.cluster.name}}<a :href="'/clusters/cluster?clusterId=' + node.cluster.id" target="_blank"><link-icon></link-icon></a> </td>
|
||||
<td>{{node.name}}<a :href="'/clusters/cluster/node?clusterId=' + node.cluster.id + '&nodeId=' + node.id" target="_blank"><link-icon></link-icon></a></td>
|
||||
<td>{{node.cluster.dnsName}}</td>
|
||||
<td>{{node.route.name}}</td>
|
||||
<td>{{node.ipAddr}}</td>
|
||||
<td>
|
||||
<span class="green" v-if="node.isOk">已解析</span>
|
||||
<span class="red" v-else>未解析</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
45
EdgeUser/web/views/@default/dns/domains/nodesPopup.js
Normal file
45
EdgeUser/web/views/@default/dns/domains/nodesPopup.js
Normal file
@@ -0,0 +1,45 @@
|
||||
Tea.context(function () {
|
||||
this.keyword = ""
|
||||
this.status = ""
|
||||
|
||||
let allNodes = []
|
||||
this.clusters.forEach(function (cluster) {
|
||||
let nodes = cluster.nodes
|
||||
nodes.forEach(function (node) {
|
||||
node.cluster = cluster
|
||||
allNodes.push(node)
|
||||
})
|
||||
})
|
||||
|
||||
this.nodes = allNodes
|
||||
|
||||
this.$delay(function () {
|
||||
this.$watch("keyword", function () {
|
||||
this.reloadNodes()
|
||||
})
|
||||
this.$watch("status", function () {
|
||||
this.reloadNodes()
|
||||
})
|
||||
})
|
||||
|
||||
this.reloadNodes = function () {
|
||||
let that = this
|
||||
this.nodes = allNodes.$copy().$findAll(function (k, v) {
|
||||
if (that.keyword.length > 0
|
||||
&& !teaweb.match(v.cluster.name, that.keyword)
|
||||
&& !teaweb.match(v.cluster.dnsName, that.keyword)
|
||||
&& !teaweb.match(v.name, that.keyword)
|
||||
&& !teaweb.match(v.ipAddr, that.keyword)
|
||||
&& !teaweb.match(v.route.name, that.keyword)) {
|
||||
return false
|
||||
}
|
||||
if (that.status == "ok" && !v.isOk) {
|
||||
return false
|
||||
}
|
||||
if (that.status == "notOk" && v.isOk) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
})
|
||||
18
EdgeUser/web/views/@default/dns/domains/routesPopup.html
Normal file
18
EdgeUser/web/views/@default/dns/domains/routesPopup.html
Normal file
@@ -0,0 +1,18 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>域名支持的线路</h3>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">线路</td>
|
||||
<td>
|
||||
<p class="comment" v-if="routes.length == 0">暂时还没有支持的线路。</p>
|
||||
<div v-if="routes.length > 0">
|
||||
<div class="ui label tiny basic" v-for="route in routes" style="margin-bottom: 0.5em">{{route.name}}<span v-if="route.code.length > 0 && route.code != route.name"> ({{route.code}})</span></div>
|
||||
</div>
|
||||
<p class="comment">注意:有些DNS服务商会根据账号的会员级别等限制线路的使用。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<button class="ui button primary" @click.prevent="close" type="button">确定</button>
|
||||
3
EdgeUser/web/views/@default/dns/domains/routesPopup.js
Normal file
3
EdgeUser/web/views/@default/dns/domains/routesPopup.js
Normal file
@@ -0,0 +1,3 @@
|
||||
Tea.context(function () {
|
||||
this.close = NotifyPopup
|
||||
})
|
||||
39
EdgeUser/web/views/@default/dns/domains/selectPopup.html
Normal file
39
EdgeUser/web/views/@default/dns/domains/selectPopup.html
Normal file
@@ -0,0 +1,39 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>选择集群DNS设置</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">DNS服务商</td>
|
||||
<td>
|
||||
<select name="providerType" class="ui dropdown auto-width" v-model="providerType" @change="changeProviderType">
|
||||
<option v-for="providerType in providerTypes" :value="providerType.code">{{providerType.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>账号</td>
|
||||
<td>
|
||||
<p class="comment" v-if="providers.length == 0">没有账号可选</p>
|
||||
<select name="providerId" class="ui dropdown auto-width" v-model="providerId" v-show="providers.length > 0">
|
||||
<option v-for="provider in providers" :value="provider.id">{{provider.name}}</option>
|
||||
</select>
|
||||
<p class="comment"><a href="/dns/providers" target="_blank">去管理DNS服务商账号»</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="providerId > 0">
|
||||
<td>域名</td>
|
||||
<td>
|
||||
<p class="comment" v-if="domains.length == 0">没有域名可选</p>
|
||||
<select name="domainId" class="ui dropdown auto-width" v-model="domainId" v-show="domains.length > 0">
|
||||
<option v-for="domain in domains" :value="domain.id">{{domain.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
80
EdgeUser/web/views/@default/dns/domains/selectPopup.js
Normal file
80
EdgeUser/web/views/@default/dns/domains/selectPopup.js
Normal file
@@ -0,0 +1,80 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
this.changeProviderType()
|
||||
this.changeProvider()
|
||||
|
||||
this.$watch("providerId", function () {
|
||||
this.changeProvider()
|
||||
})
|
||||
this.$watch("domainId", function () {
|
||||
this.changeDomain()
|
||||
})
|
||||
})
|
||||
|
||||
this.success = NotifyPopup
|
||||
|
||||
// 初始化的内容
|
||||
// this.domainId = 0
|
||||
// this.domain = ""
|
||||
// this.providerId = 0
|
||||
|
||||
if (this.providerType == "") {
|
||||
this.providerType = this.providerTypes[0].code
|
||||
}
|
||||
this.providers = []
|
||||
this.domains = []
|
||||
|
||||
this.changeProviderType = function () {
|
||||
this.$post("/dns/providerOptions")
|
||||
.params({
|
||||
type: this.providerType
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.providers = resp.data.providers
|
||||
|
||||
// 检查providerId
|
||||
if (this.providers.length == 0) {
|
||||
this.providerId = 0
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
if (this.providers.$find(function (k, v) {
|
||||
return v.id == that.providerId
|
||||
}) == null) {
|
||||
this.providerId = this.providers[0].id
|
||||
}
|
||||
this.changeProvider()
|
||||
})
|
||||
}
|
||||
|
||||
this.changeProvider = function () {
|
||||
this.$post("/dns/domainOptions")
|
||||
.params({
|
||||
providerId: this.providerId
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.domains = resp.data.domains
|
||||
this.changeDomain()
|
||||
})
|
||||
}
|
||||
|
||||
this.changeDomain = function () {
|
||||
if (this.domains.length == 0) {
|
||||
this.domainId = 0
|
||||
this.domain = ""
|
||||
return
|
||||
}
|
||||
|
||||
let domainId = this.domainId
|
||||
let domainInfo = this.domains.$find(function (k, v) {
|
||||
return v.id == domainId
|
||||
})
|
||||
if (domainInfo == null) {
|
||||
// 默认选取第一个
|
||||
this.domainId = this.domains[0].id
|
||||
this.domain = this.domains[0].name
|
||||
} else {
|
||||
this.domain = domainInfo.name
|
||||
}
|
||||
}
|
||||
})
|
||||
40
EdgeUser/web/views/@default/dns/domains/serversPopup.html
Normal file
40
EdgeUser/web/views/@default/dns/domains/serversPopup.html
Normal file
@@ -0,0 +1,40 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>使用域名"{{domain}}"的网站</h3>
|
||||
<form class="ui form" action="/dns/domains/serversPopup" method="get">
|
||||
<input type="hidden" name="domainId" :value="domainId"/>
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" placeholder="关键词" v-model="keyword"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<select class="ui dropdown auto-width" v-model="status">
|
||||
<option value="">[全部状态]</option>
|
||||
<option value="ok">已解析</option>
|
||||
<option value="notOk">未解析</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="ui divider"></div>
|
||||
<table class="ui table selectable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>集群</th>
|
||||
<th>网站</th>
|
||||
<th>子域名</th>
|
||||
<th>CNAME</th>
|
||||
<th class="width10">解析状态</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="server in servers">
|
||||
<td>{{server.cluster.name}}<a :href="'/clusters/cluster?clusterId=' + server.cluster.id" target="_blank"><link-icon></link-icon></a> </td>
|
||||
<td>{{server.name}}<a :href="'/servers/server?clusterId=' + server.cluster.id + '&serverId=' + server.id" target="_blank"><link-icon></link-icon></a></td>
|
||||
<td>{{server.cluster.dnsName}}</td>
|
||||
<td>{{server.dnsName}}</td>
|
||||
<td>
|
||||
<span class="green" v-if="server.isOk">已解析</span>
|
||||
<span class="red" v-else>未解析</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
44
EdgeUser/web/views/@default/dns/domains/serversPopup.js
Normal file
44
EdgeUser/web/views/@default/dns/domains/serversPopup.js
Normal file
@@ -0,0 +1,44 @@
|
||||
Tea.context(function () {
|
||||
this.keyword = ""
|
||||
this.status = ""
|
||||
|
||||
let allServers = []
|
||||
this.clusters.forEach(function (cluster) {
|
||||
let servers = cluster.servers
|
||||
servers.forEach(function (server) {
|
||||
server.cluster = cluster
|
||||
allServers.push(server)
|
||||
})
|
||||
})
|
||||
|
||||
this.servers = allServers
|
||||
|
||||
this.$delay(function () {
|
||||
this.$watch("keyword", function () {
|
||||
this.reloadServers()
|
||||
})
|
||||
this.$watch("status", function () {
|
||||
this.reloadServers()
|
||||
})
|
||||
})
|
||||
|
||||
this.reloadServers = function () {
|
||||
let that = this
|
||||
this.servers = allServers.$copy().$findAll(function (k, v) {
|
||||
if (that.keyword.length > 0
|
||||
&& !teaweb.match(v.cluster.name, that.keyword)
|
||||
&& !teaweb.match(v.cluster.dnsName, that.keyword)
|
||||
&& !teaweb.match(v.name, that.keyword)
|
||||
&& !teaweb.match(v.dnsName, that.keyword)) {
|
||||
return false
|
||||
}
|
||||
if (that.status == "ok" && !v.isOk) {
|
||||
return false
|
||||
}
|
||||
if (that.status == "notOk" && v.isOk) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
})
|
||||
33
EdgeUser/web/views/@default/dns/domains/updatePopup.html
Normal file
33
EdgeUser/web/views/@default/dns/domains/updatePopup.html
Normal file
@@ -0,0 +1,33 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改管理域名</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="domainId" :value="domain.id"/>
|
||||
<csrf-token></csrf-token>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">域名 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="64" ref="focus" v-model="domain.name"/>
|
||||
<p class="comment">在DNS服务商中可以管理的域名。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>启用当前域名</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="isOn" value="1" v-model="domain.isOn"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
4
EdgeUser/web/views/@default/dns/index.css
Normal file
4
EdgeUser/web/views/@default/dns/index.css
Normal file
@@ -0,0 +1,4 @@
|
||||
.italic {
|
||||
font-style: italic !important;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
1
EdgeUser/web/views/@default/dns/index.css.map
Normal file
1
EdgeUser/web/views/@default/dns/index.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,6BAAA","file":"index.css"}
|
||||
52
EdgeUser/web/views/@default/dns/index.html
Normal file
52
EdgeUser/web/views/@default/dns/index.html
Normal file
@@ -0,0 +1,52 @@
|
||||
{$layout}
|
||||
|
||||
<div class="margin"></div>
|
||||
|
||||
<form class="ui form" method="get" action="/dns">
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" name="keyword" placeholder="集群、域名..." v-model="keyword"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<button class="ui button" type="submit">搜索</button>
|
||||
|
||||
<a href="/dns" v-if="keyword.length > 0">[清除条件]</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="comment" v-if="clusters.length == 0" style="margin-top: 1em">暂时还没有集群。</p>
|
||||
<table class="ui table selectable celled" v-if="clusters.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>集群</th>
|
||||
<th>子域名</th>
|
||||
<th>DNS服务商</th>
|
||||
<th>DNS服务商账号</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="cluster in clusters">
|
||||
<td>
|
||||
<a :href="'/dns/clusters/cluster?clusterId=' + cluster.id"><keyword :v-word="keyword">{{cluster.name}}</keyword></a><link-icon :href="'/clusters/cluster?clusterId=' + cluster.id"></link-icon>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="cluster.dnsName.length > 0 && cluster.domainName.length > 0"><em class="italic"><keyword :v-word="keyword">{{cluster.dnsName}}</keyword></em>.<keyword :v-word="keyword">{{cluster.domainName}}</keyword></span>
|
||||
<span v-else="" class="disabled">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="cluster.providerTypeName.length > 0">{{cluster.providerTypeName}}</span>
|
||||
<span v-else class="disabled">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="cluster.providerName.length > 0">{{cluster.providerName}}<link-icon :href="'/dns/providers/provider?providerId=' + cluster.providerId"></link-icon></span>
|
||||
<span v-else="" class="disabled">-</span>
|
||||
</td>
|
||||
<td>
|
||||
<a :href="'/dns/clusters/cluster?clusterId=' + cluster.id">详情</a> <a href="" @click.prevent="updateCluster(cluster.id)">修改</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p class="comment" v-if="clusters.length > 0">这里列出了所有集群对应的域名设置。</p>
|
||||
|
||||
<div class="page" v-html="page"></div>
|
||||
12
EdgeUser/web/views/@default/dns/index.js
Normal file
12
EdgeUser/web/views/@default/dns/index.js
Normal file
@@ -0,0 +1,12 @@
|
||||
Tea.context(function () {
|
||||
this.updateCluster = function (clusterId) {
|
||||
teaweb.popup("/dns/updateClusterPopup?clusterId=" + clusterId, {
|
||||
height: "25em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
3
EdgeUser/web/views/@default/dns/index.less
Normal file
3
EdgeUser/web/views/@default/dns/index.less
Normal file
@@ -0,0 +1,3 @@
|
||||
.italic {
|
||||
font-style: italic !important;
|
||||
}
|
||||
50
EdgeUser/web/views/@default/dns/issues/index.html
Normal file
50
EdgeUser/web/views/@default/dns/issues/index.html
Normal file
@@ -0,0 +1,50 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<span class="item" v-if="issues.length > 0">共<span class="red">{{issues.length}}</span>个问题</span>
|
||||
<span class="item" v-if="issues.length > 0">|</span>
|
||||
<a href="/dns/issues" title="刷新" class="item" @click.prevent="reload">刷新</a>
|
||||
<span class="item">|</span>
|
||||
<span class="item"><tip-icon content="这里是一个全局的DNS解析问题发现页,方便我们诊断并修复问题。"></tip-icon></span>
|
||||
</first-menu>
|
||||
|
||||
<div v-if="isRequesting">
|
||||
<div class="margin"></div>
|
||||
正在检查系统问题,请耐心等待...
|
||||
</div>
|
||||
|
||||
<div v-if="issues.length == 0 && !isRequesting">
|
||||
<div class="margin"></div>
|
||||
<p class="comment">暂时没有发现问题。</p>
|
||||
</div>
|
||||
|
||||
<table class="ui table selectable celled" v-if="issues.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 50%">问题对象</th>
|
||||
<th>问题描述</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="issue in issues">
|
||||
<td>
|
||||
<div v-if="issue.type == 'cluster'">
|
||||
集群 "{{issue.target}}" <link-icon :href="'/clusters/cluster?clusterId=' + issue.targetId"></link-icon>
|
||||
</div>
|
||||
<div v-if="issue.type == 'node'">
|
||||
集群 "{{issue.params.clusterName}}" 节点 "{{issue.target}}" <link-icon :href="'/clusters/cluster/node?clusterId=' + issue.params.clusterId + '&nodeId=' + issue.targetId"></link-icon>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{issue.description}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<div v-if="issue.type == 'cluster'">
|
||||
<link-red @click.prevent="updateCluster(issue.targetId)">修复</link-red>
|
||||
</div>
|
||||
<div v-if="issue.type == 'node'">
|
||||
<link-red @click.prevent="updateNode(issue.params.clusterId, issue.targetId)">修复</link-red>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
43
EdgeUser/web/views/@default/dns/issues/index.js
Normal file
43
EdgeUser/web/views/@default/dns/issues/index.js
Normal file
@@ -0,0 +1,43 @@
|
||||
Tea.context(function () {
|
||||
this.isRequesting = true
|
||||
|
||||
this.$delay(function () {
|
||||
this.reload()
|
||||
})
|
||||
|
||||
this.updateCluster = function (clusterId) {
|
||||
let that = this
|
||||
teaweb.popup("/dns/updateClusterPopup?clusterId=" + clusterId, {
|
||||
height: "25em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
that.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.updateNode = function (clusterId, nodeId) {
|
||||
let that = this
|
||||
teaweb.popup("/dns/issues/updateNodePopup?clusterId=" + clusterId + "&nodeId=" + nodeId, {
|
||||
width: "46em",
|
||||
height: "26em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
that.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.reload = function () {
|
||||
this.isRequesting = true
|
||||
this.$post("$")
|
||||
.success(function (resp) {
|
||||
this.issues = resp.data.issues;
|
||||
})
|
||||
.done(function () {
|
||||
this.isRequesting = false
|
||||
})
|
||||
}
|
||||
})
|
||||
42
EdgeUser/web/views/@default/dns/issues/updateNodePopup.html
Normal file
42
EdgeUser/web/views/@default/dns/issues/updateNodePopup.html
Normal file
@@ -0,0 +1,42 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改节点DNS设置</h3>
|
||||
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<input type="hidden" name="nodeId" :value="nodeId"/>
|
||||
<input type="hidden" name="domainId" :value="domainId"/>
|
||||
<input type="hidden" name="ipAddrId" :value="ipAddrId"/>
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr v-if="domainName.length > 0">
|
||||
<td>主域名</td>
|
||||
<td>{{domainName}}
|
||||
<p class="comment">由当前节点所属集群设置。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="title">IP地址 *</td>
|
||||
<td>
|
||||
<input type="text" name="ipAddr" maxlength="64" ref="focus" v-model="ipAddr"/>
|
||||
<p class="comment">用于域名解析的节点IP地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="domainId > 0">
|
||||
<td>线路</td>
|
||||
<td>
|
||||
<p class="comment" v-if="allRoutes.length == 0">没有可选的线路。<a href="" @click.prevent="syncDomain(domainId)">[获取线路]</a></p>
|
||||
<div v-if="allRoutes.length > 0">
|
||||
<dns-route-selector :v-all-routes="allRoutes" :v-routes="routes"></dns-route-selector>
|
||||
<p class="comment">当前节点IP对应的线路。<a href="" @click.prevent="syncDomain(domainId)">[重新获取线路]</a></p>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="domainId == 0">
|
||||
<td>线路</td>
|
||||
<td><span class="disabled">当前集群没有选择域名。</span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
13
EdgeUser/web/views/@default/dns/issues/updateNodePopup.js
Normal file
13
EdgeUser/web/views/@default/dns/issues/updateNodePopup.js
Normal file
@@ -0,0 +1,13 @@
|
||||
Tea.context(function () {
|
||||
this.syncDomain = function (domainId) {
|
||||
this.$post(".syncDomain")
|
||||
.params({
|
||||
domainId: domainId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.success("从服务商获取线路成功", function () {
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
416
EdgeUser/web/views/@default/dns/providers/createPopup.html
Normal file
416
EdgeUser/web/views/@default/dns/providers/createPopup.html
Normal file
@@ -0,0 +1,416 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>添加DNS服务商账号</h3>
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">账号说明 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="50" ref="focus"/>
|
||||
<p class="comment">用来方便区分不同的账号。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>服务商厂家 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="type" v-model="type" @change="changeType">
|
||||
<option value="">[请选择]</option>
|
||||
<option v-for="type in types" :value="type.code">{{type.name}}</option>
|
||||
</select>
|
||||
<p class="comment" v-if="typeDescription.length > 0">{{typeDescription}} 系统会保留原有域名下的域名解析,请放心使用。<span v-if="!teaIsPlus">购买商业版可获得更多厂商支持。</span></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="type.length > 0">
|
||||
<td colspan="2">API参数</td>
|
||||
</tr>
|
||||
|
||||
<!-- DNSPod -->
|
||||
<tbody v-if="type == 'dnspod'">
|
||||
<tr>
|
||||
<td>密钥类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramDNSPodAPIType" v-model="paramDNSPodAPIType">
|
||||
<option value="tencentDNS">腾讯云API密钥</option>
|
||||
<option value="dnsPodToken">DNSPod Token</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="paramDNSPodAPIType == 'tencentDNS'">
|
||||
<td>SecretId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodAccessKeyId" maxlength="100"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="paramDNSPodAPIType == 'tencentDNS'">
|
||||
<td>SecretKey *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodAccessKeySecret" maxlength="100"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥”中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="paramDNSPodAPIType == 'dnsPodToken'">
|
||||
<td>密钥ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥--DNSPod Token”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="paramDNSPodAPIType == 'dnsPodToken'">
|
||||
<td>密钥Token *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodToken" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥--DNSPod Token”中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="paramDNSPodAPIType == 'dnsPodToken'">
|
||||
<td>区域</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramDNSPodRegion">
|
||||
<option value="">中国站</option>
|
||||
<option value="international">国际站</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- AliDNS -->
|
||||
<tbody v-if="type == 'alidns'">
|
||||
<tr>
|
||||
<td>AccessKeyId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSAccessKeyId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">登录阿里云控制台 -- 在"访问控制"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSAccessKeySecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">登录阿里云控制台 -- 在"访问控制"中创建和获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域ID<optional-label></optional-label></td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSRegionId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">阿里云产品所在区域代号,通常不需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 华为云 -->
|
||||
<tbody v-if="type == 'huaweiDNS'">
|
||||
<tr>
|
||||
<td>AccessKeyId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiAccessKeyId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiAccessKeySecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiEndpoint" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">选填项。可以填写终端节点(Endpoint)区域代号或者域名,参考 <a href="https://developer.huaweicloud.com/endpoint?DNS" target="_blank">https://developer.huaweicloud.com/endpoint?DNS</a>(如果此链接失效,请到华为云开发者中心自行查找)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- CloudFlare -->
|
||||
<tbody v-if="type == 'cloudFlare'">
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCloudFlareAPIKey" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在个人资料中的"API令牌"--"API密钥"--"Global API Key"中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>账号邮箱 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCloudFlareEmail" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">登录账号使用的邮箱。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- GoDaddy -->
|
||||
<tbody v-if="type == 'godaddy'">
|
||||
<tr>
|
||||
<td>Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGoDaddyKey" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">可以在GoDaddy<a href="https://developer.godaddy.com/keys" target="_blank">开发者中心</a>创建,创建时Environment选择Production。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGoDaddySecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- ClouDNS -->
|
||||
<tbody v-if="type == 'cloudns'">
|
||||
<tr>
|
||||
<td>用户认证ID<em>(auth-id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="paramClouDNSAuthId" maxlength="20" spellcheck="false"/>
|
||||
<p class="comment">和子用户认证ID二选一。可以在ClouDNS<a href="https://www.cloudns.net/api-settings/" target="_blank">API设置页面</a>添加。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>子用户认证ID<em>(sub-auth-id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="paramClouDNSSubAuthId" maxlength="20" spellcheck="false"/>
|
||||
<p class="comment">和用户认证ID二选一。可以在ClouDNS<a href="https://www.cloudns.net/api-settings/" target="_blank">API设置页面</a>添加。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>认证密码 *<em>(auth-password)</em></td>
|
||||
<td>
|
||||
<input type="password" name="paramClouDNSAuthPassword" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">用户或者子用户的认证密码。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- DNS.COM -->
|
||||
<tbody v-if="type == 'dnscom'">
|
||||
<tr>
|
||||
<td>API Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSComKey" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在51DNS.COM控制台账号中心--API设置中创建和查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSComSecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在51DNS.COM控制台账号中心--API设置中创建和查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- DNS.LA -->
|
||||
<tbody v-if="type == 'dnsla'">
|
||||
<tr>
|
||||
<td>API ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSLaAPIId" maxlength="100"/>
|
||||
<p class="comment">在DNS.LA控制台--账户信息中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSLaSecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在DNS.LA控制台--账户信息中查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- VolcEngine -->
|
||||
<tbody v-if="type == 'volcEngine'">
|
||||
<tr>
|
||||
<td>Access Key ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramVolcEngineAccessKeyId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在火山引擎“访问控制--API访问密钥”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramVolcEngineAccessKeySecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Amazon Route 53 -->
|
||||
<tbody v-if="type == 'amazonRoute53'">
|
||||
<tr>
|
||||
<td>Access Key ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53AccessKeyId" maxlength="100" spellcheck="false"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53AccessKeySecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API区域</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53Region" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">通常不需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Microsoft Azure DNS -->
|
||||
<tbody v-if="type == 'azureDNS'">
|
||||
<tr>
|
||||
<td>订阅ID <br/><em>(Subscription ID)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSSubscriptionId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">可以在订阅(Subscriptions)服务中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>目录(租户) ID <br/><em>(Directory Tenant ID)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSTenantId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">可以在应用注册(App registrations)中对应应用概述(Overview)中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>应用程序(客户端) ID <br/><em>(Client ID)</em> *</td>
|
||||
<td><input type="text" name="paramAzureDNSClientId" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">需要在应用注册(App registrations)中新注册应用程序获得。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>客户端密码值 <br/><em>(Client Secret Value)</em> *</td>
|
||||
<td><input type="text" name="paramAzureDNSClientSecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">可以在应用注册(App registrations)中对应应用的“证书和密码(Certificates & secrets)”--“客户端密码(Client secrets)”中创建和查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>资源组 <br/><em>(Resource Group Name)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSResourceGroupName" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">权限设置帮助:你需要在对应资源组(Resource group)-- 访问控制(Access control (IAM))-- 角色分配(Role assignments)中添加一个角色分配(Role assignment),其中作业职能角色(Job function roles)为"DNS 区域参与者(DNS Zone Contributor)",成员(Members)为应用注册(App registrations)中的应用程序(application)(有时需要在选择成员(select members)界面搜索应用程序(application)名称才能看到)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- bunny.net -->
|
||||
<tbody v-if="type == 'bunnyNet'">
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramBunnyNetAPIKey" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在"Edit account details" -- "API Key"中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Gname -->
|
||||
<tbody v-if="type == 'gname'">
|
||||
<tr>
|
||||
<td>APPID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGnameAppid" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在Gname控制台API设置中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGnameSecret" maxlength="100" spellcheck="false"/>
|
||||
<p class="comment">在Gname控制台API设置中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- EdgeDNS -->
|
||||
<tbody v-if="type == 'localEdgeDNS'">
|
||||
<tr>
|
||||
<td>选择域名服务集群 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramLocalEdgeDNSClusterId">
|
||||
<option value="0">[选择域名服务集群]</option>
|
||||
<option v-for="cluster in nsClusters" :value="cluster.id">{{cluster.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- EdgeDNS API -->
|
||||
<tbody v-if="type == 'edgeDNSAPI'">
|
||||
<tr>
|
||||
<td>API地址 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIHost" maxlength="100"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramEdgeDNSAPIRole">
|
||||
<option value="user">平台用户</option>
|
||||
<option value="admin">管理员</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIAccessKeyId" maxlength="64"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIAccessKeySecret" maxlength="64"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 自定义HTTP-->
|
||||
<tbody v-if="type == 'customHTTP'">
|
||||
<tr>
|
||||
<td>HTTP URL *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCustomHTTPURL" maxlength="200"/>
|
||||
<p class="comment">HTTP URL完整地址,DNS所有操作都会以POST的方式转发到此地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>私钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCustomHTTPSecret" maxlength="64" v-model="paramCustomHTTPSecret"/>
|
||||
<p class="comment">通讯用的私钥,转发请求时会在Header中加入相关信息,方便开发者校验请求是否合法。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 更多选项 -->
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>最小TTL</td>
|
||||
<td>
|
||||
<div class="ui right labeled input">
|
||||
<input type="text" name="minTTL" size="4" maxlength="6" style="width: 6em"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">生成的DNS时可以使用的最小TTL,请根据你选择的服务商和你在服务商中的账号等级进行填写;不填写或者0表示默认。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
20
EdgeUser/web/views/@default/dns/providers/createPopup.js
Normal file
20
EdgeUser/web/views/@default/dns/providers/createPopup.js
Normal file
@@ -0,0 +1,20 @@
|
||||
Tea.context(function () {
|
||||
this.success = NotifyPopup
|
||||
this.type = ""
|
||||
this.typeDescription = ""
|
||||
|
||||
this.changeType = function () {
|
||||
let that = this
|
||||
let t = this.types.$find(function (k, v) {
|
||||
return v.code == that.type
|
||||
})
|
||||
if (t != null) {
|
||||
this.typeDescription = t.description
|
||||
} else {
|
||||
this.typeDescription = ""
|
||||
}
|
||||
}
|
||||
|
||||
// DNSPod
|
||||
this.paramDNSPodAPIType = "tencentDNS"
|
||||
})
|
||||
55
EdgeUser/web/views/@default/dns/providers/index.html
Normal file
55
EdgeUser/web/views/@default/dns/providers/index.html
Normal file
@@ -0,0 +1,55 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<a href="" class="item" @click.prevent="createProvider()">[添加DNS账号信息]</a>
|
||||
</first-menu>
|
||||
|
||||
<div class="margin"></div>
|
||||
|
||||
<form class="ui form" method="get" action="/dns/providers">
|
||||
<div class="ui fields inline">
|
||||
<div class="ui field">
|
||||
<input type="text" name="keyword" placeholder="账号说明..." v-model="keyword"/>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<input type="text" name="domain" placeholder="域名..." v-model="domain"/>
|
||||
</div>
|
||||
<div class="ui field" v-if="providerTypes.length > 0">
|
||||
<select class="ui dropdown auto-width" name="providerType" v-model="providerType">
|
||||
<option value="">[服务商厂家]</option>
|
||||
<option v-for="p in providerTypes" :value="p.code">{{p.name}}({{p.count}})</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ui field">
|
||||
<button class="ui button" type="submit">搜索</button>
|
||||
|
||||
<a :href="Tea.url('.')" v-if="keyword.length > 0 || domain.length > 0 || providerType.length > 0">[清除条件]</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p class="comment" v-if="providers.length == 0">暂时还没有第三方DNS服务商。</p>
|
||||
|
||||
<table class="ui table selectable celled" v-if="providers.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>账号说明</th>
|
||||
<th class="three wide">服务商</th>
|
||||
<th class="width5 center">域名</th>
|
||||
<th class="two op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="(provider, index) in providers">
|
||||
<td><a :href="'/dns/providers/provider?providerId=' + provider.id"><keyword :v-word="keyword">{{provider.name}}</keyword></a></td>
|
||||
<td>{{provider.typeName}}</td>
|
||||
<td class="center">
|
||||
<span v-if="provider.countDomains == 0" class="disabled">0</span>
|
||||
<span v-else>{{provider.countDomains}}</span>
|
||||
</td>
|
||||
<td>
|
||||
<a :href="'/dns/providers/provider?providerId=' + provider.id">详情</a> <a href="" @click.prevent="deleteProvider(provider.id)">删除</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<div class="page" v-html="page"></div>
|
||||
23
EdgeUser/web/views/@default/dns/providers/index.js
Normal file
23
EdgeUser/web/views/@default/dns/providers/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
Tea.context(function () {
|
||||
this.createProvider = function () {
|
||||
teaweb.popup(Tea.url(".createPopup"), {
|
||||
height: "28em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteProvider = function (providerId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除这个DNS服务商账号吗?", function () {
|
||||
that.$post(".delete")
|
||||
.params({
|
||||
providerId: providerId
|
||||
})
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
})
|
||||
356
EdgeUser/web/views/@default/dns/providers/provider.html
Normal file
356
EdgeUser/web/views/@default/dns/providers/provider.html
Normal file
@@ -0,0 +1,356 @@
|
||||
{$layout}
|
||||
|
||||
<first-menu>
|
||||
<a href="/dns/providers" class="item">DNS账号列表</a>
|
||||
<span class="item">|</span>
|
||||
<a :href="'/dns/providers/provider?providerId=' + provider.id" class="item active">{{provider.name}}</a>
|
||||
</first-menu>
|
||||
|
||||
|
||||
<h3>账号信息 <a href="" @click.prevent="updateProvider(provider.id)">[修改]</a> </h3>
|
||||
|
||||
<table class="ui table selectable definition">
|
||||
<tr>
|
||||
<td class="title">账号说明</td>
|
||||
<td>{{provider.name}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>服务商</td>
|
||||
<td>{{provider.typeName}}</td>
|
||||
</tr>
|
||||
|
||||
<!-- DNSPod -->
|
||||
<tbody v-if="provider.type == 'dnspod'">
|
||||
<tr>
|
||||
<td class="color-border">密钥类型</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.apiType == 'tencentDNS'">腾讯云API密钥</span>
|
||||
<span v-else>DNSPod Token</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.apiType == 'tencentDNS'">
|
||||
<td class="color-border">SecretId</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.apiType == 'tencentDNS'">
|
||||
<td class="color-border">SecretKey</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.apiType != 'tencentDNS'">
|
||||
<td class="color-border">密钥ID</td>
|
||||
<td>{{provider.apiParams.id}}</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.apiType != 'tencentDNS'">
|
||||
<td class="color-border">密钥Token</td>
|
||||
<td>{{provider.apiParams.token}}</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.apiType != 'tencentDNS'">
|
||||
<td class="color-border">区域</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.region == 'international'">国际站</span>
|
||||
<span v-else>中国站</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- AliDNS -->
|
||||
<tbody v-if="provider.type == 'alidns'">
|
||||
<tr>
|
||||
<td>AccessKeyId</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域ID</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.regionId != null && provider.apiParams.regionId.length > 0">{{provider.apiParams.regionId}}</span>
|
||||
<span v-else class="disabled">没有设置。</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- HuaweiDNS -->
|
||||
<tbody v-if="provider.type == 'huaweiDNS'">
|
||||
<tr>
|
||||
<td>AccessKeyId</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.endpoint != null && provider.apiParams.endpoint.length > 0">{{provider.apiParams.endpoint}}</span>
|
||||
<span v-else class="disabled">默认</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- CloudFlare -->
|
||||
<tbody v-if="provider.type == 'cloudFlare'">
|
||||
<tr>
|
||||
<td class="color-border">API密钥</td>
|
||||
<td>
|
||||
{{provider.apiParams.apiKey}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">账号邮箱</td>
|
||||
<td>{{provider.apiParams.email}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- GoDaddy -->
|
||||
<tbody v-if="provider.type == 'godaddy'">
|
||||
<tr>
|
||||
<td class="color-border">Key</td>
|
||||
<td>
|
||||
{{provider.apiParams.key}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">Secret</td>
|
||||
<td>{{provider.apiParams.secret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- ClouDNS -->
|
||||
<tbody v-if="provider.type == 'cloudns'">
|
||||
<tr v-if="provider.apiParams.authId > 0">
|
||||
<td class="color-border">用户认证ID<em>(auth-id)</em></td>
|
||||
<td>{{provider.apiParams.authId}}</td>
|
||||
</tr>
|
||||
<tr v-if="provider.apiParams.subAuthId > 0">
|
||||
<td class="color-border">子用户认证ID<em>(sub-auth-id)</em></td>
|
||||
<td>{{provider.apiParams.subAuthId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">认证密码<em>(auth-password)</em></td>
|
||||
<td>{{provider.apiParams.authPassword}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- DNS.COM -->
|
||||
<tbody v-if="provider.type == 'dnscom'">
|
||||
<tr>
|
||||
<td class="color-border">API Key</td>
|
||||
<td>{{provider.apiParams.key}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">API Secret</td>
|
||||
<td>{{provider.apiParams.secret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
<!-- DNS.LA -->
|
||||
<tbody v-if="provider.type == 'dnsla'">
|
||||
<tr>
|
||||
<td class="color-border">API ID</td>
|
||||
<td>{{provider.apiParams.apiId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">API密钥</td>
|
||||
<td>{{provider.apiParams.secret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- VolcEngine -->
|
||||
<tbody v-if="provider.type == 'volcEngine'">
|
||||
<tr>
|
||||
<td class="color-border">Access Key ID</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">Secret Access Key</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Amazon Route 53 -->
|
||||
<tbody v-if="provider.type == 'amazonRoute53'">
|
||||
<tr>
|
||||
<td class="color-border">Access Key ID</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">Secret Access Key</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">API区域</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.region != null && provider.apiParams.region.length > 0">{{provider.apiParams.region}}</span>
|
||||
<span v-else class="disabled">暂未设置</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody v-if="provider.type == 'azureDNS'">
|
||||
<tr>
|
||||
<td class="color-border">订阅ID <br/><em>(Subscription ID)</em></td>
|
||||
<td>
|
||||
{{provider.apiParams.subscriptionId}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">目录(租户) ID <br/><em>(Directory Tenant ID)</em></td>
|
||||
<td>
|
||||
{{provider.apiParams.tenantId}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">应用程序(客户端) ID <br/><em>(Client ID)</em></td>
|
||||
<td>
|
||||
{{provider.apiParams.clientId}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">客户端密码值 <br/><em>(Client Secret Value)</em></td>
|
||||
<td>
|
||||
{{provider.apiParams.clientSecret}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">资源组 <br/><em>(Resource Group Name)</em></td>
|
||||
<td>
|
||||
{{provider.apiParams.resourceGroupName}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- bunny.net -->
|
||||
<tbody v-if="provider.type == 'bunnyNet'">
|
||||
<tr>
|
||||
<td class="color-border">API密钥</td>
|
||||
<td>
|
||||
{{provider.apiParams.apiKey}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Local EdgeDNS -->
|
||||
<tbody v-if="provider.type == 'localEdgeDNS'">
|
||||
<tr>
|
||||
<td class="color-border">域名服务集群</td>
|
||||
<td>
|
||||
{{provider.localEdgeDNS.name}}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- EdgeDNS API -->
|
||||
<tbody v-if="provider.type == 'edgeDNSAPI'">
|
||||
<tr>
|
||||
<td class="color-border">API地址</td>
|
||||
<td>{{provider.apiParams.host}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">AccessKey类型</td>
|
||||
<td>
|
||||
<span v-if="provider.apiParams.role == 'user'">平台用户</span>
|
||||
<span v-if="provider.apiParams.role == 'admin'">管理员</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">AccessKey ID</td>
|
||||
<td>{{provider.apiParams.accessKeyId}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">AccessKey密钥</td>
|
||||
<td>{{provider.apiParams.accessKeySecret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- CustomHTTP -->
|
||||
<tbody v-if="provider.type == 'customHTTP'">
|
||||
<tr>
|
||||
<td class="color-border">HTTP URL</td>
|
||||
<td>{{provider.apiParams.url}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="color-border">私钥</td>
|
||||
<td>{{provider.apiParams.secret}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tr v-if="provider.minTTL > 0">
|
||||
<td>最小TTL</td>
|
||||
<td>{{provider.minTTL}}秒</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h4>管理的域名 <a href="" @click.prevent="syncDomains()" style="font-size: 0.8em">[刷新域名]</a> <a href="" @click.prevent="createDomain()" style="font-size: 0.8em">[添加域名]</a></h4>
|
||||
|
||||
<p class="ui message blue" v-if="isUpdatingDomains">正在检查域名状态...</p>
|
||||
|
||||
<second-menu>
|
||||
<menu-item :href="'/dns/providers/provider?providerId=' + provider.id + '&filter='" :active="filter == ''">正常状态</menu-item>
|
||||
<menu-item :href="'/dns/providers/provider?providerId=' + provider.id + '&filter=down'" :active="filter == 'down'">已下线</menu-item>
|
||||
<menu-item :href="'/dns/providers/provider?providerId=' + provider.id + '&filter=deleted'" :active="filter == 'deleted'">已删除</menu-item>
|
||||
</second-menu>
|
||||
|
||||
<p class="comment" v-if="domains.length == 0">暂时还没有<span v-if="filter == 'deleted'">已删除</span><span v-if="filter == 'down'">已下线</span><span v-if="filter == ''">可以管理</span>的域名。</p>
|
||||
|
||||
<table class="ui table selectable celled" v-if="domains.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>域名</th>
|
||||
<th class="center" style="width: 7em">线路</th>
|
||||
<th class="center" style="width: 6em">集群</th>
|
||||
<th class="center" style="width: 7em">节点域名</th>
|
||||
<th class="center" style="width: 7em">网站域名</th>
|
||||
<th>数据更新时间</th>
|
||||
<th class="center width10">状态</th>
|
||||
<th class="three op">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="(domain, index) in domains">
|
||||
<td>{{domain.name}}</td>
|
||||
<td class="center">
|
||||
<a href="" v-if="domain.countRoutes > 0" @click.prevent="showRoutes(domain.id)">{{domain.countRoutes}}个<popup-icon></popup-icon></a>
|
||||
<span v-else class="disabled">0个</span>
|
||||
</td>
|
||||
<td class="center">
|
||||
<a href="" v-if="domain.countClusters > 0" @click.prevent="viewClusters(domain.id)">{{domain.countClusters}}<popup-icon></popup-icon></a>
|
||||
<span v-else class="disabled">0个</span>
|
||||
</td>
|
||||
<td class="center">
|
||||
<a href="" v-if="domain.countAllNodes > 0" @click.prevent="viewNodes(domain.id)">{{domain.countNodeRecords}}/{{domain.countAllNodes}}个<popup-icon></popup-icon></a>
|
||||
<span v-else class="disabled">0个</span>
|
||||
</td>
|
||||
<td class="center">
|
||||
<a href="" v-if="domain.countAllServers > 0" @click.prevent="viewServers(domain.id)">{{domain.countServerRecords}}/{{domain.countAllServers}}个<popup-icon></popup-icon></a>
|
||||
<span v-else class="disabled">0个</span>
|
||||
</td>
|
||||
<td>
|
||||
<span v-if="domain.dataUpdatedTime.length > 0">{{domain.dataUpdatedTime}}</span>
|
||||
<span v-else class="disabled">尚未更新</span>
|
||||
</td>
|
||||
<td class="center">
|
||||
<span v-if="!domain.isOn"><label-on :v-is-on="domain.isOn"></label-on></span>
|
||||
<div v-else-if="domain.countRoutes == 0 || domain.nodesChanged || domain.serversChanged">
|
||||
<a href="" style="border-bottom: 1px #db2828 dashed" title="点击和DNS服务商系统同步" @click.prevent="syncDomain(index,domain)" v-if="!domain.isSyncing"><span class="red">需要同步</span></a>
|
||||
<span v-else>正在同步...</span>
|
||||
</div>
|
||||
<div v-else-if="!domain.isUp">
|
||||
<a href="" style="border-bottom: 1px #db2828 dashed" @click.prevent="alertDown"><span class="red">已下线</span></a>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a href="" @click.prevent="syncDomain(index, domain)" v-if="!domain.isSyncing">同步</a>
|
||||
<span v-else>正在同步...</span>
|
||||
<a href="" @click.prevent="updateDomain(domain.id)" v-if="!domain.isSyncing">修改</a>
|
||||
<a href="" @click.prevent="deleteDomain(domain)" v-if="!domain.isSyncing && !domain.isDeleted">删除</a>
|
||||
<a href="" @click.prevent="recoverDomain(domain)" v-if="!domain.isSyncing && domain.isDeleted">恢复</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<page-box></page-box>
|
||||
139
EdgeUser/web/views/@default/dns/providers/provider.js
Normal file
139
EdgeUser/web/views/@default/dns/providers/provider.js
Normal file
@@ -0,0 +1,139 @@
|
||||
Tea.context(function () {
|
||||
this.isUpdatingDomains = false
|
||||
this.hasDeletedDomains = this.domains.$find(function (k, v) {
|
||||
return v.isDeleted
|
||||
}) != null
|
||||
|
||||
this.$delay(function () {
|
||||
if (this.pageNo <= 1 && this.filter.length == 0) {
|
||||
this.syncDomains()
|
||||
}
|
||||
})
|
||||
|
||||
this.syncDomains = function () {
|
||||
this.isUpdatingDomains = true
|
||||
this.$post(".syncDomains")
|
||||
.params({
|
||||
providerId: this.provider.id
|
||||
})
|
||||
.success(function (resp) {
|
||||
if (resp.data.hasChanges) {
|
||||
teaweb.reload()
|
||||
}
|
||||
})
|
||||
.done(function () {
|
||||
this.$delay(function () {
|
||||
this.isUpdatingDomains = false
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
this.updateProvider = function (providerId) {
|
||||
teaweb.popup(Tea.url(".updatePopup?providerId=" + providerId), {
|
||||
height: "28em",
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.createDomain = function () {
|
||||
teaweb.popup("/dns/domains/createPopup?providerId=" + this.provider.id, {
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.updateDomain = function (domainId) {
|
||||
teaweb.popup("/dns/domains/updatePopup?domainId=" + domainId, {
|
||||
callback: function () {
|
||||
teaweb.success("保存成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteDomain = function (domain) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除域名\"" + domain.name + "\"吗?", function () {
|
||||
that.$post("/dns/domains/delete")
|
||||
.params({
|
||||
domainId: domain.id
|
||||
})
|
||||
.post()
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
this.recoverDomain = function (domain) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要恢复域名\"" + domain.name + "\"吗?", function () {
|
||||
that.$post("/dns/domains/recover")
|
||||
.params({
|
||||
domainId: domain.id
|
||||
})
|
||||
.post()
|
||||
.refresh()
|
||||
})
|
||||
}
|
||||
|
||||
this.syncDomain = function (index, domain) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要同步此域名下的所有解析记录吗?", function () {
|
||||
domain.isSyncing = true
|
||||
Vue.set(that.domains, index, domain)
|
||||
|
||||
this.$post("/dns/domains/sync")
|
||||
.params({
|
||||
domainId: domain.id
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.success("同步成功", function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
.fail(function (resp) {
|
||||
teaweb.warn(resp.message, function () {
|
||||
if (resp.data.shouldFix) {
|
||||
window.location = "/dns/issues"
|
||||
}
|
||||
})
|
||||
})
|
||||
.done(function () {
|
||||
Vue.set(that.domains, index, domain)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.showRoutes = function (domainId) {
|
||||
teaweb.popup("/dns/domains/routesPopup?domainId=" + domainId)
|
||||
}
|
||||
|
||||
this.viewClusters = function (domainId) {
|
||||
teaweb.popup("/dns/domains/clustersPopup?domainId=" + domainId)
|
||||
}
|
||||
|
||||
this.viewNodes = function (domainId) {
|
||||
teaweb.popup("/dns/domains/nodesPopup?domainId=" + domainId, {
|
||||
width: "50em",
|
||||
height: "30em"
|
||||
})
|
||||
}
|
||||
|
||||
this.viewServers = function (domainId) {
|
||||
teaweb.popup("/dns/domains/serversPopup?domainId=" + domainId, {
|
||||
width: "50em",
|
||||
height: "30em"
|
||||
})
|
||||
}
|
||||
|
||||
this.alertDown = function () {
|
||||
teaweb.popupTip("当前域名已从服务商下线")
|
||||
}
|
||||
})
|
||||
418
EdgeUser/web/views/@default/dns/providers/updatePopup.html
Normal file
418
EdgeUser/web/views/@default/dns/providers/updatePopup.html
Normal file
@@ -0,0 +1,418 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改DNS服务商账号</h3>
|
||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
|
||||
<csrf-token></csrf-token>
|
||||
<input type="hidden" name="providerId" :value="provider.id"/>
|
||||
<input type="hidden" name="type" :value="provider.type"/>
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">账号说明 *</td>
|
||||
<td>
|
||||
<input type="text" name="name" maxlength="50" ref="focus" v-model="provider.name"/>
|
||||
<p class="comment">用来方便区分不同的账号。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>服务商厂家 *</td>
|
||||
<td>
|
||||
{{provider.typeName}}
|
||||
<p class="comment">{{typeDescription}}创建后无法修改此选项。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">API参数</td>
|
||||
</tr>
|
||||
|
||||
<!-- DNSPod -->
|
||||
<tbody v-if="provider.type == 'dnspod'">
|
||||
<tr>
|
||||
<td>密钥类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramDNSPodAPIType" v-model="provider.params.apiType">
|
||||
<option value="tencentDNS">腾讯云API密钥</option>
|
||||
<option value="dnsPodToken">DNSPod Token</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="provider.params.apiType == 'tencentDNS'">
|
||||
<td>SecretId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodAccessKeyId" maxlength="100" v-model="provider.params.accessKeyId"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="provider.params.apiType == 'tencentDNS'">
|
||||
<td>SecretKey *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodAccessKeySecret" maxlength="100" v-model="provider.params.accessKeySecret"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥”中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="provider.params.apiType == null || provider.params.apiType.length == 0 || provider.params.apiType == 'dnsPodToken'">
|
||||
<td>密钥ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodId" maxlength="100" v-model="provider.params.id"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥--DNSPod Token”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="provider.params.apiType == null || provider.params.apiType.length == 0 || provider.params.apiType == 'dnsPodToken'">
|
||||
<td>密钥Token *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSPodToken" maxlength="100" v-model="provider.params.token" spellcheck="false"/>
|
||||
<p class="comment">在DNSPod控制台“账号中心--API密钥--DNSPod Token”中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="provider.params.apiType == null || provider.params.apiType.length == 0 || provider.params.apiType == 'dnsPodToken'">
|
||||
<td>区域</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramDNSPodRegion" v-model="provider.params.region">
|
||||
<option value="">中国站</option>
|
||||
<option value="international">国际站</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- AliDNS -->
|
||||
<tbody v-if="provider.type == 'alidns'">
|
||||
<tr>
|
||||
<td>AccessKeyId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSAccessKeyId" maxlength="100" v-model="provider.params.accessKeyId" spellcheck="false"/>
|
||||
<p class="comment">登录阿里云控制台 -- 在"访问控制"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSAccessKeySecret" maxlength="100" v-model="provider.params.accessKeySecret" spellcheck="false"/>
|
||||
<p class="comment">登录阿里云控制台 -- 在"访问控制"中创建和获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>区域ID<optional-label></optional-label></td>
|
||||
<td>
|
||||
<input type="text" name="paramAliDNSRegionId" maxlength="100" v-model="provider.params.regionId"/>
|
||||
<p class="comment">阿里云产品所在区域代号,通常不需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 华为云 -->
|
||||
<tbody v-if="provider.type == 'huaweiDNS'">
|
||||
<tr>
|
||||
<td>AccessKeyId *</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiAccessKeyId" maxlength="100" v-model="provider.params.accessKeyId" spellcheck="false"/>
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKeySecret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiAccessKeySecret" maxlength="100" v-model="provider.params.accessKeySecret" spellcheck="false"/>
|
||||
<p class="comment">登录华为云控制台 -- 在"我的凭证 -- 访问密钥"中创建和获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>终端节点</td>
|
||||
<td>
|
||||
<input type="text" name="paramHuaweiEndpoint" maxlength="100" v-model="provider.params.endpoint" spellcheck="false"/>
|
||||
<p class="comment">选填项。可以填写终端节点(Endpoint)区域代号或者域名,参考 <a href="https://developer.huaweicloud.com/endpoint?DNS" target="_blank">https://developer.huaweicloud.com/endpoint?DNS</a>(如果此链接失效,请到华为云开发者中心自行查找)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
<!-- CloudFlare -->
|
||||
<tbody v-if="provider.type == 'cloudFlare'">
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCloudFlareAPIKey" maxlength="100" v-model="provider.params.apiKey" spellcheck="false"/>
|
||||
<p class="comment">在个人资料中的"API令牌"--"API密钥"--"Global API Key"中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>账号邮箱 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCloudFlareEmail" maxlength="100" v-model="provider.params.email" spellcheck="false"/>
|
||||
<p class="comment">登录账号使用的邮箱。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- GoDaddy -->
|
||||
<tbody v-if="provider.type == 'godaddy'">
|
||||
<tr>
|
||||
<td>Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGoDaddyKey" maxlength="100" v-model="provider.params.key" spellcheck="false"/>
|
||||
<p class="comment">可以在GoDaddy<a href="https://developer.godaddy.com/keys" target="_blank">开发者中心</a>创建,创建时Environment选择Production。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGoDaddySecret" maxlength="100" v-model="provider.params.secret" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- ClouDNS -->
|
||||
<tbody v-if="provider.type == 'cloudns'">
|
||||
<tr>
|
||||
<td>用户认证ID<em>(auth-id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="paramClouDNSAuthId" maxlength="20" v-model="provider.params.authId" spellcheck="false"/>
|
||||
<p class="comment">和子用户认证ID二选一。可以在ClouDNS<a href="https://www.cloudns.net/api-settings/" target="_blank">API设置页面</a>添加。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>子用户认证ID<em>(sub-auth-id)</em></td>
|
||||
<td>
|
||||
<input type="text" name="paramClouDNSSubAuthId" maxlength="20" v-model="provider.params.subAuthId"/>
|
||||
<p class="comment">和用户认证ID二选一。可以在ClouDNS<a href="https://www.cloudns.net/api-settings/" target="_blank">API设置页面</a>添加。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>认证密码 *<em>(auth-password)</em></td>
|
||||
<td>
|
||||
<input type="password" name="paramClouDNSAuthPassword" maxlength="100" v-model="provider.params.authPassword" spellcheck="false"/>
|
||||
<p class="comment">用户或者子用户的认证密码。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- DNS.COM -->
|
||||
<tbody v-if="provider.type == 'dnscom'">
|
||||
<tr>
|
||||
<td>API Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSComKey" maxlength="100" v-model="provider.params.key" spellcheck="false"/>
|
||||
<p class="comment">在51DNS.COM控制台账号中心--API设置中创建和查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSComSecret" maxlength="100" v-model="provider.params.secret" spellcheck="false"/>
|
||||
<p class="comment">在51DNS.COM控制台账号中心--API设置中创建和查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- DNS.LA -->
|
||||
<tbody v-if="provider.type == 'dnsla'">
|
||||
<tr>
|
||||
<td>API ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSLaAPIId" maxlength="100" v-model="provider.params.apiId" spellcheck="false"/>
|
||||
<p class="comment">在DNS.LA控制台--账户信息中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramDNSLaSecret" maxlength="100" v-model="provider.params.secret" spellcheck="false"/>
|
||||
<p class="comment">在DNS.LA控制台--账户信息中查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- VolcEngine -->
|
||||
<tbody v-if="provider.type == 'volcEngine'">
|
||||
<tr>
|
||||
<td>Access Key ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramVolcEngineAccessKeyId" maxlength="100" v-model="provider.params.accessKeyId" spellcheck="false"/>
|
||||
<p class="comment">在火山引擎“访问控制--API访问密钥”中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramVolcEngineAccessKeySecret" maxlength="100" v-model="provider.params.accessKeySecret" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Amazon Route 53 -->
|
||||
<tbody v-if="provider.type == 'amazonRoute53'">
|
||||
<tr>
|
||||
<td>Access Key ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53AccessKeyId" maxlength="100" v-model="provider.params.accessKeyId" spellcheck="false"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Secret Access Key *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53AccessKeySecret" maxlength="100" v-model="provider.params.accessKeySecret" spellcheck="false"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API区域</td>
|
||||
<td>
|
||||
<input type="text" name="paramAmazonRoute53Region" maxlength="100" v-model="provider.params.region" spellcheck="false"/>
|
||||
<p class="comment">通常不需要填写。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Microsoft Azure DNS -->
|
||||
<tbody v-if="provider.type == 'azureDNS'">
|
||||
<tr>
|
||||
<td>订阅ID <br/><em>(Subscription ID)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSSubscriptionId" maxlength="100" v-model="provider.params.subscriptionId" spellcheck="false"/>
|
||||
<p class="comment">可以在订阅(Subscriptions)服务中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>目录(租户) ID <br/><em>(Directory Tenant ID)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSTenantId" maxlength="100" v-model="provider.params.tenantId" spellcheck="false"/>
|
||||
<p class="comment">可以在应用注册(App registrations)中对应应用概述(Overview)中查看。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>应用程序(客户端) ID <br/><em>(Client ID)</em> *</td>
|
||||
<td><input type="text" name="paramAzureDNSClientId" maxlength="100" v-model="provider.params.clientId" spellcheck="false"/>
|
||||
<p class="comment">需要在应用注册(App registrations)中新注册应用程序获得。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>客户端密码值 <br/><em>(Client Secret Value)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSClientSecret" maxlength="100" v-model="provider.params.clientSecret" spellcheck="false"/>
|
||||
<p class="comment">可以在应用注册(App registrations)中对应应用的“证书和密码(Certificates & secrets)”--“客户端密码(Client secrets)”中创建和查看。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>资源组 <br/><em>(Resource Group Name)</em> *</td>
|
||||
<td>
|
||||
<input type="text" name="paramAzureDNSResourceGroupName" maxlength="100" v-model="provider.params.resourceGroupName" spellcheck="false"/>
|
||||
<p class="comment">权限设置帮助:你需要在对应资源组(Resource group)-- 访问控制(Access control (IAM))-- 角色分配(Role assignments)中添加一个角色分配(Role assignment),其中作业职能角色(Job function roles)为"DNS 区域参与者(DNS Zone Contributor)",成员(Members)为应用注册(App registrations)中的应用程序(application)(有时需要在选择成员(select members)界面搜索应用程序(application)名称才能看到)。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- bunny.net -->
|
||||
<tbody v-if="provider.type == 'bunnyNet'">
|
||||
<tr>
|
||||
<td>API密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramBunnyNetAPIKey" maxlength="100" spellcheck="false" v-model="provider.params.apiKey"/>
|
||||
<p class="comment">在"Edit account details" -- "API Key"中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- Gname -->
|
||||
<tbody v-if="provider.type == 'gname'">
|
||||
<tr>
|
||||
<td>APPID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGnameAppid" maxlength="100" v-model="provider.params.appid" spellcheck="false"/>
|
||||
<p class="comment">在Gname控制台API设置中获取。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>API Secret *</td>
|
||||
<td>
|
||||
<input type="text" name="paramGnameSecret" maxlength="100" v-model="provider.params.secret" spellcheck="false"/>
|
||||
<p class="comment">在Gname控制台API设置中获取。<mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- EdgeDNS -->
|
||||
<tbody v-if="provider.type == 'localEdgeDNS'">
|
||||
<tr>
|
||||
<td>选择域名服务集群 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramLocalEdgeDNSClusterId" v-model="provider.params.clusterId">
|
||||
<option value="0">[选择域名服务集群]</option>
|
||||
<option v-for="cluster in nsClusters" :value="cluster.id">{{cluster.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
|
||||
<!-- EdgeDNS API -->
|
||||
<tbody v-if="provider.type == 'edgeDNSAPI'">
|
||||
<tr>
|
||||
<td>API地址 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIHost" maxlength="100" v-model="provider.params.host"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey类型 *</td>
|
||||
<td>
|
||||
<select class="ui dropdown auto-width" name="paramEdgeDNSAPIRole" v-model="provider.params.role">
|
||||
<option value="user">平台用户</option>
|
||||
<option value="admin">管理员</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey ID *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIAccessKeyId" maxlength="64" v-model="provider.params.accessKeyId"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AccessKey密钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramEdgeDNSAPIAccessKeySecret" maxlength="64" v-model="provider.params.accessKeySecret"/>
|
||||
<p class="comment"><mask-warning></mask-warning></p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 自定义HTTP-->
|
||||
<tbody v-if="provider.type == 'customHTTP'">
|
||||
<tr>
|
||||
<td>HTTP URL *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCustomHTTPURL" maxlength="200" v-model="provider.params.url"/>
|
||||
<p class="comment">HTTP URL完整地址,DNS所有操作都会以POST的方式转发到此地址。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>私钥 *</td>
|
||||
<td>
|
||||
<input type="text" name="paramCustomHTTPSecret" maxlength="64" v-model="provider.params.secret"/>
|
||||
<p class="comment">通讯用的私钥,转发请求时会在Header中加入相关信息,方便开发者校验请求是否合法。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<!-- 更多选项 -->
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>最小TTL</td>
|
||||
<td>
|
||||
<div class="ui right labeled input">
|
||||
<input type="text" name="minTTL" size="4" maxlength="6" style="width: 6em" v-model="provider.minTTL"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">生成的DNS时可以使用的最小TTL,请根据你选择的服务商和你在服务商中的账号等级进行填写;不填写或者0表示默认。</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
15
EdgeUser/web/views/@default/dns/providers/updatePopup.js
Normal file
15
EdgeUser/web/views/@default/dns/providers/updatePopup.js
Normal file
@@ -0,0 +1,15 @@
|
||||
Tea.context(function () {
|
||||
this.typeDescription = ""
|
||||
|
||||
let that = this
|
||||
this.types.forEach(function (v) {
|
||||
if (v.code == that.provider.type) {
|
||||
that.typeDescription = v.description
|
||||
}
|
||||
})
|
||||
|
||||
// DNSPod
|
||||
if (this.provider.type == "dnspod" && this.provider.params != null && (this.provider.params.apiType == null || this.provider.params.apiType.length == 0)) {
|
||||
this.provider.params.apiType = "dnsPodToken"
|
||||
}
|
||||
})
|
||||
6
EdgeUser/web/views/@default/dns/tasks/listPopup.css
Normal file
6
EdgeUser/web/views/@default/dns/tasks/listPopup.css
Normal file
@@ -0,0 +1,6 @@
|
||||
h3 span {
|
||||
margin-left: 0.5em;
|
||||
color: grey;
|
||||
font-size: 0.6em !important;
|
||||
}
|
||||
/*# sourceMappingURL=listPopup.css.map */
|
||||
1
EdgeUser/web/views/@default/dns/tasks/listPopup.css.map
Normal file
1
EdgeUser/web/views/@default/dns/tasks/listPopup.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["listPopup.less"],"names":[],"mappings":"AAAA,EAAG;EACF,kBAAA;EACA,WAAA;EACA,2BAAA","file":"listPopup.css"}
|
||||
43
EdgeUser/web/views/@default/dns/tasks/listPopup.html
Normal file
43
EdgeUser/web/views/@default/dns/tasks/listPopup.html
Normal file
@@ -0,0 +1,43 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>正在同步的DNS任务<span v-if="tasks.length > 0">(共{{tasks.length}}个)</span></h3>
|
||||
<p class="comment" v-if="tasks.length == 0">暂时没有同步的任务。</p>
|
||||
<div v-if="tasks.length > 0">
|
||||
<button class="ui button tiny basic" @click.prevent="deleteAllTasks">清空所有任务</button>
|
||||
|
||||
<table class="ui table selectable celled">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="three wide">对象</th>
|
||||
<th>任务</th>
|
||||
<th>状态</th>
|
||||
<th>触发时间</th>
|
||||
<th class="one op"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="task in tasks">
|
||||
<td nowrap="">
|
||||
<span v-if="(task.type == 'clusterChange' || task.type == 'clusterNodesChange' || task.type == 'clusterRemoveDomain') && task.cluster != null">{{task.cluster.name}}
|
||||
<link-icon :href="'/dns/clusters/cluster?clusterId=' + task.cluster.id" target="_top"></link-icon>
|
||||
</span>
|
||||
<span v-if="task.type == 'nodeChange'">{{task.node.name}}</span>
|
||||
<span v-if="task.type == 'serverChange'">{{task.server.name}}</span>
|
||||
<span v-if="task.type == 'domainChange'">{{task.domain.name}}</span>
|
||||
</td>
|
||||
<td nowrap="">
|
||||
<span v-if="task.type == 'clusterChange' || task.type == 'clusterNodesChange' || task.type == 'clusterRemoveDomain'">集群</span>
|
||||
<span v-if="task.type == 'nodeChange'">节点</span>
|
||||
<span v-if="task.type == 'serverChange'">网站</span>
|
||||
<span v-if="task.type == 'domainChange'">域名</span>
|
||||
</td>
|
||||
<td style="word-break: break-word; width: 26em">
|
||||
<span v-if="task.isDone" class="red">{{task.error}}</span>
|
||||
<span v-else>正在同步...</span>
|
||||
</td>
|
||||
<td nowrap="">{{task.updatedTime}}</td>
|
||||
<td>
|
||||
<a href="" title="删除" class="remove-btn" @click.prevent="deleteTask(task.id)"><i class="icon remove small grey"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
40
EdgeUser/web/views/@default/dns/tasks/listPopup.js
Normal file
40
EdgeUser/web/views/@default/dns/tasks/listPopup.js
Normal file
@@ -0,0 +1,40 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
this.reload()
|
||||
})
|
||||
|
||||
this.reload = function () {
|
||||
this.$post("$")
|
||||
.success(function (resp) {
|
||||
this.tasks = resp.data.tasks
|
||||
})
|
||||
.done(function () {
|
||||
this.$delay(function () {
|
||||
this.reload()
|
||||
}, 3000)
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteTask = function (taskId) {
|
||||
let that = this
|
||||
teaweb.confirm("确定要删除这个任务吗?", function () {
|
||||
that.$post(".delete")
|
||||
.params({
|
||||
taskId: taskId
|
||||
})
|
||||
.success(function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
this.deleteAllTasks = function () {
|
||||
let that = this
|
||||
teaweb.confirm("确定要清空所有的任务吗?", function () {
|
||||
that.$post(".deleteAll")
|
||||
.success(function () {
|
||||
teaweb.reload()
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
5
EdgeUser/web/views/@default/dns/tasks/listPopup.less
Normal file
5
EdgeUser/web/views/@default/dns/tasks/listPopup.less
Normal file
@@ -0,0 +1,5 @@
|
||||
h3 span {
|
||||
margin-left: 0.5em;
|
||||
color: grey;
|
||||
font-size: 0.6em !important;
|
||||
}
|
||||
104
EdgeUser/web/views/@default/dns/updateClusterPopup.html
Normal file
104
EdgeUser/web/views/@default/dns/updateClusterPopup.html
Normal file
@@ -0,0 +1,104 @@
|
||||
{$layout "layout_popup"}
|
||||
|
||||
<h3>修改集群DNS设置</h3>
|
||||
|
||||
<form method="post" class="ui form" data-tea-success="success" data-tea-action="$">
|
||||
<input type="hidden" name="clusterId" :value="clusterId"/>
|
||||
<csrf-token></csrf-token>
|
||||
|
||||
<table class="ui table definition selectable">
|
||||
<tr>
|
||||
<td class="title">DNS服务商</td>
|
||||
<td>
|
||||
<select name="providerType" class="ui dropdown auto-width" v-model="providerType" @change="changeProviderType">
|
||||
<option v-for="providerType in providerTypes" :value="providerType.code">{{providerType.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>账号</td>
|
||||
<td>
|
||||
<p class="comment" v-if="providers.length == 0">没有账号可选</p>
|
||||
<select name="providerId" class="ui dropdown auto-width" v-model="providerId" v-show="providers.length > 0">
|
||||
<option v-for="provider in providers" :value="provider.id">{{provider.name}}</option>
|
||||
</select>
|
||||
<p class="comment"><a href="/dns/providers" target="_blank">去管理DNS服务商账号»</a></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="providerId > 0">
|
||||
<td>域名</td>
|
||||
<td>
|
||||
<p class="comment" v-if="domains.length == 0">没有域名可选</p>
|
||||
<select name="domainId" class="ui dropdown auto-width" v-model="domainId" v-show="domains.length > 0">
|
||||
<option v-for="domain in domains" :value="domain.id">{{domain.name}}</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>子域名</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" name="dnsName" v-model="dnsName" maxlength="64" size="20" style="width:10em"/>
|
||||
<span class="ui label">.<span v-if="domain.length == 0">主域名</span><span v-else>{{domain}}</span></span>
|
||||
</div>
|
||||
<p class="comment">子域名和主域名共同组成集群的域名。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>自动设置CNAME记录</td>
|
||||
<td>
|
||||
<values-box :values="cnameRecords" name="cnameRecords" placeholder="记录名" ref="cnameRecords"></values-box>
|
||||
<p class="comment">除集群已创建的网站之外,自动解析到集群的CNAME记录,比如<code-label @click.prevent="addCnameRecord('www')">www</code-label>。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"><more-options-indicator></more-options-indicator></td>
|
||||
</tr>
|
||||
<tbody v-show="moreOptionsVisible">
|
||||
<tr>
|
||||
<td>允许通过CNAME访问网站</td>
|
||||
<td>
|
||||
<checkbox name="cnameAsDomain" v-model="cnameAsDomain"></checkbox>
|
||||
<p class="comment">选中后,表示允许使用CNAME直接访问网站;如果取消选中,则表示CNAME只作为DNS解析记录使用。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-show="teaIsPlus">
|
||||
<td>包含Ln节点</td>
|
||||
<td>
|
||||
<checkbox name="includingLnNodes" v-model="includingLnNodes"></checkbox>
|
||||
<p class="comment">选中后,表示域名解析中包含L2及以上级别节点,也就意味着用户请求可能会被分配到这些节点。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>记录TTL</td>
|
||||
<td>
|
||||
<div class="ui input right labeled">
|
||||
<input type="text" name="ttl" maxlength="6" style="width: 6em" v-model="ttl"/>
|
||||
<span class="ui label">秒</span>
|
||||
</div>
|
||||
<p class="comment">每个DNS服务商或者账号的TTL限制各有不同,请注意取值范围;修改后,只对新的解析记录生效。0表示使用默认。</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>同步节点DNS状态</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="nodesAutoSync" value="1" v-model="nodesAutoSync"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>同步网站DNS状态</td>
|
||||
<td>
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="serversAutoSync" value="1" v-model="serversAutoSync"/>
|
||||
<label></label>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<submit-btn></submit-btn>
|
||||
</form>
|
||||
87
EdgeUser/web/views/@default/dns/updateClusterPopup.js
Normal file
87
EdgeUser/web/views/@default/dns/updateClusterPopup.js
Normal file
@@ -0,0 +1,87 @@
|
||||
Tea.context(function () {
|
||||
this.$delay(function () {
|
||||
this.changeProviderType()
|
||||
this.changeProvider()
|
||||
|
||||
this.$watch("providerId", function () {
|
||||
this.changeProvider()
|
||||
})
|
||||
this.$watch("domainId", function () {
|
||||
this.changeDomain()
|
||||
})
|
||||
})
|
||||
|
||||
this.success = NotifyPopup
|
||||
|
||||
// 初始化的内容
|
||||
// this.domainId = 0
|
||||
// this.domain = ""
|
||||
// this.providerId = 0
|
||||
|
||||
if (this.providerType == "") {
|
||||
this.providerType = this.providerTypes[0].code
|
||||
}
|
||||
this.providers = []
|
||||
this.domains = []
|
||||
|
||||
this.changeProviderType = function () {
|
||||
this.$post(".providerOptions")
|
||||
.params({
|
||||
type: this.providerType
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.providers = resp.data.providers
|
||||
|
||||
// 检查providerId
|
||||
if (this.providers.length == 0) {
|
||||
this.providerId = 0
|
||||
return
|
||||
}
|
||||
let that = this
|
||||
if (this.providers.$find(function (k, v) {
|
||||
return v.id == that.providerId
|
||||
}) == null) {
|
||||
this.providerId = this.providers[0].id
|
||||
}
|
||||
this.changeProvider()
|
||||
})
|
||||
}
|
||||
|
||||
this.changeProvider = function () {
|
||||
this.$post(".domainOptions")
|
||||
.params({
|
||||
providerId: this.providerId
|
||||
})
|
||||
.success(function (resp) {
|
||||
this.domains = resp.data.domains
|
||||
this.changeDomain()
|
||||
})
|
||||
}
|
||||
|
||||
this.changeDomain = function () {
|
||||
if (this.domains.length == 0) {
|
||||
this.domainId = 0
|
||||
this.domain = ""
|
||||
return
|
||||
}
|
||||
|
||||
let domainId = this.domainId
|
||||
let domainInfo = this.domains.$find(function (k, v) {
|
||||
return v.id == domainId
|
||||
})
|
||||
if (domainInfo == null) {
|
||||
// 默认选取第一个
|
||||
this.domainId = this.domains[0].id
|
||||
this.domain = this.domains[0].name
|
||||
} else {
|
||||
this.domain = domainInfo.name
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自动设置CNAME
|
||||
*/
|
||||
this.addCnameRecord = function (name) {
|
||||
this.$refs.cnameRecords.addValue(name)
|
||||
}
|
||||
})
|
||||
85
EdgeUser/web/views/@default/docs/index.css
Normal file
85
EdgeUser/web/views/@default/docs/index.css
Normal file
@@ -0,0 +1,85 @@
|
||||
.doc-box {
|
||||
line-height: 1.8;
|
||||
}
|
||||
.doc-box p {
|
||||
line-height: 1.8;
|
||||
}
|
||||
.doc-box .toc-box {
|
||||
width: 11em;
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
background: #F5F7FA;
|
||||
margin-left: -1em;
|
||||
border-right: 1px #eee solid;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.doc-box .toc-box ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
.doc-box .toc-box ul li {
|
||||
padding-left: 1em;
|
||||
}
|
||||
.doc-box .toc-box ul li li {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.doc-box .toc-box a {
|
||||
color: #333;
|
||||
}
|
||||
.doc-box .toc-box a.active {
|
||||
color: #4183c4;
|
||||
}
|
||||
.doc-box .toc-box.right {
|
||||
top: 3em;
|
||||
right: 1em;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
border-right: none;
|
||||
border-left: 1px #eee solid;
|
||||
background: white;
|
||||
}
|
||||
.doc-box .toc-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
.doc-box .content-box {
|
||||
margin-left: 11em;
|
||||
margin-right: 11em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
.doc-box .content-box img {
|
||||
max-width: 600px;
|
||||
margin-top: 1em;
|
||||
}
|
||||
.doc-box .content-box h1,
|
||||
.doc-box .content-box h2,
|
||||
.doc-box .content-box h3,
|
||||
.doc-box .content-box h4,
|
||||
.doc-box .content-box h5,
|
||||
.doc-box .content-box h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
.doc-box .content-box > ul,
|
||||
.doc-box .content-box > ol {
|
||||
padding-left: 1.2em;
|
||||
}
|
||||
.doc-box .content-box > ul > li > ul,
|
||||
.doc-box .content-box > ol > li > ul {
|
||||
padding-left: 1.6em;
|
||||
}
|
||||
.doc-box .content-box > ul > li > ul > li > ul,
|
||||
.doc-box .content-box > ol > li > ul > li > ul {
|
||||
padding-left: 1.6em;
|
||||
}
|
||||
.doc-box .content-box code {
|
||||
border: 1px #eee solid;
|
||||
padding: 2px 1px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
.doc-box .content-box pre code {
|
||||
border: none;
|
||||
background: #F4F7F9;
|
||||
display: block;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
1
EdgeUser/web/views/@default/docs/index.css.map
Normal file
1
EdgeUser/web/views/@default/docs/index.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.less"],"names":[],"mappings":"AAAA;EACC,gBAAA;;AADD,QAGC;EACC,gBAAA;;AAJF,QAOC;EACC,WAAA;EACA,eAAA;EACA,UAAA;EACA,SAAA;EACA,mBAAA;EACA,iBAAA;EACA,4BAAA;EACA,gBAAA;;AAfF,QAOC,SAUC;EACC,gBAAA;EACA,UAAA;;AAnBH,QAOC,SAUC,GAIC;EACC,iBAAA;;AAtBJ,QAOC,SAUC,GAIC,GAGC;EACC,gBAAA;;AAzBL,QAOC,SAuBC;EACC,WAAA;;AA/BH,QAOC,SA2BC,EAAC;EACA,cAAA;;AAnCH,QAuCC,SAAQ;EACP,QAAA;EACA,UAAA;EACA,SAAA;EACA,WAAA;EACA,kBAAA;EACA,2BAAA;EACA,iBAAA;;AA9CF,QAiDC,SAAQ;EACP,UAAA;;AAlDF,QAqDC;EACC,iBAAA;EACA,kBAAA;EACA,gBAAA;;AAxDF,QAqDC,aAKC;EACC,gBAAA;EACA,eAAA;;AA5DH,QAqDC,aAUC;AA/DF,QAqDC,aAUK;AA/DN,QAqDC,aAUS;AA/DV,QAqDC,aAUa;AA/Dd,QAqDC,aAUiB;AA/DlB,QAqDC,aAUqB;EACnB,mBAAA;;AAhEH,QAqDC,aAcC;AAnEF,QAqDC,aAcO;EACL,mBAAA;;AApEH,QAqDC,aAcC,KAGC,KAAK;AAtER,QAqDC,aAcO,KAGL,KAAK;EACJ,mBAAA;;AAvEJ,QAqDC,aAcC,KAGC,KAAK,KAGJ,KAAK;AAzET,QAqDC,aAcO,KAGL,KAAK,KAGJ,KAAK;EACJ,mBAAA;;AA1EL,QAqDC,aA0BC;EACC,sBAAA;EACA,gBAAA;EACA,gBAAA;;AAlFH,QAqDC,aAgCC,IACC;EACC,YAAA;EACA,mBAAA;EACA,cAAA;EACA,gBAAA","file":"index.css"}
|
||||
9
EdgeUser/web/views/@default/docs/index.html
Normal file
9
EdgeUser/web/views/@default/docs/index.html
Normal file
@@ -0,0 +1,9 @@
|
||||
{$layout}
|
||||
|
||||
<div class="doc-box">
|
||||
<div class="toc-box">{$.rootTOC}</div>
|
||||
<div class="content-box">
|
||||
{$.content}
|
||||
</div>
|
||||
<div class="toc-box right">{$.toc}</div>
|
||||
</div>
|
||||
95
EdgeUser/web/views/@default/docs/index.less
Normal file
95
EdgeUser/web/views/@default/docs/index.less
Normal file
@@ -0,0 +1,95 @@
|
||||
.doc-box {
|
||||
line-height: 1.8;
|
||||
|
||||
p {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.toc-box {
|
||||
width: 11em;
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
background: #F5F7FA;
|
||||
margin-left: -1em;
|
||||
border-right: 1px #eee solid;
|
||||
overflow-y: auto;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
padding-left: 1em;
|
||||
|
||||
li {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
a.active {
|
||||
color: #4183c4;
|
||||
}
|
||||
}
|
||||
|
||||
.toc-box.right {
|
||||
top: 3em;
|
||||
right: 1em;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
border-right: none;
|
||||
border-left: 1px #eee solid;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.toc-box::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
margin-left: 11em;
|
||||
margin-right: 11em;
|
||||
padding-top: 1em;
|
||||
|
||||
img {
|
||||
max-width: 600px;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
> ul, > ol {
|
||||
padding-left: 1.2em;
|
||||
|
||||
> li > ul {
|
||||
padding-left: 1.6em;
|
||||
|
||||
> li > ul {
|
||||
padding-left: 1.6em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
border: 1px #eee solid;
|
||||
padding: 2px 1px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
pre {
|
||||
code {
|
||||
border: none;
|
||||
background: #F4F7F9;
|
||||
display: block;
|
||||
padding: 4px 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
EdgeUser/web/views/@default/email/verify.css
Normal file
32
EdgeUser/web/views/@default/email/verify.css
Normal file
@@ -0,0 +1,32 @@
|
||||
.form-box {
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
form {
|
||||
position: fixed;
|
||||
width: 30em;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -15em;
|
||||
margin-top: -16em;
|
||||
}
|
||||
span.red,
|
||||
pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
.home-link-box {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
a.enabled,
|
||||
span.enabled,
|
||||
span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
h4 {
|
||||
font-weight: normal !important;
|
||||
font-size: 1.2em !important;
|
||||
}
|
||||
/*# sourceMappingURL=verify.css.map */
|
||||
1
EdgeUser/web/views/@default/email/verify.css.map
Normal file
1
EdgeUser/web/views/@default/email/verify.css.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["verify.less"],"names":[],"mappings":"AAAA;EACC,eAAA;EACA,UAAA;EACA,SAAA;EACA,OAAA;EACA,QAAA;;AAGD;EACC,eAAA;EACA,WAAA;EACA,QAAA;EACA,SAAA;EACA,kBAAA;EACA,iBAAA;;AAGD,IAAI;AAAM,GAAG;EACZ,cAAA;;AAGD;EACC,iBAAA;;AAGD,CAAC;AAAU,IAAI;AAAU,IAAI;EAC5B,cAAA;;AAGD;EACC,8BAAA;EACA,gBAAA","file":"verify.css"}
|
||||
37
EdgeUser/web/views/@default/email/verify.html
Normal file
37
EdgeUser/web/views/@default/email/verify.html
Normal file
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
{$if eq .faviconFileId 0}
|
||||
<link rel="shortcut icon" href="/images/favicon.png"/>
|
||||
{$else}
|
||||
<link rel="shortcut icon" href="/ui/image/{$ .faviconFileId}"/>
|
||||
{$end}
|
||||
<title>激活邮箱 - {$.systemName}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
|
||||
{$TEA.VUE}
|
||||
{$TEA.SEMANTIC}
|
||||
<script type="text/javascript" src="/js/md5.min.js"></script>
|
||||
<script type="text/javascript" src="/js/utils.min.js"></script>
|
||||
<script type="text/javascript" src="/js/sweetalert2/dist/sweetalert2.all.min.js"></script>
|
||||
<script type="text/javascript" src="/js/components.js?v=1.0.0"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
{$template "/menu"}
|
||||
|
||||
<div class="form-box">
|
||||
<form>
|
||||
<div v-if="isOk">
|
||||
<h4 class="green"><span class="green">邮箱地址 {{email}} 激活成功!</span></h4>
|
||||
</div>
|
||||
<div v-if="!isOk">
|
||||
<h4><span class="red"><span v-if="email.length > 0">邮箱地址 {{email}} </span>激活失败!</span></h4>
|
||||
<p><span class="red">失败原因:{{errorMessage}}</span></p>
|
||||
</div>
|
||||
<div class="home-link-box">
|
||||
<a href="/login">去登录页 »</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
33
EdgeUser/web/views/@default/email/verify.less
Normal file
33
EdgeUser/web/views/@default/email/verify.less
Normal file
@@ -0,0 +1,33 @@
|
||||
.form-box {
|
||||
position: fixed;
|
||||
top: 2.5em;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
position: fixed;
|
||||
width: 30em;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin-left: -15em;
|
||||
margin-top: -16em;
|
||||
}
|
||||
|
||||
span.red, pre.red {
|
||||
color: #db2828;
|
||||
}
|
||||
|
||||
.home-link-box {
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
a.enabled, span.enabled, span.green {
|
||||
color: #21ba45;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: normal !important;
|
||||
font-size: 1.2em!important;
|
||||
}
|
||||
3
EdgeUser/web/views/@default/finance/bills/@menu.html
Normal file
3
EdgeUser/web/views/@default/finance/bills/@menu.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<first-menu>
|
||||
<menu-item href="/finance/bills" code="index">账单</menu-item>
|
||||
</first-menu>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user