init the project
This commit is contained in:
commit
81e14d12ea
54 files changed
+6829
No files matched your search
@@ -0,0 +1,4 @@
|
||||
#idea file
|
||||
.idea
|
||||
|
||||
dist
|
||||
@@ -0,0 +1,12 @@
|
||||
server{
|
||||
listen 80;
|
||||
server_name tank.zicpo.cn;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:9090;
|
||||
proxy_set_header host $host;
|
||||
proxy_set_header X-Forwarded-For $remote_addr;
|
||||
proxy_pass_request_headers on;
|
||||
client_max_body_size 2048m;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"ServerPort": 9090,
|
||||
"LogToConsole": true,
|
||||
"MysqlPort": 3306,
|
||||
"MysqlHost": "127.0.0.1",
|
||||
"MysqlSchema": "tank",
|
||||
"MysqlUserName": "tank",
|
||||
"MysqlPassword": "tank123",
|
||||
"AdminUsername": "admin",
|
||||
"AdminEmail": "admin@tank.eyeblue.cn",
|
||||
"AdminPassword": "123456"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<!DOCTYPE html><html><head><title>tank-front</title><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport content="user-scalable=no,width=device-width,initial-scale=1,maximum-scale=1"><meta name=msapplication-tap-highlight content=no><meta name=apple-mobile-web-app-capable content=yes><link href=/static/css/app.cfd8f574917fd86fad8effb02f5563b2.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.67df5041971dde987922.js></script><script type=text/javascript src=/static/js/vendor.392879af4bb24a810ba3.js></script><script type=text/javascript src=/static/js/app.64233513a41451689d54.js></script></body></html>
|
||||
@@ -0,0 +1,17 @@
|
||||
/*!
|
||||
* Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome
|
||||
* License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
|
||||
*/@font-face{font-family:FontAwesome;src:url(/static/fonts/fontawesome-webfont.674f50d.eot);src:url(/static/fonts/fontawesome-webfont.674f50d.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(/static/fonts/fontawesome-webfont.af7ae50.woff2) format("woff2"),url(/static/fonts/fontawesome-webfont.fee66e7.woff) format("woff"),url(/static/fonts/fontawesome-webfont.b06871f.ttf) format("truetype"),url(/static/img/fontawesome-webfont.912ec66.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\F000"}.fa-music:before{content:"\F001"}.fa-search:before{content:"\F002"}.fa-envelope-o:before{content:"\F003"}.fa-heart:before{content:"\F004"}.fa-star:before{content:"\F005"}.fa-star-o:before{content:"\F006"}.fa-user:before{content:"\F007"}.fa-film:before{content:"\F008"}.fa-th-large:before{content:"\F009"}.fa-th:before{content:"\F00A"}.fa-th-list:before{content:"\F00B"}.fa-check:before{content:"\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\F00D"}.fa-search-plus:before{content:"\F00E"}.fa-search-minus:before{content:"\F010"}.fa-power-off:before{content:"\F011"}.fa-signal:before{content:"\F012"}.fa-cog:before,.fa-gear:before{content:"\F013"}.fa-trash-o:before{content:"\F014"}.fa-home:before{content:"\F015"}.fa-file-o:before{content:"\F016"}.fa-clock-o:before{content:"\F017"}.fa-road:before{content:"\F018"}.fa-download:before{content:"\F019"}.fa-arrow-circle-o-down:before{content:"\F01A"}.fa-arrow-circle-o-up:before{content:"\F01B"}.fa-inbox:before{content:"\F01C"}.fa-play-circle-o:before{content:"\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\F01E"}.fa-refresh:before{content:"\F021"}.fa-list-alt:before{content:"\F022"}.fa-lock:before{content:"\F023"}.fa-flag:before{content:"\F024"}.fa-headphones:before{content:"\F025"}.fa-volume-off:before{content:"\F026"}.fa-volume-down:before{content:"\F027"}.fa-volume-up:before{content:"\F028"}.fa-qrcode:before{content:"\F029"}.fa-barcode:before{content:"\F02A"}.fa-tag:before{content:"\F02B"}.fa-tags:before{content:"\F02C"}.fa-book:before{content:"\F02D"}.fa-bookmark:before{content:"\F02E"}.fa-print:before{content:"\F02F"}.fa-camera:before{content:"\F030"}.fa-font:before{content:"\F031"}.fa-bold:before{content:"\F032"}.fa-italic:before{content:"\F033"}.fa-text-height:before{content:"\F034"}.fa-text-width:before{content:"\F035"}.fa-align-left:before{content:"\F036"}.fa-align-center:before{content:"\F037"}.fa-align-right:before{content:"\F038"}.fa-align-jusLine truncated
|
||||
* animate.css -http://daneden.me/animate
|
||||
* Version - 3.5.1
|
||||
* Licensed under the MIT license - http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Copyright (c) 2016 Daniel Eden
|
||||
*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{0%,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);transform:translateZ(0)}40%,43%{-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}40%,43%,70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}70%{-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,20%,53%,80%,to{-webkit-animation-timing-function:cubic-bezier(.215,.61,.355,1);animation-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translateZ(0);transform:translateZ(0)}40%,43%{-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}40%,43%,70%{-webkit-animation-timing-function:cubic-bezier(.755,.05,.855,.06);animation-timing-function:cubic-bezier(.755,.05,.855,.06)}70%{-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes pulse{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}@keyframes rubberBand{0%{-webkit-transform:scaleX(1);transform:scaleX(1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}to{-webkit-transform:scaleX(1);transform:scaleX(1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,to{-webkit-transform:translateZ(0);transform:translateZ(0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(3deg)}50%{-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes headShake{0%{-webkit-transform:translateX(0);transform:translateX(0)}6.5%{-webkit-transform:translateX(-6px) rotateY(-9deg);transform:translateX(-6px) rotateY(-9deg)}18.5%{-webkit-transform:translateX(5px) rotateY(7deg);transform:translateX(5px) rotateY(7deg)}31.5%{-webkit-transform:translateX(-3px) rotateY(-5deg);transform:translateX(-3px) rotateY(-5deg)}43.5%{-webkit-transform:translateX(2px) rotateY(3deg);transform:translateX(2px) rotateY(Line truncated
|
||||
/*!
|
||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
||||
* Copyright 2011-2016 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}
|
||||
/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{background:transparent!important;color:#000!important;box-shadow:none!important;text-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}*,:after,:before{box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:Helvetica Neue,Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#676a6c;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#605ca8;text-decoration:none}a:focus,a:hover{color:#434078;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;border-radius:4px;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#777}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-size:18px}.h5,h5{font-size:14px}.h6,h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:300;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}.small,small{font-size:85%}.mark,mark{background-color:#fcf8e3;padding:.2em}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-nowrap{white-space:nowrap}.text-lowercase{text-transform:lowercase}.text-capitalize{text-transform:capitalize}.text-muted{color:#777}a.text-primary:focus,a.text-primary:hover{color:#4c4988}.text-success{color:#3c763d}a.text-success:focus,a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:focus,a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:focus,a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:focus,a.text-danger:hover{color:#843534}a.bg-primary:focus,a.bg-primary:hover{background-color:#4c4988}.bg-success{background-color:#dff0d8}a.bg-success:focus,a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:focus,a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:focus,a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:focus,a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ol,ul{margin-top:0;margin-bottom:10px}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}.list-inline,.list-unstyled{padding-left:0;list-style:none}.list-inline{margin-left:-5px}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}dl{margin-top:0;margin-bottom:20px}dd,dt{line-height:1.42857143}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[data-original-title],abbr[title]{cursor:help;border-Line truncated
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large.
Load diff
|
After Width: | Height: | Size: 434 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
@@ -0,0 +1,10 @@
|
||||
webpackJsonp([1],{"+UqT":function(t,exports){},"+b5G":function(t,exports){},"+o1O":function(t,e,a){"use strict";function injectStyle(t){a("PS7R")}var i=a("ifW5"),n=a("MenX"),s=a("/Xao"),r=injectStyle,o=s(i.a,n.a,!1,r,null,null);e.a=o.exports},"+pNW":function(t,e,a){"use strict";var i=a("SzSZ");e.a={props:{filter:{type:i.a,required:!0,validator:function(t){return t.name?!t.value||null===t.value||!0===t.value||!1===t.value||(console.error("order can only be true,false or null."),console.error(t.value),!1):(console.error("name is required."),!1)}},callback:{type:Function,required:!1}},methods:{change:function(){null===this.filter.value?this.filter.value=!0:this.filter.value=!0!==this.filter.value,this.callback&&this.callback()},clear:function(){this.filter.value=null,this.callback&&this.callback()}}}},"/Amy":function(t,e,a){"use strict";function injectStyle(t){a("nppv")}var i=a("C0Ew"),n=a("Z+Rw"),s=a("/Xao"),r=injectStyle,o=s(i.a,n.a,!1,r,null,null);e.a=o.exports},0:function(t,exports){},"0Dt+":function(t,e,a){"use strict";var i=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[t.pager.loading?t._e():a("div",[a("Multiselect",{attrs:{"tag-placeholder":"选择用户",placeholder:"搜索或选择用户",selectedLabel:"已选",deselectLabel:"点击移除",selectLabel:"点击选择",options:t.options,"custom-label":t.customLabel,multiple:!0,max:1},scopedSlots:t._u([{key:"option",fn:function(e){return[a("div",{staticClass:"option__desc"},[a("span",{staticClass:"option__title"},[t._v(t._s(e.option.username))])])]}}]),model:{value:t.innerTags,callback:function(e){t.innerTags=e},expression:"innerTags"}},[a("span",{staticClass:"italic",attrs:{slot:"maxElements"},slot:"maxElements"},[t._v("\n\t\t\t\t最多只能选择1项\n\t\t\t")]),t._v(" "),a("span",{staticClass:"italic",attrs:{slot:"noResult"},slot:"noResult"},[t._v("\n\t\t\t\t没有符合条件的条目\n\t\t\t")])])],1),t._v(" "),t.pager.loading?a("div",[a("i",{staticClass:"fa fa-spinner fa-spin fa-fw"})]):t._e()])},n=[],s={render:i,staticRenderFns:n};e.a=s},"0Y0o":function(t,e,a){"use strict";var i=a("TWX9"),n=a("my5B"),s=a("uElL"),r=a("6PUn"),o=a("z5U/"),l=(a.n(o),a("d2J/")),c=a("H4Ef"),u=a("NY9V"),p=a("tra3"),d=a.n(p),m=a("neBs");e.a={data:function(){return{ExtensionsType:l.a,ExtensionsTypeMap:l.c,ExtensionsTypeList:l.b,matter:new c.a,pager:new u.a(c.a,50),user:this.$store.state.user,currentUser:new m.a,keywords:"",listData:[],multipleSelection:[]}},props:{matterType:{type:String,required:!0}},components:{NbPager:n.a,UserSelection:s.a,UserInputSelection:r.a},watch:{keywords:function(t,e){t||(this.pager.setFilterValue("name",null),this.refresh())}},methods:{currentUserChange:function(t){t?(this.currentUser.uuid=t.uuid,this.currentUser.httpDetail()):this.currentUser.render(new m.a),this.refresh()},keySearch:function(){this.keywords&&(this.pager.page=0,this.pager.setFilterValue("name",this.keywords),this.refresh())},deleteBatch:function(){var t=this;o.MessageBox.confirm("此操作将永久删除选中文件, 是否继续?","提示",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning",callback:function(e,a){if("confirm"===e){var i="";t.multipleSelection.forEach(function(e,a){a!==t.multipleSelection.length-1?i+=e.uuid+",":i+=e.uuid}),t.matter.httpMatterDeleteBatch(i,function(e){o.Message.success("删除成功!"),t.refresh()},function(t){o.Message.error("删除失败!")})}}})},cellMouseEnter:function(t,e,a,i){t.showOperation=!0},cellMouseLeave:function(t,e,a,i){t.showOperation=!1},selectText:function(t,e,a){if(t.setSelectionRange)t.setSelectionRange(e,a);else if(t.createTextRange){var i=t.createTextRange();i.moveStart("character",e),i.moveEnd("character",a-e),i.select()}t.focus()},renameRow:function(t,e){var a=this;t.renameStatus=!0,setTimeout(function(){var e=d()("#modify");if(t.type){var i=e.val(),n=i.lastIndexOf(".");a.selectText(e.get(0),0,n)}else e.select()},100)},saveRename:function(t){if(t.renameStatus){t.name=d()("#modify").val(),t.httpMatterRename(function(e){o.Message.success("重命名成功!"),t.renameStatus=!1},function(e){o.Message.error(e.data.msg),t.renameStatus=!1,t.httpDetail()})}},downloadRow:function(t){t.type&&window.open(i.default.http.options.root+"/matter/download?uuid="+t.uuid)},deleteRow:function(t){var e=this;o.MessageBox.confirm("此操作将永久删除该文件, 是否继续?","提示",{confirmButtonText:"确定",cancelButtonText:"取消",type:"warning",callback:function(a,i){"confirm"===a&&t.httpMatterDelete(function(t){o.Message.success("删除成功!"),e.refresh()})}})},handleSelectionChange:function(t){this.multipleSelection=t},refresh:function(){var t=this;this.pager.setFilterValue("userUuid",this.currentUser.uuid),this.pager.httpFastPage(function(e){t.listData=t.pager.data})}},created:function(){this.$store.state.route.query.userUuid?this.currentUser.uuid=this.$store.state.route.query.userUuid:this.currentUser.uuid=this.user.uuid,this.currentUser.httpDetail()},mounted:function(){this.Line truncated
|
||||
* iCheck v1.0.2, http://git.io/arlzeA
|
||||
* ===================================
|
||||
* Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization
|
||||
*
|
||||
* (c) 2013 Damir Sultanov, http://fronteed.com
|
||||
* MIT Licensed
|
||||
*/
|
||||
function iCheck($){function operate(t,e,n){var s=t[0],p=/er/.test(n)?l:/bl/.test(n)?r:i,d=n==c?{checked:s[i],disabled:s[r],indeterminate:"true"==t.attr(l)||"false"==t.attr(o)}:s[p];if(/^(ch|di|in)/.test(n)&&!d)on(t,p);else if(/^(un|en|de)/.test(n)&&d)off(t,p);else if(n==c)for(var m in d)d[m]?on(t,m,!0):off(t,m,!0);else e&&"toggle"!=n||(e||t[v]("ifClicked"),d?s[u]!==a&&off(t,p):on(t,p))}function on(n,c,p){var v=n[0],f=n.parent(),g=c==i,A=c==l,w=c==r,y=A?o:g?s:"enabled",x=option(n,y+capitalize(v[u])),b=option(n,c+capitalize(v[u]));if(!0!==v[c]){if(!p&&c==i&&v[u]==a&&v.name){var C=n.closest("form"),k='input[name="'+v.name+'"]';k=C.length?C.find(k):$(k),k.each(function(){this!==v&&$(this).data(t)&&off($(this),c)})}A?(v[c]=!0,v[i]&&off(n,i,"force")):(p||(v[c]=!0),g&&v[l]&&off(n,l,!1)),callbacks(n,g,c,p)}v[r]&&option(n,h,!0)&&f.find("."+e).css(h,"default"),f[d](b||option(n,c)||""),f.attr("role")&&!A&&f.attr("aria-"+(w?r:i),"true"),f[m](x||option(n,y)||"")}function off(t,a,n){var c=t[0],p=t.parent(),v=a==i,f=a==l,g=a==r,A=f?o:v?s:"enabled",w=option(t,A+capitalize(c[u])),y=option(t,a+capitalize(c[u]));!1!==c[a]&&(!f&&n&&"force"!=n||(c[a]=!1),callbacks(t,v,A,n)),!c[r]&&option(t,h,!0)&&p.find("."+e).css(h,"pointer"),p[m](y||option(t,a)||""),p.attr("role")&&!f&&p.attr("aria-"+(g?r:i),"false"),p[d](w||option(t,A)||"")}function tidy(e,a){e.data(t)&&(e.parent().html(e.attr("style",e.data(t).s||"")),a&&e[v](a),e.off(".i").unwrap(),$(f+'[for="'+e[0].id+'"]').add(e.closest(f)).off(".i"))}function option(e,a,i){if(e.data(t))return e.data(t).o[a+(i?"":"Class")]}function capitalize(t){return t.charAt(0).toUpperCase()+t.slice(1)}function callbacks(t,e,a,i){i||(e&&t[v]("ifToggled"),t[v]("ifChanged")[v]("if"+capitalize(a)))}var t="iCheck",e=t+"-helper",a="radio",i="checked",s="un"+i,r="disabled",o="determinate",l="in"+o,c="update",u="type",p="touchbegin.i touchend.i",d="addClass",m="removeClass",v="trigger",f="label",h="cursor",g=/ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.memberAgent);$.fn[t]=function(s,o){var h='input[type="checkbox"], input[type="'+a+'"]',A=$(),w=function(t){t.each(function(){var t=$(this);A=t.is(h)?A.add(t):A.add(t.find(h))})};if(/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(s))return s=s.toLowerCase(),w(this),A.each(function(){var t=$(this);"destroy"==s?tidy(t,"ifDestroyed"):operate(t,!0,s),$.isFunction(o)&&o()});if("object"!=(void 0===s?"undefined":n()(s))&&s)return this;var y=$.extend({checkedClass:i,disabledClass:r,indeterminateClass:l,labelHover:!0},s),x=y.handle,b=y.hoverClass||"hover",C=y.focusClass||"focus",k=y.activeClass||"active",S=!!y.labelHover,E=y.labelHoverClass||"hover",M=0|(""+y.increaseArea).replace("%","");return"checkbox"!=x&&x!=a||(h='input[type="'+x+'"]'),M<-50&&(M=-50),w(this),A.each(function(){var n=$(this);tidy(n);var s,o=this,l=o.id,h=-M+"%",A=100+2*M+"%",w={position:"absolute",top:h,left:h,display:"block",width:A,height:A,margin:0,padding:0,background:"#fff",border:0,opacity:0},x=g?{position:"absolute",visibility:"hidden"}:M?w:{position:"absolute",opacity:0},T="checkbox"==o[u]?y.checkboxClass||"icheckbox":y.radioClass||"i"+a,U=$(f+'[for="'+l+'"]').add(n.closest(f)),D=!!y.aria,I=t+"-"+Math.random().toString(36).substr(2,6),P='<div class="'+T+'" '+(D?'role="'+o[u]+'" ':"");D&&U.each(function(){P+='aria-labelledby="',this.id?P+=this.id:(this.id=I,P+=I),P+='"'}),P=n.wrap(P+"/>")[v]("ifCreated").parent().append(y.insert),s=$('<ins class="'+e+'"/>').css(w).appendTo(P),n.data(t,{o:y,s:n.attr("style")}).css(x),!!y.inheritClass&&P[d](o.className||""),!!y.inheritID&&l&&P.attr("id",t+"-"+l),"static"==P.css("position")&&P.css("position","relative"),operate(n,!0,c),U.length&&U.on("click.i mouseover.i mouseout.i "+p,function(t){var e=t[u],a=$(this);if(!o[r]){if("click"==e){if($(t.target).is("a"))return;operate(n,!1,!0)}else S&&(/ut|nd/.test(e)?(P[m](b),a[m](E)):(P[d](b),a[d](E)));if(!g)return!1;t.stopPropagation()}}),n.on("click.i focus.i blur.i keyup.i keydown.i keypress.i",function(t){var e=t[u],s=t.keyCode;return"click"!=e&&("keydown"==e&&32==s?(o[u]==a&&o[i]||(o[i]?off(n,i):on(n,i)),!1):void("keyup"==e&&o[u]==a?!o[i]&&on(n,i):/us|ur/.test(e)&&P["blur"==e?m:d](C)))}),s.on("click mousedown mouseup mouseover mouseout "+p,function(t){var e=t[u],a=/wn|up/.test(e)?k:b;if(!o[r]){if("click"==e?operate(n,!1,!0):(/wn|er|in/.test(e)?P[d](a):P[m](a+" "+k),U.length&&S&&a==b&&U[/ut|nd/.test(e)?m:d](E)),!g)return!1;t.stopPropagation()}})})}}e.a=iCheck;var i=a("hRKE"),n=a.n(i)},seH5:function(t,e,a){"use strict";var i=function(){var t=this,e=t.$createElement,i=t._self._c||e;return i("div",{staticClass:"matter-all-type"},[i("div",[i("div",{staticClass:"row"},[i("div",{staticClass:"col-md-4 mb10",staticStyle:{"line-height":"40px"}},[t.matter.uuid&&"root"!==t.matter.uuid&&!t.keywords?i("router-link",{attrs:{to:"/matter/list/root"}},[t._v("\n\t\t\t\t\t\t全部文件\n\t\t\t\t\t")]):i("span",[t._v("全部文件")]),t._v(" "),t._l(tLine truncated
|
||||
//# sourceMappingURL=app.64233513a41451689d54.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///static/js/app.64233513a41451689d54.js","webpack:///./src/components/filter/NbFilterSort.vue","webpack:///src/components/filter/NbFilterCheck.vue","webpack:///./src/view/layout/TopNavigation.vue","webpack:///./src/view/user/widget/UserInputSelection.vue?9aab","webpack:///src/view/matter/components/TypeMatterComponent.vue","webpack:///./src/components/CreateSaveButton.vue?2db3","webpack:///./src/components/NbBtnDropdown.vue","webpack:///src/view/layout/widget/AvatarNaviBarDropdown.vue","webpack:///./src/assets/img/file/ppt.png","webpack:///./src/view/login/widget/LoginFrame.vue?94ba","webpack:///./src/components/NbExpanding.vue?0a18","webpack:///./src/components/NbCheckbox.vue?d2ac","webpack:///./src/model/frontend/MenuManager.js","webpack:///./src/view/matter/photo/List.vue?ceea","webpack:///src/components/filter/NbFilter.vue","webpack:///./src/components/NbRadio.vue","webpack:///./src/model/directive/directive.js","webpack:///./src/view/user/widget/UserInputSelection.vue","webpack:///./src/assets/img/error.png","webpack:///./src/view/Frame.vue?142d","webpack:///./src/view/user/ChangePassword.vue","webpack:///./src/model/tank/Tank.js","webpack:///./src/view/matter/word/List.vue","webpack:///./src/assets/img/file/archive.png","webpack:///src/view/matter/components/UploadComponent.vue","webpack:///src/view/matter/word/List.vue","webpack:///./src/components/NbExpanding.vue","webpack:///./src/components/filter/NbFilter.vue","webpack:///src/view/matter/photo/List.vue","webpack:///src/view/layout/TopNavigation.vue","webpack:///./src/view/layout/widget/AvatarNaviBarDropdown.vue?47e7","webpack:///./src/assets/img/file/text.png","webpack:///./src/components/NbRadio.vue?0645","webpack:///src/view/matter/music/List.vue","webpack:///./src/components/NbSlidePanel.vue","webpack:///src/view/matter/List.vue","webpack:///./src/components/NbPager.vue?1f0d","webpack:///./src/view/matter/components/TypeMatterComponent.vue?32e0","webpack:///./src/view/matter/components/TypeMatterComponent.vue","webpack:///./src/view/matter/components/MoveComponent.vue","webpack:///./src/components/CreateSaveButton.vue","webpack:///./src/model/matter/Matter.js","webpack:///./src/view/user/Profile.vue?c591","webpack:///./src/view/login/widget/LoginFrame.vue","webpack:///./src/assets/img/file/file.png","webpack:///./src/assets/img/file/pdf.png","webpack:///./src/model/filter/index.js","webpack:///src/view/matter/widget/FolderTree.vue","webpack:///./src/components/NbSlidePanel.vue?9053","webpack:///src/components/NbCheckbox.vue","webpack:///src/components/NbTanks.vue","webpack:///./src/App.vue","webpack:///./src/App.vue?6a4a","webpack:///./src/model/base/MimeType.js","webpack:///./src/components/filter/NbFilterSort.vue?b2f6","webpack:///./src/components/filter/NbFilterCheck.vue","webpack:///./src/components/NbTank.vue?3ae2","webpack:///./src/components/filter/NbFilterHttpSelection.vue?c805","webpack:///./src/main.js","webpack:///./src/model/filter/time.js","webpack:///./src/model/base/Pager.js","webpack:///src/App.vue","webpack:///src/view/matter/video/List.vue","webpack:///src/view/layout/widget/BtnDropdown.vue","webpack:///./src/components/NbBtnDropdown.vue?b5a8","webpack:///./src/view/layout/widget/AvatarDropdownUl.vue","webpack:///./src/assets/img/file/audio.png","webpack:///src/view/user/Create.vue","webpack:///./src/components/filter/NbFilterSelection.vue?b7be","webpack:///src/components/NbRadio.vue","webpack:///./src/model/util/Utils.js","webpack:///./src/view/matter/components/UploadComponent.vue?7b1c","webpack:///./src/view/user/Create.vue","webpack:///./src/model/base/Filter.js","webpack:///src/components/NbPager.vue","webpack:///./src/view/matter/photo/List.vue","webpack:///./src/components/filter/NbFilter.vue?648f","webpack:///./src/assets/img/file/doc.png","webpack:///./src/view/user/ChangePassword.vue?4479","webpack:///./src/components/filter/NbFilterHttpInputSelection.vue?b4c3","webpack:///./src/components/filter/NbFilterDateTime.vue","webpack:///src/view/user/List.vue","webpack:///src/view/layout/SideNavigation.vue","webpack:///src/components/NbExpanding.vue","webpack:///./src/view/matter/music/List.vue","webpack:///./src/components/filter/NbFilterHttpSelection.vue","webpack:///src/components/NbSlidePanel.vue","webpack:///src/components/filter/NbFilterDateTime.vue","webpack:///./src/router/index.js","webpack:///./src/model/base/BaseEntity.js","webpack:///src/view/login/Login.vue","webpack:///./src/view/layout/TopNavigation.vue?a376","webpack:///./src/components/NbTank.vue","webpack:///./src/view/layout/SideNavigation.vue?afc1","webpack:///src/view/layout/SideMenu.vue","webpack:///./src/assets/img/file/image.png","webpack:///./src/view/matter/components/MoveComponent.vue?76e0","webpack:///./src/view/layout/widget/BtnDropdown.vue","webpack:///./src/view/matter/List.vue","webpack:///./src/view/login/Login.vue?014b","webpack:///./src/components/NbTanks.vue","webpack:///./src/view/layout/SideMenu.vue",Line truncated
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(e){function __webpack_require__(r){if(_[r])return _[r].exports;var t=_[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,__webpack_require__),t.l=!0,t.exports}var r=window.webpackJsonp;window.webpackJsonp=function(_,n,o){for(var c,a,i,u=0,p=[];u<_.length;u++)a=_[u],t[a]&&p.push(t[a][0]),t[a]=0;for(c in n)Object.prototype.hasOwnProperty.call(n,c)&&(e[c]=n[c]);for(r&&r(_,n,o);p.length;)p.shift()();if(o)for(u=0;u<o.length;u++)i=__webpack_require__(__webpack_require__.s=o[u]);return i};var _={},t={2:0};__webpack_require__.e=function(e){function onScriptComplete(){o.onerror=o.onload=null,clearTimeout(c);var r=t[e];0!==r&&(r&&r[1](new Error("Loading chunk "+e+" failed.")),t[e]=void 0)}var r=t[e];if(0===r)return new Promise(function(e){e()});if(r)return r[2];var _=new Promise(function(_,n){r=t[e]=[_,n]});r[2]=_;var n=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,__webpack_require__.nc&&o.setAttribute("nonce",__webpack_require__.nc),o.src=__webpack_require__.p+"static/js/"+e+"."+{0:"392879af4bb24a810ba3",1:"64233513a41451689d54"}[e]+".js";var c=setTimeout(onScriptComplete,12e4);return o.onerror=o.onload=onScriptComplete,n.appendChild(o),_},__webpack_require__.m=e,__webpack_require__.c=_,__webpack_require__.d=function(exports,e,r){__webpack_require__.o(exports,e)||Object.defineProperty(exports,e,{configurable:!1,enumerable:!0,get:r})},__webpack_require__.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return __webpack_require__.d(r,"a",r),r},__webpack_require__.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},__webpack_require__.p="/",__webpack_require__.oe=function(e){throw console.error(e),e}}([]);
|
||||
//# sourceMappingURL=manifest.67df5041971dde987922.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///static/js/manifest.67df5041971dde987922.js","webpack:///webpack/bootstrap 21111edc5519deb42acb"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","parentJsonpFunction","window","chunkIds","moreModules","executeModules","chunkId","result","resolves","length","installedChunks","push","Object","prototype","hasOwnProperty","shift","s","2","e","onScriptComplete","script","onerror","onload","clearTimeout","timeout","chunk","Error","undefined","installedChunkData","Promise","resolve","promise","reject","head","document","getElementsByTagName","createElement","type","charset","async","nc","setAttribute","src","p","0","1","setTimeout","appendChild","m","c","d","name","getter","o","defineProperty","configurable","enumerable","get","n","__esModule","object","property","oe","err","console","error"],"mappings":"CAAS,SAAUA,GCuCnB,QAAAC,qBAAAC,GAGA,GAAAC,EAAAD,GACA,MAAAC,GAAAD,GAAAE,OAGA,IAAAC,GAAAF,EAAAD,IACAI,EAAAJ,EACAK,GAAA,EACAH,WAUA,OANAJ,GAAAE,GAAAM,KAAAH,EAAAD,QAAAC,IAAAD,QAAAH,qBAGAI,EAAAE,GAAA,EAGAF,EAAAD,QA1DA,GAAAK,GAAAC,OAAA,YACAA,QAAA,sBAAAC,EAAAC,EAAAC,GAIA,IADA,GAAAX,GAAAY,EAAAC,EAAAT,EAAA,EAAAU,KACQV,EAAAK,EAAAM,OAAoBX,IAC5BQ,EAAAH,EAAAL,GACAY,EAAAJ,IACAE,EAAAG,KAAAD,EAAAJ,GAAA,IAEAI,EAAAJ,GAAA,CAEA,KAAAZ,IAAAU,GACAQ,OAAAC,UAAAC,eAAAd,KAAAI,EAAAV,KACAF,EAAAE,GAAAU,EAAAV,GAIA,KADAO,KAAAE,EAAAC,EAAAC,GACAG,EAAAC,QACAD,EAAAO,SAEA,IAAAV,EACA,IAAAP,EAAA,EAAYA,EAAAO,EAAAI,OAA2BX,IACvCS,EAAAd,wCAAAuB,EAAAX,EAAAP,GAGA,OAAAS,GAIA,IAAAZ,MAGAe,GACAO,EAAA,EA6BAxB,qBAAAyB,EAAA,SAAAZ,GA+BA,QAAAa,oBAEAC,EAAAC,QAAAD,EAAAE,OAAA,KACAC,aAAAC,EACA,IAAAC,GAAAf,EAAAJ,EACA,KAAAmB,IACAA,GACAA,EAAA,MAAAC,OAAA,iBAAApB,EAAA,aAEAI,EAAAJ,OAAAqB,IAvCA,GAAAC,GAAAlB,EAAAJ,EACA,QAAAsB,EACA,UAAAC,SAAA,SAAAC,GAA0CA,KAI1C,IAAAF,EACA,MAAAA,GAAA,EAIA,IAAAG,GAAA,GAAAF,SAAA,SAAAC,EAAAE,GACAJ,EAAAlB,EAAAJ,IAAAwB,EAAAE,IAEAJ,GAAA,GAAAG,CAGA,IAAAE,GAAAC,SAAAC,qBAAA,WACAf,EAAAc,SAAAE,cAAA,SACAhB,GAAAiB,KAAA,kBACAjB,EAAAkB,QAAA,QACAlB,EAAAmB,OAAA,EACAnB,EAAAI,QAAA,KAEA/B,oBAAA+C,IACApB,EAAAqB,aAAA,QAAAhD,oBAAA+C,IAEApB,EAAAsB,IAAAjD,oBAAAkD,EAAA,aAAArC,EAAA,KAAwEsC,EAAA,uBAAAC,EAAA,wBAAsDvC,GAAA,KAC9H,IAAAkB,GAAAsB,WAAA3B,iBAAA,KAgBA,OAfAC,GAAAC,QAAAD,EAAAE,OAAAH,iBAaAc,EAAAc,YAAA3B,GAEAW,GAIAtC,oBAAAuD,EAAAxD,EAGAC,oBAAAwD,EAAAtD,EAGAF,oBAAAyD,EAAA,SAAAtD,QAAAuD,EAAAC,GACA3D,oBAAA4D,EAAAzD,QAAAuD,IACAvC,OAAA0C,eAAA1D,QAAAuD,GACAI,cAAA,EACAC,YAAA,EACAC,IAAAL,KAMA3D,oBAAAiE,EAAA,SAAA7D,GACA,GAAAuD,GAAAvD,KAAA8D,WACA,WAA2B,MAAA9D,GAAA,SAC3B,WAAiC,MAAAA,GAEjC,OADAJ,qBAAAyD,EAAAE,EAAA,IAAAA,GACAA,GAIA3D,oBAAA4D,EAAA,SAAAO,EAAAC,GAAsD,MAAAjD,QAAAC,UAAAC,eAAAd,KAAA4D,EAAAC,IAGtDpE,oBAAAkD,EAAA,IAGAlD,oBAAAqE,GAAA,SAAAC,GAA8D,KAApBC,SAAAC,MAAAF,GAAoBA","file":"static/js/manifest.67df5041971dde987922.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// install a JSONP callback for chunk loading\n/******/ \tvar parentJsonpFunction = window[\"webpackJsonp\"];\n/******/ \twindow[\"webpackJsonp\"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {\n/******/ \t\t// add \"moreModules\" to the modules object,\n/******/ \t\t// then flag all \"chunkIds\" as loaded and fire callback\n/******/ \t\tvar moduleId, chunkId, i = 0, resolves = [], result;\n/******/ \t\tfor(;i < chunkIds.length; i++) {\n/******/ \t\t\tchunkId = chunkIds[i];\n/******/ \t\t\tif(installedChunks[chunkId]) {\n/******/ \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n/******/ \t\t\t}\n/******/ \t\t\tinstalledChunks[chunkId] = 0;\n/******/ \t\t}\n/******/ \t\tfor(moduleId in moreModules) {\n/******/ \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n/******/ \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\tif(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);\n/******/ \t\twhile(resolves.length) {\n/******/ \t\t\tresolves.shift()();\n/******/ \t\t}\n/******/ \t\tif(executeModules) {\n/******/ \t\t\tfor(i=0; i < executeModules.length; i++) {\n/******/ \t\t\t\tresult = __webpack_require__(__webpack_require__.s = executeModules[i]);\n/******/ \t\t\t}\n/******/ \t\t}\n/******/ \t\treturn result;\n/******/ \t};\n/******/\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// objects to store loaded and loading chunks\n/******/ \tvar installedChunks = {\n/******/ \t\t2: 0\n/******/ \t};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute thLine truncated
|
||||
@@ -0,0 +1,46 @@
|
||||
webpackJsonp([0],{"+L0O":function(e,exports,t){var n=t("9kjK"),i=t("Ul84"),r=t("0IA1"),o=t("W9GI"),a="["+o+"]",s="
",l=RegExp("^"+a+a+"*"),u=RegExp(a+a+"*$"),c=function(e,t,i){var a={},l=r(function(){return!!o[e]()||s[e]()!=s}),u=a[e]=l?t(d):o[e];i&&(a[i]=u),n(n.P+n.F*l,"String",a)},d=c.trim=function(e,t){return e=String(i(e)),1&t&&(e=e.replace(l,"")),2&t&&(e=e.replace(u,"")),e};e.exports=c},"+rd1":function(e,exports,t){var n=t("30Io");e.exports=function(e){return Object(n(e))}},"/N1I":function(e,exports,t){"use strict";var n=t("38t3"),i=t("TUEb"),r=t("9Poz"),o={};t("q1/O")(o,t("IFGh")("iterator"),function(){return this}),e.exports=function(e,t,a){e.prototype=n(o,{next:i(1,a)}),r(e,t+" Iterator")}},"/RPK":function(e,exports,t){var n=t("z59m"),i=t("30Io");e.exports=function(e){return n(i(e))}},"/Xao":function(e,exports){e.exports=function(e,t,n,i,r,o){var a,s=e=e||{},l=typeof e.default;"object"!==l&&"function"!==l||(a=e,s=e.default);var u="function"==typeof s?s.options:s;t&&(u.render=t.render,u.staticRenderFns=t.staticRenderFns,u._compiled=!0),n&&(u.functional=!0),r&&(u._scopeId=r);var c;if(o?(c=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),i&&i.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(o)},u._ssrRegister=c):i&&(c=i),c){var d=u.functional,f=d?u.render:u.beforeCreate;d?(u._injectStyles=c,u.render=function(e,t){return c.call(t),f(e,t)}):u.beforeCreate=f?[].concat(f,c):[c]}return{esModule:a,exports:s,options:u}}},"/ZBN":function(e,exports,t){"use strict";function isNonNullObject(e){return!!e&&"object"==typeof e}function isSpecial(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||isReactElement(e)}function isReactElement(e){return e.$$typeof===r}function emptyTarget(e){return Array.isArray(e)?[]:{}}function cloneIfNecessary(e,t){return t&&!0===t.clone&&n(e)?deepmerge(emptyTarget(e),e,t):e}function defaultArrayMerge(e,t,i){var r=e.slice();return t.forEach(function(t,o){void 0===r[o]?r[o]=cloneIfNecessary(t,i):n(t)?r[o]=deepmerge(e[o],t,i):-1===e.indexOf(t)&&r.push(cloneIfNecessary(t,i))}),r}function mergeObject(e,t,i){var r={};return n(e)&&Object.keys(e).forEach(function(t){r[t]=cloneIfNecessary(e[t],i)}),Object.keys(t).forEach(function(o){n(t[o])&&e[o]?r[o]=deepmerge(e[o],t[o],i):r[o]=cloneIfNecessary(t[o],i)}),r}function deepmerge(e,t,n){var i=Array.isArray(t),r=Array.isArray(e),o=n||{arrayMerge:defaultArrayMerge};if(i===r)return i?(o.arrayMerge||defaultArrayMerge)(e,t,n):mergeObject(e,t,n);return cloneIfNecessary(t,n)}var n=function(e){return isNonNullObject(e)&&!isSpecial(e)},i="function"==typeof Symbol&&Symbol.for,r=i?Symbol.for("react.element"):60103;deepmerge.all=function(e,t){if(!Array.isArray(e)||e.length<2)throw new Error("first argument should be an array with at least two elements");return e.reduce(function(e,n){return deepmerge(e,n,t)})};var o=deepmerge;e.exports=o},"/fWK":function(e,exports){var t=0,n=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++t+n).toString(36))}},"/fqW":function(e,exports,t){"use strict";t("XV3y")("small",function(e){return function(){return e(this,"small","","")}})},"/n10":function(e,exports){var t=e.exports={version:"2.5.1"};"number"==typeof __e&&(__e=t)},"/oxD":function(e,exports,t){e.exports=!t("ryZK")&&!t("0IA1")(function(){return 7!=Object.defineProperty(t("rVQF")("div"),"a",{get:function(){return 7}}).a})},"091p":function(e,exports,t){"use strict";function packIEEE754(e,t,n){var i,r,o,a=Array(n),s=8*n-t-1,l=(1<<s)-1,u=l>>1,c=23===t?T(2,-24)-T(2,-77):0,d=0,f=e<0||0===e&&1/e<0?1:0;for(e=S(e),e!=e||e===C?(r=e!=e?1:0,i=l):(i=M(D(e)/E),e*(o=T(2,-i))<1&&(i--,o*=2),e+=i+u>=1?c/o:c*T(2,1-u),e*o>=2&&(i++,o/=2),i+u>=l?(r=0,i=l):i+u>=1?(r=(e*o-1)*T(2,t),i+=u):(r=e*T(2,u-1)*T(2,t),i=0));t>=8;a[d++]=255&r,r/=256,t-=8);for(i=i<<t|r,s+=t;s>0;a[d++]=255&i,i/=256,s-=8);return a[--d]|=128*f,a}function unpackIEEE754(e,t,n){var i,r=8*n-t-1,o=(1<<r)-1,a=o>>1,s=r-7,l=n-1,u=e[l--],c=127&u;for(u>>=7;s>0;c=256*c+e[l],l--,s-=8);for(i=c&(1<<-s)-1,c>>=-s,s+=t;s>0;i=256*i+e[l],l--,s-=8);if(0===c)c=1-a;else{if(c===o)return i?NaN:u?-C:C;i+=T(2,t),c-=a}return(u?-1:1)*i*T(2,c-t)}function unpackI32(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]}function packI8(e){return[255&e]}function packI16(e){return[255&e,e>>8&255]}function packI32(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]}function packF64(e){return packIEEE754(e,52,8)}function packF32(e){return packIEEE754(e,23,4)}function addGetter(e,t,n){p(e[g],t,{get:function(){return this[n]}})}function get(e,t,n,i){var r=+n,o=f(r);if(o+t>e[P])throw w(y);var a=e[O]._b,s=o+e[A],l=a.slice(s,s+t);return i?l:l.reverse()}function set(e,t,n,i,r,o){var a=+n,s=f(a);if(s+t>e[P])throw w(y);for(var l=e[O]._b,u=s+e[A],c=i(+r),d=0;d<t;d++)l[u+d]=c[o?d:t-d-1]}var n=t("WdGS"),i=t("ryZK"),r=t("FFc+"),o=t("ugN3"),a=t("sVyS"),s=t("LMeO"Line truncated
|
||||
* vuex v3.0.1
|
||||
* (c) 2017 Evan You
|
||||
* @license MIT
|
||||
*/
|
||||
var i=function(e){function vuexInit(){var e=this.$options;e.store?this.$store="function"==typeof e.store?e.store():e.store:e.parent&&e.parent.$store&&(this.$store=e.parent.$store)}if(Number(e.version.split(".")[0])>=2)e.mixin({beforeCreate:vuexInit});else{var t=e.prototype._init;e.prototype._init=function(e){void 0===e&&(e={}),e.init=e.init?[vuexInit].concat(e.init):vuexInit,t.call(this,e)}}},r="undefined"!=typeof window&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,o=function(e,t){this.runtime=t,this._children=Object.create(null),this._rawModule=e;var n=e.state;this.state=("function"==typeof n?n():n)||{}},a={namespaced:{configurable:!0}};a.namespaced.get=function(){return!!this._rawModule.namespaced},o.prototype.addChild=function(e,t){this._children[e]=t},o.prototype.removeChild=function(e){delete this._children[e]},o.prototype.getChild=function(e){return this._children[e]},o.prototype.update=function(e){this._rawModule.namespaced=e.namespaced,e.actions&&(this._rawModule.actions=e.actions),e.mutations&&(this._rawModule.mutations=e.mutations),e.getters&&(this._rawModule.getters=e.getters)},o.prototype.forEachChild=function(e){forEachValue(this._children,e)},o.prototype.forEachGetter=function(e){this._rawModule.getters&&forEachValue(this._rawModule.getters,e)},o.prototype.forEachAction=function(e){this._rawModule.actions&&forEachValue(this._rawModule.actions,e)},o.prototype.forEachMutation=function(e){this._rawModule.mutations&&forEachValue(this._rawModule.mutations,e)},Object.defineProperties(o.prototype,a);var s=function(e){this.register([],e,!1)};s.prototype.get=function(e){return e.reduce(function(e,t){return e.getChild(t)},this.root)},s.prototype.getNamespace=function(e){var t=this.root;return e.reduce(function(e,n){return t=t.getChild(n),e+(t.namespaced?n+"/":"")},"")},s.prototype.update=function(e){update([],this.root,e)},s.prototype.register=function(e,t,n){var i=this;void 0===n&&(n=!0);var r=new o(t,n);if(0===e.length)this.root=r;else{this.get(e.slice(0,-1)).addChild(e[e.length-1],r)}t.modules&&forEachValue(t.modules,function(t,r){i.register(e.concat(r),t,n)})},s.prototype.unregister=function(e){var t=this.get(e.slice(0,-1)),n=e[e.length-1];t.getChild(n).runtime&&t.removeChild(n)};var l,u=function(e){var t=this;void 0===e&&(e={}),!l&&"undefined"!=typeof window&&window.Vue&&install(window.Vue);var n=e.plugins;void 0===n&&(n=[]);var i=e.strict;void 0===i&&(i=!1);var r=e.state;void 0===r&&(r={}),"function"==typeof r&&(r=r()||{}),this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new s(e),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._watcherVM=new l;var o=this,a=this,u=a.dispatch,c=a.commit;this.dispatch=function(e,t){return u.call(o,e,t)},this.commit=function(e,t,n){return c.call(o,e,t,n)},this.strict=i,installModule(this,r,[],this._modules.root),resetStoreVM(this,r),n.forEach(function(e){return e(t)}),l.config.devtools&&devtoolPlugin(this)},c={state:{configurable:!0}};c.state.get=function(){return this._vm._data.$$state},c.state.set=function(e){},u.prototype.commit=function(e,t,n){var i=this,r=unifyObjectStyle(e,t,n),o=r.type,a=r.payload,s=(r.options,{type:o,payload:a}),l=this._mutations[o];l&&(this._withCommit(function(){l.forEach(function(e){e(a)})}),this._subscribers.forEach(function(e){return e(s,i.state)}))},u.prototype.dispatch=function(e,t){var n=this,i=unifyObjectStyle(e,t),r=i.type,o=i.payload,a={type:r,payload:o},s=this._actions[r];if(s)return this._actionSubscribers.forEach(function(e){return e(a,n.state)}),s.length>1?Promise.all(s.map(function(e){return e(o)})):s[0](o)},u.prototype.subscribe=function(e){return genericSubscribe(e,this._subscribers)},u.prototype.subscribeAction=function(e){return genericSubscribe(e,this._actionSubscribers)},u.prototype.watch=function(e,t,n){var i=this;return this._watcherVM.$watch(function(){return e(i.state,i.getters)},t,n)},u.prototype.replaceState=function(e){var t=this;this._withCommit(function(){t._vm._data.$$state=e})},u.prototype.registerModule=function(e,t,n){void 0===n&&(n={}),"string"==typeof e&&(e=[e]),this._modules.register(e,t),installModule(this,this.state,e,this._modules.get(e),n.preserveState),resetStoreVM(this,this.state)},u.prototype.unregisterModule=function(e){var t=this;"string"==typeof e&&(e=[e]),this._modules.unregister(e),this._withCommit(function(){var n=getNestedState(t.state,e.slice(0,-1));l.delete(n,e[e.length-1])}),resetStore(this)},u.prototype.hotUpdate=function(e){this._modules.update(e),resetStore(this,!0)},u.prototype._withCommit=function(e){var t=this._committing;this._committing=!0,e(),this._committing=t},Object.defineProperties(u.prototype,c);var d=normalizeNamespace(function(e,t){var n={};return normalizeMap(t).forEach(function(t){var i=t.key,r=t.val;n[i]=function(){var t=this.$store.state,n=this.$store.getters;if(e){var i=getModuleByNamespace(this.$store,"mapState",e);if(!i)return;t=Line truncated
|
||||
* enquire.js v2.1.6 - Awesome Media Queries in JavaScript
|
||||
* Copyright (c) 2017 Nick Williams - http://wicky.nillia.ms/enquire.js
|
||||
* License: MIT */
|
||||
!function(e){t.exports=e()}(function(){return function e(t,n,i){function s(o,a){if(!n[o]){if(!t[o]){var l="function"==typeof require&&require;if(!a&&l)return require(o,!0);if(r)return r(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=n[o]={exports:{}};t[o][0].call(c.exports,function(e){var n=t[o][1][e];return s(n||e)},c,c.exports,e,t,n,i)}return n[o].exports}for(var r="function"==typeof require&&require,o=0;o<i.length;o++)s(i[o]);return s}({1:[function(require,e,exports){function MediaQuery(e,t){this.query=e,this.isUnconditional=t,this.handlers=[],this.mql=window.matchMedia(e);var n=this;this.listener=function(e){n.mql=e.currentTarget||e,n.assess()},this.mql.addListener(this.listener)}var t=require(3),n=require(4).each;MediaQuery.prototype={constuctor:MediaQuery,addHandler:function(e){var n=new t(e);this.handlers.push(n),this.matches()&&n.on()},removeHandler:function(e){var t=this.handlers;n(t,function(n,i){if(n.equals(e))return n.destroy(),!t.splice(i,1)})},matches:function(){return this.mql.matches||this.isUnconditional},clear:function(){n(this.handlers,function(e){e.destroy()}),this.mql.removeListener(this.listener),this.handlers.length=0},assess:function(){var e=this.matches()?"on":"off";n(this.handlers,function(t){t[e]()})}},e.exports=MediaQuery},{3:3,4:4}],2:[function(require,e,exports){function MediaQueryDispatch(){if(!window.matchMedia)throw new Error("matchMedia not present, legacy browsers require a polyfill");this.queries={},this.browserIsIncapable=!window.matchMedia("only all").matches}var t=require(1),n=require(4),i=n.each,r=n.isFunction,o=n.isArray;MediaQueryDispatch.prototype={constructor:MediaQueryDispatch,register:function(e,n,a){var s=this.queries,l=a&&this.browserIsIncapable;return s[e]||(s[e]=new t(e,l)),r(n)&&(n={match:n}),o(n)||(n=[n]),i(n,function(t){r(t)&&(t={match:t}),s[e].addHandler(t)}),this},unregister:function(e,t){var n=this.queries[e];return n&&(t?n.removeHandler(t):(n.clear(),delete this.queries[e])),this}},e.exports=MediaQueryDispatch},{1:1,4:4}],3:[function(require,e,exports){function QueryHandler(e){this.options=e,!e.deferSetup&&this.setup()}QueryHandler.prototype={constructor:QueryHandler,setup:function(){this.options.setup&&this.options.setup(),this.initialised=!0},on:function(){!this.initialised&&this.setup(),this.options.match&&this.options.match()},off:function(){this.options.unmatch&&this.options.unmatch()},destroy:function(){this.options.destroy?this.options.destroy():this.off()},equals:function(e){return this.options===e||this.options.match===e}},e.exports=QueryHandler},{}],4:[function(require,e,exports){function each(e,t){var n=0,i=e.length;for(n;n<i&&!1!==t(e[n],n);n++);}function isArray(e){return"[object Array]"===Object.prototype.toString.apply(e)}function isFunction(e){return"function"==typeof e}e.exports={isFunction:isFunction,isArray:isArray,each:each}},{}],5:[function(require,e,exports){var t=require(2);e.exports=new t},{2:2}]},{},[5])(5)})},BWjf:function(e,exports){exports.f=Object.getOwnPropertySymbols},Bgpb:function(e,exports,t){e.exports=function(e){function __webpack_require__(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,__webpack_require__),i.l=!0,i.exports}var t={};return __webpack_require__.m=e,__webpack_require__.c=t,__webpack_require__.d=function(exports,e,t){__webpack_require__.o(exports,e)||Object.defineProperty(exports,e,{configurable:!1,enumerable:!0,get:t})},__webpack_require__.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return __webpack_require__.d(t,"a",t),t},__webpack_require__.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},__webpack_require__.p="/dist/",__webpack_require__(__webpack_require__.s=157)}({0:function(e,exports){e.exports=function(e,t,n,i,r,o){var a,s=e=e||{},l=typeof e.default;"object"!==l&&"function"!==l||(a=e,s=e.default);var u="function"==typeof s?s.options:s;t&&(u.render=t.render,u.staticRenderFns=t.staticRenderFns,u._compiled=!0),n&&(u.functional=!0),r&&(u._scopeId=r);var c;if(o?(c=function(e){e=e||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext,e||"undefined"==typeof __VUE_SSR_CONTEXT__||(e=__VUE_SSR_CONTEXT__),i&&i.call(this,e),e&&e._registeredComponents&&e._registeredComponents.add(o)},u._ssrRegister=c):i&&(c=i),c){var d=u.functional,f=d?u.render:u.beforeCreate;d?(u._injectStyles=c,u.render=function(e,t){return c.call(t),f(e,t)}):u.beforeCreate=f?[].concat(f,c):[c]}return{esModule:a,exports:s,options:u}}},1:function(e,exports){e.exports=t("Uyl6")},12:function(e,exports){e.exports=t("x018")},13:function(e,exports){e.exports=t("RLlM")},14:function(e,exports){e.exports=t("M4cF")},157:function(e,exports,t){e.exports=t(158)},158:function(e,exports,t){"use strict";exports.__esModule=!0;var n=t(159),i=function(e){return e&&e.__esModule?e:{default:e}}(n);i.default.install=function(e){e.component(i.default.name,i.deLine truncated
|
||||
* Vue.js v2.5.8
|
||||
* (c) 2014-2017 Evan You
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
var i=Object.freeze({}),r=Object.prototype.toString,o=makeMap("slot,component",!0),a=makeMap("key,ref,slot,slot-scope,is"),s=Object.prototype.hasOwnProperty,l=/-(\w)/g,u=cached(function(e){return e.replace(l,function(e,t){return t?t.toUpperCase():""})}),c=cached(function(e){return e.charAt(0).toUpperCase()+e.slice(1)}),d=/\B([A-Z])/g,f=cached(function(e){return e.replace(d,"-$1").toLowerCase()}),h=function(e,t,n){return!1},p=function(e){return e},m="data-server-rendered",v=["component","directive","filter"],g=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured"],y={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:h,isReservedAttr:h,isUnknownElement:h,getTagNamespace:noop,parsePlatformTagName:p,mustUseProp:h,_lifecycleHooks:g},b=/[^\w.$]/,_="__proto__"in{},x="undefined"!=typeof window,w="undefined"!=typeof WXEnvironment&&!!WXEnvironment.platform,C=w&&WXEnvironment.platform.toLowerCase(),k=x&&window.navigator.userAgent.toLowerCase(),S=k&&/msie|trident/.test(k),T=k&&k.indexOf("msie 9.0")>0,M=k&&k.indexOf("edge/")>0,D=k&&k.indexOf("android")>0||"android"===C,E=k&&/iphone|ipad|ipod|ios/.test(k)||"ios"===C,O=(k&&/chrome\/\d+/.test(k),{}.watch),P=!1;if(x)try{var A={};Object.defineProperty(A,"passive",{get:function(){P=!0}}),window.addEventListener("test-passive",null,A)}catch(e){}var N,R,F=function(){return void 0===N&&(N=!x&&void 0!==e&&"server"===e.process.env.VUE_ENV),N},I=x&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__,j="undefined"!=typeof Symbol&&isNative(Symbol)&&"undefined"!=typeof Reflect&&isNative(Reflect.ownKeys);R="undefined"!=typeof Set&&isNative(Set)?Set:function(){function Set(){this.set=Object.create(null)}return Set.prototype.has=function(e){return!0===this.set[e]},Set.prototype.add=function(e){this.set[e]=!0},Set.prototype.clear=function(){this.set=Object.create(null)},Set}();var q=noop,L=0,V=function(){this.id=L++,this.subs=[]};V.prototype.addSub=function(e){this.subs.push(e)},V.prototype.removeSub=function(e){remove(this.subs,e)},V.prototype.depend=function(){V.target&&V.target.addDep(this)},V.prototype.notify=function(){for(var e=this.subs.slice(),t=0,n=e.length;t<n;t++)e[t].update()},V.target=null;var H=[],B=function(e,t,n,i,r,o,a,s){this.tag=e,this.data=t,this.children=n,this.text=i,this.elm=r,this.ns=void 0,this.context=o,this.functionalContext=void 0,this.functionalOptions=void 0,this.functionalScopeId=void 0,this.key=t&&t.key,this.componentOptions=a,this.componentInstance=void 0,this.parent=void 0,this.raw=!1,this.isStatic=!1,this.isRootInsert=!0,this.isComment=!1,this.isCloned=!1,this.isOnce=!1,this.asyncFactory=s,this.asyncMeta=void 0,this.isAsyncPlaceholder=!1},z={child:{configurable:!0}};z.child.get=function(){return this.componentInstance},Object.defineProperties(B.prototype,z);var W=function(e){void 0===e&&(e="");var t=new B;return t.text=e,t.isComment=!0,t},K=Array.prototype,U=Object.create(K);["push","pop","shift","unshift","splice","sort","reverse"].forEach(function(e){var t=K[e];def(U,e,function(){for(var n=[],i=arguments.length;i--;)n[i]=arguments[i];var r,o=t.apply(this,n),a=this.__ob__;switch(e){case"push":case"unshift":r=n;break;case"splice":r=n.slice(2)}return r&&a.observeArray(r),a.dep.notify(),o})});var G=Object.getOwnPropertyNames(U),Y={shouldConvert:!0},X=function(e){if(this.value=e,this.dep=new V,this.vmCount=0,def(e,"__ob__",this),Array.isArray(e)){(_?protoAugment:copyAugment)(e,U,G),this.observeArray(e)}else this.walk(e)};X.prototype.walk=function(e){for(var t=Object.keys(e),n=0;n<t.length;n++)defineReactive(e,t[n],e[t[n]])},X.prototype.observeArray=function(e){for(var t=0,n=e.length;t<n;t++)observe(e[t])};var J=y.optionMergeStrategies;J.data=function(e,t,n){return n?mergeDataOrFn(e,t,n):t&&"function"!=typeof t?e:mergeDataOrFn(e,t)},g.forEach(function(e){J[e]=mergeHook}),v.forEach(function(e){J[e+"s"]=mergeAssets}),J.watch=function(e,t,n,i){if(e===O&&(e=void 0),t===O&&(t=void 0),!t)return Object.create(e||null);if(!e)return t;var r={};extend(r,e);for(var o in t){var a=r[o],s=t[o];a&&!Array.isArray(a)&&(a=[a]),r[o]=a?a.concat(s):Array.isArray(s)?s:[s]}return r},J.props=J.methods=J.inject=J.computed=function(e,t,n,i){if(!e)return t;var r=Object.create(null);return extend(r,e),t&&extend(r,t),r},J.provide=mergeDataOrFn;var Q,Z,ee=function(e,t){return void 0===t?e:t},te=[],ne=!1,ie=!1;if(void 0!==n&&isNative(n))Z=function(){n(flushCallbacks)};else if("undefined"==typeof MessageChannel||!isNative(MessageChannel)&&"[object MessageChannelConstructor]"!==MessageChannel.toString())Z=function(){setTimeout(flushCallbacks,0)};else{var re=new MessageChannel,oe=re.port2;re.port1.onmessage=flushCallbacks,Z=function(){oe.postMessage(1)}}if("undefined"!=typeof Promise&&isNative(Promise)){var ae=Promise.resolve();Q=function(){ae.then(flushCallbacks),E&&setTimeouLine truncated
|
||||
* jQuery JavaScript Library v3.2.1
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2017-03-20T18:59Z
|
||||
*/
|
||||
!function(t,n){"use strict";"object"==typeof e&&"object"==typeof e.exports?e.exports=t.document?n(t,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return n(e)}:n(t)}("undefined"!=typeof window?window:this,function(t,r){"use strict";function DOMEval(e,t){t=t||a;var n=t.createElement("script");n.text=e,t.head.appendChild(n).parentNode.removeChild(n)}function isArrayLike(e){var t=!!e&&"length"in e&&e.length,n=y.type(e);return"function"!==n&&!y.isWindow(e)&&("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e)}function nodeName(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}function winnow(e,t,n){return y.isFunction(t)?y.grep(e,function(e,i){return!!t.call(e,i,e)!==n}):t.nodeType?y.grep(e,function(e){return e===t!==n}):"string"!=typeof t?y.grep(e,function(e){return d.call(t,e)>-1!==n}):D.test(t)?y.filter(t,e,n):(t=y.filter(t,e),y.grep(e,function(e){return d.call(t,e)>-1!==n&&1===e.nodeType}))}function sibling(e,t){for(;(e=e[t])&&1!==e.nodeType;);return e}function createOptions(e){var t={};return y.each(e.match(N)||[],function(e,n){t[n]=!0}),t}function Identity(e){return e}function Thrower(e){throw e}function adoptValue(e,t,n,i){var r;try{e&&y.isFunction(r=e.promise)?r.call(e).done(t).fail(n):e&&y.isFunction(r=e.then)?r.call(e,t,n):t.apply(void 0,[e].slice(i))}catch(e){n.apply(void 0,[e])}}function completed(){a.removeEventListener("DOMContentLoaded",completed),t.removeEventListener("load",completed),y.ready()}function Data(){this.expando=y.expando+Data.uid++}function getData(e){return"true"===e||"false"!==e&&("null"===e?null:e===+e+""?+e:V.test(e)?JSON.parse(e):e)}function dataAttr(e,t,n){var i;if(void 0===n&&1===e.nodeType)if(i="data-"+t.replace(H,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(i))){try{n=getData(n)}catch(e){}L.set(e,t,n)}else n=void 0;return n}function adjustCSS(e,t,n,i){var r,o=1,a=20,s=i?function(){return i.cur()}:function(){return y.css(e,t,"")},l=s(),u=n&&n[3]||(y.cssNumber[t]?"":"px"),c=(y.cssNumber[t]||"px"!==u&&+l)&&z.exec(y.css(e,t));if(c&&c[3]!==u){u=u||c[3],n=n||[],c=+l||1;do{o=o||".5",c/=o,y.style(e,t,c+u)}while(o!==(o=s()/l)&&1!==o&&--a)}return n&&(c=+c||+l||0,r=n[1]?c+(n[1]+1)*n[2]:+n[2],i&&(i.unit=u,i.start=c,i.end=r)),r}function getDefaultDisplay(e){var t,n=e.ownerDocument,i=e.nodeName,r=G[i];return r||(t=n.body.appendChild(n.createElement(i)),r=y.css(t,"display"),t.parentNode.removeChild(t),"none"===r&&(r="block"),G[i]=r,r)}function showHide(e,t){for(var n,i,r=[],o=0,a=e.length;o<a;o++)i=e[o],i.style&&(n=i.style.display,t?("none"===n&&(r[o]=q.get(i,"display")||null,r[o]||(i.style.display="")),""===i.style.display&&K(i)&&(r[o]=getDefaultDisplay(i))):"none"!==n&&(r[o]="none",q.set(i,"display",n)));for(o=0;o<a;o++)null!=r[o]&&(e[o].style.display=r[o]);return e}function getAll(e,t){var n;return n=void 0!==e.getElementsByTagName?e.getElementsByTagName(t||"*"):void 0!==e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&nodeName(e,t)?y.merge([e],n):n}function setGlobalEval(e,t){for(var n=0,i=e.length;n<i;n++)q.set(e[n],"globalEval",!t||q.get(t[n],"globalEval"))}function buildFragment(e,t,n,i,r){for(var o,a,s,l,u,c,d=t.createDocumentFragment(),f=[],h=0,p=e.length;h<p;h++)if((o=e[h])||0===o)if("object"===y.type(o))y.merge(f,o.nodeType?[o]:o);else if(Z.test(o)){for(a=a||d.appendChild(t.createElement("div")),s=(X.exec(o)||["",""])[1].toLowerCase(),l=Q[s]||Q._default,a.innerHTML=l[1]+y.htmlPrefilter(o)+l[2],c=l[0];c--;)a=a.lastChild;y.merge(f,a.childNodes),a=d.firstChild,a.textContent=""}else f.push(t.createTextNode(o));for(d.textContent="",h=0;o=f[h++];)if(i&&y.inArray(o,i)>-1)r&&r.push(o);else if(u=y.contains(o.ownerDocument,o),a=getAll(d.appendChild(o),"script"),u&&setGlobalEval(a),n)for(c=0;o=a[c++];)J.test(o.type||"")&&n.push(o);return d}function returnTrue(){return!0}function returnFalse(){return!1}function safeActiveElement(){try{return a.activeElement}catch(e){}}function on(e,t,n,i,r,o){var a,s;if("object"==typeof t){"string"!=typeof n&&(i=i||n,n=void 0);for(s in t)on(e,s,n,i,t[s],o);return e}if(null==i&&null==r?(r=n,i=n=void 0):null==r&&("string"==typeof n?(r=i,i=void 0):(r=i,i=n,n=void 0)),!1===r)r=returnFalse;else if(!r)return e;return 1===o&&(a=r,r=function(e){return y().off(e),a.apply(this,arguments)},r.guid=a.guid||(a.guid=y.guid++)),e.each(function(){y.event.add(this,t,r,i,n)})}function manipulationTarget(e,t){return nodeName(e,"table")&&nodeName(11!==t.nodeType?t:t.firstChild,"tr")?y(">tbody",e)[0]||e:e}function disableScript(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function restoreScript(e){var t=se.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function cloneCopyEvent(e,t){var n,i,r,o,a,s,l,u;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),a=q.set(t,o),u=o.events)){delete a.handle,a.events={};for(r in u)for(n=0,i=u[r].length;n<i;n++)y.event.add(t,r,u[r][n])}L.hasData(e)&&(s=L.access(e),l=y.extend({},s),L.set(t,l))}}function fixInput(e,t){var n=t.nLine truncated
|
||||
* Sizzle CSS Selector Engine v2.3.3
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: 2016-08-08
|
||||
*/
|
||||
function(e){function Sizzle(e,t,i,r){var o,s,u,c,d,p,g,y=t&&t.ownerDocument,w=t?t.nodeType:9;if(i=i||[],"string"!=typeof e||!e||1!==w&&9!==w&&11!==w)return i;if(!r&&((t?t.ownerDocument||t:x)!==h&&f(t),t=t||h,m)){if(11!==w&&(d=Q.exec(e)))if(o=d[1]){if(9===w){if(!(u=t.getElementById(o)))return i;if(u.id===o)return i.push(u),i}else if(y&&(u=y.getElementById(o))&&b(t,u)&&u.id===o)return i.push(u),i}else{if(d[2])return A.apply(i,t.getElementsByTagName(e)),i;if((o=d[3])&&n.getElementsByClassName&&t.getElementsByClassName)return A.apply(i,t.getElementsByClassName(o)),i}if(n.qsa&&!T[e+" "]&&(!v||!v.test(e))){if(1!==w)y=t,g=e;else if("object"!==t.nodeName.toLowerCase()){for((c=t.getAttribute("id"))?c=c.replace(ne,ie):t.setAttribute("id",c=_),p=a(e),s=p.length;s--;)p[s]="#"+c+" "+toSelector(p[s]);g=p.join(","),y=Z.test(e)&&testContext(t.parentNode)||t}if(g)try{return A.apply(i,y.querySelectorAll(g)),i}catch(e){}finally{c===_&&t.removeAttribute("id")}}}return l(e.replace(H,"$1"),t,i,r)}function createCache(){function cache(t,n){return e.push(t+" ")>i.cacheLength&&delete cache[e.shift()],cache[t+" "]=n}var e=[];return cache}function markFunction(e){return e[_]=!0,e}function assert(e){var t=h.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function addHandle(e,t){for(var n=e.split("|"),r=n.length;r--;)i.attrHandle[n[r]]=t}function siblingCheck(e,t){var n=t&&e,i=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(i)return i;if(n)for(;n=n.nextSibling;)if(n===t)return-1;return e?1:-1}function createDisabledPseudo(e){return function(t){return"form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.isDisabled!==!e&&oe(t)===e:t.disabled===e:"label"in t&&t.disabled===e}}function createPositionalPseudo(e){return markFunction(function(t){return t=+t,markFunction(function(n,i){for(var r,o=e([],n.length,t),a=o.length;a--;)n[r=o[a]]&&(n[r]=!(i[r]=n[r]))})})}function testContext(e){return e&&void 0!==e.getElementsByTagName&&e}function setFilters(){}function toSelector(e){for(var t=0,n=e.length,i="";t<n;t++)i+=e[t].value;return i}function addCombinator(e,t,n){var i=t.dir,r=t.next,o=r||i,a=n&&"parentNode"===o,s=C++;return t.first?function(t,n,r){for(;t=t[i];)if(1===t.nodeType||a)return e(t,n,r);return!1}:function(t,n,l){var u,c,d,f=[w,s];if(l){for(;t=t[i];)if((1===t.nodeType||a)&&e(t,n,l))return!0}else for(;t=t[i];)if(1===t.nodeType||a)if(d=t[_]||(t[_]={}),c=d[t.uniqueID]||(d[t.uniqueID]={}),r&&r===t.nodeName.toLowerCase())t=t[i]||t;else{if((u=c[o])&&u[0]===w&&u[1]===s)return f[2]=u[2];if(c[o]=f,f[2]=e(t,n,l))return!0}return!1}}function elementMatcher(e){return e.length>1?function(t,n,i){for(var r=e.length;r--;)if(!e[r](t,n,i))return!1;return!0}:e[0]}function multipleContexts(e,t,n){for(var i=0,r=t.length;i<r;i++)Sizzle(e,t[i],n);return n}function condense(e,t,n,i,r){for(var o,a=[],s=0,l=e.length,u=null!=t;s<l;s++)(o=e[s])&&(n&&!n(o,i,r)||(a.push(o),u&&t.push(s)));return a}function setMatcher(e,t,n,i,r,o){return i&&!i[_]&&(i=setMatcher(i)),r&&!r[_]&&(r=setMatcher(r,o)),markFunction(function(o,a,s,l){var u,c,d,f=[],h=[],p=a.length,m=o||multipleContexts(t||"*",s.nodeType?[s]:s,[]),v=!e||!o&&t?m:condense(m,f,e,s,l),g=n?r||(o?e:p||i)?[]:a:v;if(n&&n(v,g,s,l),i)for(u=condense(g,h),i(u,[],s,l),c=u.length;c--;)(d=u[c])&&(g[h[c]]=!(v[h[c]]=d));if(o){if(r||e){if(r){for(u=[],c=g.length;c--;)(d=g[c])&&u.push(v[c]=d);r(null,g=[],u,l)}for(c=g.length;c--;)(d=g[c])&&(u=r?R(o,d):f[c])>-1&&(o[u]=!(a[u]=d))}}else g=condense(g===a?g.splice(p,g.length):g),r?r(null,a,g,l):A.apply(a,g)})}function matcherFromTokens(e){for(var t,n,r,o=e.length,a=i.relative[e[0].type],s=a||i.relative[" "],l=a?1:0,c=addCombinator(function(e){return e===t},s,!0),d=addCombinator(function(e){return R(t,e)>-1},s,!0),f=[function(e,n,i){var r=!a&&(i||n!==u)||((t=n).nodeType?c(e,n,i):d(e,n,i));return t=null,r}];l<o;l++)if(n=i.relative[e[l].type])f=[addCombinator(elementMatcher(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[_]){for(r=++l;r<o&&!i.relative[e[r].type];r++);return setMatcher(l>1&&elementMatcher(f),l>1&&toSelector(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(H,"$1"),n,l<r&&matcherFromTokens(e.slice(l,r)),r<o&&matcherFromTokens(e=e.slice(r)),r<o&&toSelector(e))}f.push(n)}return elementMatcher(f)}function matcherFromGroupMatchers(e,t){var n=t.length>0,r=e.length>0,o=function(o,a,s,l,c){var d,p,v,g=0,y="0",b=o&&[],_=[],x=u,C=o||r&&i.find.TAG("*",c),k=w+=null==x?1:Math.random()||.1,S=C.length;for(c&&(u=a===h||a||c);y!==S&&null!=(d=C[y]);y++){if(r&&d){for(p=0,a||d.ownerDocument===h||(f(d),s=!m);v=e[p++];)if(v(d,a||h,s)){l.push(d);break}c&&(w=k)}n&&((d=!v&&d)&&g--,o&&b.push(d))}if(g+=y,n&&y!==g){for(p=0;v=t[p++];)v(b,_,a,s);if(o){if(g>0)for(;y--;)b[y]||_[y]||(_[y]=O.call(l));_=condense(_)}A.apply(l,_),c&&!o&&_.length>0&&g+t.length>1&&Sizzle.uniqueSort(l)}return c&&(w=k,u=x),b};retLine truncated
|
||||
/*! VelocityJS.org jQuery Shim (1.0.1). (C) 2014 The jQuery Foundation. MIT @license: en.wikipedia.org/wiki/MIT_License. */
|
||||
!function(e){"use strict";function isArraylike(e){var t=e.length,n=$.type(e);return"function"!==n&&!$.isWindow(e)&&(!(1!==e.nodeType||!t)||("array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e))}if(!e.jQuery){var $=function(e,t){return new $.fn.init(e,t)};$.isWindow=function(e){return e&&e===e.window},$.type=function(e){return e?"object"==typeof e||"function"==typeof e?n[r.call(e)]||"object":typeof e:e+""},$.isArray=Array.isArray||function(e){return"array"===$.type(e)},$.isPlainObject=function(e){var t;if(!e||"object"!==$.type(e)||e.nodeType||$.isWindow(e))return!1;try{if(e.constructor&&!i.call(e,"constructor")&&!i.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(e){return!1}for(t in e);return void 0===t||i.call(e,t)},$.each=function(e,t,n){var i=0,r=e.length,o=isArraylike(e);if(n){if(o)for(;i<r&&!1!==t.apply(e[i],n);i++);else for(i in e)if(e.hasOwnProperty(i)&&!1===t.apply(e[i],n))break}else if(o)for(;i<r&&!1!==t.call(e[i],i,e[i]);i++);else for(i in e)if(e.hasOwnProperty(i)&&!1===t.call(e[i],i,e[i]))break;return e},$.data=function(e,n,i){if(void 0===i){var r=e[$.expando],o=r&&t[r];if(void 0===n)return o;if(o&&n in o)return o[n]}else if(void 0!==n){var a=e[$.expando]||(e[$.expando]=++$.uuid);return t[a]=t[a]||{},t[a][n]=i,i}},$.removeData=function(e,n){var i=e[$.expando],r=i&&t[i];r&&(n?$.each(n,function(e,t){delete r[t]}):delete t[i])},$.extend=function(){var e,t,n,i,r,o,a=arguments[0]||{},s=1,l=arguments.length,u=!1;for("boolean"==typeof a&&(u=a,a=arguments[s]||{},s++),"object"!=typeof a&&"function"!==$.type(a)&&(a={}),s===l&&(a=this,s--);s<l;s++)if(r=arguments[s])for(i in r)r.hasOwnProperty(i)&&(e=a[i],n=r[i],a!==n&&(u&&n&&($.isPlainObject(n)||(t=$.isArray(n)))?(t?(t=!1,o=e&&$.isArray(e)?e:[]):o=e&&$.isPlainObject(e)?e:{},a[i]=$.extend(u,o,n)):void 0!==n&&(a[i]=n)));return a},$.queue=function(e,t,n){if(e){t=(t||"fx")+"queue";var i=$.data(e,t);return n?(!i||$.isArray(n)?i=$.data(e,t,function(e,t){var n=t||[];return e&&(isArraylike(Object(e))?function(e,t){for(var n=+t.length,i=0,r=e.length;i<n;)e[r++]=t[i++];if(n!==n)for(;void 0!==t[i];)e[r++]=t[i++];e.length=r}(n,"string"==typeof e?[e]:e):[].push.call(n,e)),n}(n)):i.push(n),i):i||[]}},$.dequeue=function(e,t){$.each(e.nodeType?[e]:e,function(e,n){t=t||"fx";var i=$.queue(n,t),r=i.shift();"inprogress"===r&&(r=i.shift()),r&&("fx"===t&&i.unshift("inprogress"),r.call(n,function(){$.dequeue(n,t)}))})},$.fn=$.prototype={init:function(e){if(e.nodeType)return this[0]=e,this;throw new Error("Not a DOM node.")},offset:function(){var t=this[0].getBoundingClientRect?this[0].getBoundingClientRect():{top:0,left:0};return{top:t.top+(e.pageYOffset||document.scrollTop||0)-(document.clientTop||0),left:t.left+(e.pageXOffset||document.scrollLeft||0)-(document.clientLeft||0)}},position:function(){var e=this[0],t=function(e){for(var t=e.offsetParent;t&&"html"!==t.nodeName.toLowerCase()&&t.style&&"static"===t.style.position;)t=t.offsetParent;return t||document}(e),n=this.offset(),i=/^(?:body|html)$/i.test(t.nodeName)?{top:0,left:0}:$(t).offset();return n.top-=parseFloat(e.style.marginTop)||0,n.left-=parseFloat(e.style.marginLeft)||0,t.style&&(i.top+=parseFloat(t.style.borderTopWidth)||0,i.left+=parseFloat(t.style.borderLeftWidth)||0),{top:n.top-i.top,left:n.left-i.left}}};var t={};$.expando="velocity"+(new Date).getTime(),$.uuid=0;for(var n={},i=n.hasOwnProperty,r=n.toString,o="Boolean Number String Function Array Date RegExp Object Error".split(" "),a=0;a<o.length;a++)n["[object "+o[a]+"]"]=o[a].toLowerCase();$.fn.init.prototype=$.fn,e.Velocity={Utilities:$}}}(window),function(r){"use strict";"object"==typeof e&&"object"==typeof e.exports?e.exports=r():(n=r,void 0!==(i="function"==typeof n?n.call(exports,t,exports,e):n)&&(e.exports=i))}(function(){"use strict";return function(e,t,n,i){function compactSparseArray(e){for(var t=-1,n=e?e.length:0,i=[];++t<n;){var r=e[t];r&&i.push(r)}return i}function sanitizeElements(e){return u.isWrapped(e)?e=s.call(e):u.isNode(e)&&(e=[e]),e}function Data(e){var t=$.data(e,"velocity");return null===t?i:t}function pauseDelayOnElement(e,t){var n=Data(e);n&&n.delayTimer&&!n.delayPaused&&(n.delayRemaining=n.delay-t+n.delayBegin,n.delayPaused=!0,clearTimeout(n.delayTimer.setTimeout))}function resumeDelayOnElement(e,t){var n=Data(e);n&&n.delayTimer&&n.delayPaused&&(n.delayPaused=!1,n.delayTimer.setTimeout=setTimeout(n.delayTimer.next,n.delayRemaining))}function generateStep(e){return function(t){return Math.round(t*e)*(1/e)}}function generateBezier(e,n,i,r){function A(e,t){return 1-3*t+3*e}function B(e,t){return 3*t-6*e}function C(e){return 3*e}function calcBezier(e,t,n){return((A(t,n)*e+B(t,n))*e+C(t))*e}function getSlope(e,t,n){return 3*A(t,n)*e*e+2*B(t,n)*e+C(t)}function newtonRaphsonIterate(t,n){for(var r=0;r<o;++r){var a=getSlope(n,e,i);if(0===a)return n;n-=(calcBezier(n,e,i)-t)/a}return n}function calcSampleValues(){for(var t=0;t<u;++t)h[t]=calcBezier(t*c,e,i)}function binarySubdivide(t,n,r){var o,a,u=0;do{a=n+(r-n)/2,o=calcBezier(a,Line truncated
|
||||
* vue-resource v1.3.4
|
||||
* https://github.com/pagekit/vue-resource
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
var i=2;Promise$1.reject=function(e){return new Promise$1(function(t,n){n(e)})},Promise$1.resolve=function(e){return new Promise$1(function(t,n){t(e)})},Promise$1.all=function(e){return new Promise$1(function(t,n){var i=0,r=[];0===e.length&&t(r);for(var o=0;o<e.length;o+=1)Promise$1.resolve(e[o]).then(function(n){return function(o){r[n]=o,(i+=1)===e.length&&t(r)}}(o),n)})},Promise$1.race=function(e){return new Promise$1(function(t,n){for(var i=0;i<e.length;i+=1)Promise$1.resolve(e[i]).then(t,n)})};var r=Promise$1.prototype;r.resolve=function(e){var t=this;if(t.state===i){if(e===t)throw new TypeError("Promise settled with itself.");var n=!1;try{var r=e&&e.then;if(null!==e&&"object"==typeof e&&"function"==typeof r)return void r.call(e,function(e){n||t.resolve(e),n=!0},function(e){n||t.reject(e),n=!0})}catch(e){return void(n||t.reject(e))}t.state=0,t.value=e,t.notify()}},r.reject=function(e){var t=this;if(t.state===i){if(e===t)throw new TypeError("Promise settled with itself.");t.state=1,t.value=e,t.notify()}},r.notify=function(){var e=this;nextTick(function(){if(e.state!==i)for(;e.deferred.length;){var t=e.deferred.shift(),n=t[0],r=t[1],o=t[2],a=t[3];try{0===e.state?o("function"==typeof n?n.call(void 0,e.value):e.value):1===e.state&&("function"==typeof r?o(r.call(void 0,e.value)):a(e.value))}catch(e){a(e)}}})},r.then=function(e,t){var n=this;return new Promise$1(function(i,r){n.deferred.push([e,t,i,r]),n.notify()})},r.catch=function(e){return this.then(void 0,e)},"undefined"==typeof Promise&&(window.Promise=Promise$1),PromiseObj.all=function(e,t){return new PromiseObj(Promise.all(e),t)},PromiseObj.resolve=function(e,t){return new PromiseObj(Promise.resolve(e),t)},PromiseObj.reject=function(e,t){return new PromiseObj(Promise.reject(e),t)},PromiseObj.race=function(e,t){return new PromiseObj(Promise.race(e),t)};var o=PromiseObj.prototype;o.bind=function(e){return this.context=e,this},o.then=function(e,t){return e&&e.bind&&this.context&&(e=e.bind(this.context)),t&&t.bind&&this.context&&(t=t.bind(this.context)),new PromiseObj(this.promise.then(e,t),this.context)},o.catch=function(e){return e&&e.bind&&this.context&&(e=e.bind(this.context)),new PromiseObj(this.promise.catch(e),this.context)},o.finally=function(e){return this.then(function(t){return e.call(this),t},function(t){return e.call(this),Promise.reject(t)})};var a,s={},l=s.hasOwnProperty,u=[],c=u.slice,d=!1,f="undefined"!=typeof window,h=function(e){var t=e.config,n=e.nextTick;a=n,d=t.debug||!t.silent},p=Array.isArray,m=Object.assign||_assign,v=function(e,t){var n=t(e);return isString(e.root)&&!/^(https?:)?\//.test(n)&&(n=trimEnd(e.root,"/")+"/"+n),n},g=function(e,t){var n=Object.keys(Url.options.params),i={},r=t(e);return each(e.params,function(e,t){-1===n.indexOf(t)&&(i[t]=e)}),i=Url.params(i),i&&(r+=(-1==r.indexOf("?")?"?":"&")+i),r},y=function(e){var t=[],n=expand(e.url,e.params,t);return t.forEach(function(t){delete e.params[t]}),n};Url.options={url:"",root:null,params:{}},Url.transform={template:y,query:g,root:v},Url.transforms=["template","query","root"],Url.params=function(e){var t=[],n=encodeURIComponent;return t.add=function(e,t){isFunction(t)&&(t=t()),null===t&&(t=""),this.push(n(e)+"="+n(t))},serialize(t,e),t.join("&").replace(/%20/g,"+")},Url.parse=function(e){var t=document.createElement("a");return document.documentMode&&(t.href=e,e=t.href),t.href=e,{href:t.href,protocol:t.protocol?t.protocol.replace(/:$/,""):"",port:t.port,host:t.host,hostname:t.hostname,pathname:"/"===t.pathname.charAt(0)?t.pathname:"/"+t.pathname,search:t.search?t.search.replace(/^\?/,""):"",hash:t.hash?t.hash.replace(/^#/,""):""}};var b=function(e){return new PromiseObj(function(t){var n=new XDomainRequest,i=function(i){var r=i.type,o=0;"load"===r?o=200:"error"===r&&(o=500),t(e.respondWith(n.responseText,{status:o}))};e.abort=function(){return n.abort()},n.open(e.method,e.getUrl()),e.timeout&&(n.timeout=e.timeout),n.onload=i,n.onabort=i,n.onerror=i,n.ontimeout=i,n.onprogress=function(){},n.send(e.getBody())})},_=f&&"withCredentials"in new XMLHttpRequest,x=function(e,t){if(f){var n=Url.parse(location.href),i=Url.parse(e.getUrl());i.protocol===n.protocol&&i.host===n.host||(e.crossOrigin=!0,e.emulateHTTP=!1,_||(e.client=b))}t()},w=function(e,t){isFormData(e.body)?e.headers.delete("Content-Type"):isObject(e.body)&&e.emulateJSON&&(e.body=Url.params(e.body),e.headers.set("Content-Type","application/x-www-form-urlencoded")),t()},C=function(e,t){var n=e.headers.get("Content-Type")||"";isObject(e.body)&&0===n.indexOf("application/json")&&(e.body=JSON.stringify(e.body)),t(function(e){return e.bodyText?when(e.text(),function(t){if(n=e.headers.get("Content-Type")||"",0===n.indexOf("application/json")||isJson(t))try{e.body=JSON.parse(t)}catch(t){e.body=null}else e.body=t;return e}):e})},k=function(e){return new PromiseObj(function(t){var n,i,r=e.jsonp||"callback",o=e.jsonpCallback||"_jsonp"+Math.random().toString(36).substr(2),a=null;n=function(n){var r=n.type,s=0;"load"===r&&null!==aLine truncated
|
||||
//# sourceMappingURL=vendor.392879af4bb24a810ba3.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["webpack:///static/js/vendor.392879af4bb24a810ba3.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_string-trim.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_to-object.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_iter-create.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_to-iobject.js","webpack:///./node_modules/_vue-loader@13.5.0@vue-loader/lib/component-normalizer.js","webpack:///./node_modules/_deepmerge@1.5.2@deepmerge/dist/cjs.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_uid.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.string.small.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_core.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_ie8-dom-define.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_typed-buffer.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es7.math.signbit.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_fails.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_to-length.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.string.fontcolor.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_date-to-primitive.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.number.is-integer.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_core.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_shared.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_array-methods.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.regexp.replace.js","webpack:///./node_modules/_babel-runtime@6.26.0@babel-runtime/core-js/object/get-own-property-descriptor.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.math.sign.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_task.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_object-assign.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.string.fixed.js","webpack:///./node_modules/_async-validator@1.8.1@async-validator/es/validator/date.js","webpack:///./node_modules/_babel-runtime@6.26.0@babel-runtime/core-js/symbol/iterator.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.string.starts-with.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_defined.js","webpack:///./node_modules/_element-ui@2.0.5@element-ui/lib/utils/merge.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/core.regexp.escape.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/_object-create.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_is-array.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_property-desc.js","webpack:///./node_modules/_babel-runtime@6.26.0@babel-runtime/core-js/json/stringify.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.typed.int8-array.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_math-expm1.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/es6.object.keys.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es7.promise.try.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.object.is.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_species-constructor.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es7.set.from.js","webpack:///./node_modules/_babel-runtime@6.26.0@babel-runtime/helpers/extends.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_replacer.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_create-property.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.math.expm1.js","webpack:///./node_modules/_core-js@2.5.1@core-js/fn/regexp/escape.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/fn/object/create.js","webpack:///./node_modules/_element-ui@2.0.5@element-ui/lib/utils/clickoutside.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.string.includes.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.regexp.search.js","webpack:///./node_modules/_async-validator@1.8.1@async-validator/es/rule/enum.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es7.map.from.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.reflect.get.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.object.set-prototype-of.js","webpack:///./node_modules/_core-js@2.5.1@core-js/library/modules/es6.object.define-property.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/_to-index.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.array.every.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es6.math.atanh.js","webpack:///./node_modules/_core-js@2.5.1@core-js/modules/es7.math.rad-per-deg.js","webpack:///./node_modules/_element-ui@2.0.5@element-ui/lib/inLine truncated
|
||||
@@ -0,0 +1,68 @@
|
||||
@if "%DEBUG%" == "" echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Tank build script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if "%GOPATH%"=="" (
|
||||
echo The GOPATH environment variable is not defined correctly
|
||||
goto end
|
||||
)
|
||||
|
||||
set PRE_DIR=%cd%
|
||||
|
||||
cd %GOPATH%
|
||||
|
||||
echo golang.org . Please download from: https://github.com/MXi4oyu/golang.org and put in the directory with same level of github.com
|
||||
@rem echo go get golang.org/x
|
||||
@rem go get golang.org/x
|
||||
|
||||
@rem resize image
|
||||
echo go get github.com/disintegration/imaging
|
||||
go get github.com/disintegration/imaging
|
||||
|
||||
@rem json parser
|
||||
echo go get github.com/json-iterator/go
|
||||
go get github.com/json-iterator/go
|
||||
|
||||
|
||||
@rem mysql
|
||||
echo go get github.com/go-sql-driver/mysql
|
||||
go get github.com/go-sql-driver/mysql
|
||||
|
||||
@rem dao database
|
||||
echo go get github.com/jinzhu/gorm
|
||||
go get github.com/jinzhu/gorm
|
||||
|
||||
|
||||
@rem uuid
|
||||
echo go get github.com/nu7hatch/gouuid
|
||||
go get github.com/nu7hatch/gouuid
|
||||
|
||||
echo build tank ...
|
||||
go install tank
|
||||
|
||||
echo packaging
|
||||
set distPath=%GOPATH%\src\tank\dist
|
||||
if exist %distPath% (
|
||||
echo clear %distPath%
|
||||
rmdir /s/q %distPath%
|
||||
)
|
||||
|
||||
echo create directory %distPath%
|
||||
md %distPath%
|
||||
|
||||
echo copying tank.exe
|
||||
copy %GOPATH%\bin\tank.exe %distPath%
|
||||
|
||||
echo copying build
|
||||
xcopy %GOPATH%\src\tank\build %distPath% /e/h
|
||||
|
||||
cd %PRE_DIR%
|
||||
|
||||
echo check the dist file in %distPath%
|
||||
echo finish!
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
EXE_PATH=$GOPATH/bin/tank
|
||||
|
||||
EDASPID=`ps -ef | grep "$EXE_PATH"|grep -v grep |head -n 1 | awk '{print $2}'`
|
||||
if [ -z $EDASPID ];
|
||||
then
|
||||
echo "Cannot find $EXE_PATH."
|
||||
else
|
||||
kill -9 $EDASPID
|
||||
echo $EXE_PATH
|
||||
echo 'Shutdown successfully.'
|
||||
fi
|
||||
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
# executable path
|
||||
EXE_PATH=$GOPATH/bin/tank
|
||||
|
||||
# execute arguments
|
||||
MysqlHost=127.0.0.1
|
||||
MysqlPort=3306
|
||||
MysqlSchema=tank
|
||||
MysqlUserName=tank
|
||||
MysqlPassword=Tank_123
|
||||
|
||||
AdminUsername=admin
|
||||
AdminEmail=lish516@126.com
|
||||
AdminPassword=123456
|
||||
|
||||
if [ -f "$EXE_PATH" ]; then
|
||||
nohup $EXE_PATH -MysqlHost=$MysqlHost -MysqlPort=$MysqlPort -MysqlSchema=$MysqlSchema -MysqlUserName=$MysqlUserName -MysqlPassword=$MysqlPassword -AdminUsername=$AdminUsername -AdminEmail=$AdminEmail -AdminPassword=$AdminPassword >/dev/null 2>&1 &
|
||||
else
|
||||
echo 'Cannot find $EXE_PATH.'
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
homePath=$GOPATH/src/tank
|
||||
|
||||
oldPath=$(pwd)
|
||||
|
||||
echo "cd homePath"
|
||||
cd $homePath
|
||||
|
||||
echo "shutdown tank"
|
||||
source $homePath/doc/script/shutdown.sh
|
||||
|
||||
echo "git reset"
|
||||
git reset --hard HEAD
|
||||
|
||||
echo "git pull"
|
||||
git pull
|
||||
|
||||
echo "go install tank"
|
||||
go install tank
|
||||
|
||||
cd $oldPath
|
||||
|
||||
echo "startup tank"
|
||||
source $homePath/doc/script/startup.sh
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"log"
|
||||
"net/http"
|
||||
"tank/rest"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
//将运行时参数装填到config中去。
|
||||
rest.PrepareConfigs()
|
||||
context := rest.NewContext()
|
||||
defer context.Destroy()
|
||||
|
||||
http.Handle("/", context.Router)
|
||||
|
||||
dotPort := fmt.Sprintf(":%v", rest.CONFIG.ServerPort)
|
||||
|
||||
info := fmt.Sprintf("App started at http://localhost%v", dotPort)
|
||||
rest.LogInfo(info)
|
||||
|
||||
err := http.ListenAndServe(dotPort, nil)
|
||||
if err != nil {
|
||||
log.Fatal("ListenAndServe: ", err)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,459 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/disintegration/imaging"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type AlienController struct {
|
||||
BaseController
|
||||
uploadTokenDao *UploadTokenDao
|
||||
downloadTokenDao *DownloadTokenDao
|
||||
matterDao *MatterDao
|
||||
matterService *MatterService
|
||||
}
|
||||
|
||||
//初始化方法
|
||||
func (this *AlienController) Init(context *Context) {
|
||||
this.BaseController.Init(context)
|
||||
|
||||
//手动装填本实例的Bean.
|
||||
b := context.GetBean(this.uploadTokenDao)
|
||||
if c, ok := b.(*UploadTokenDao); ok {
|
||||
this.uploadTokenDao = c
|
||||
}
|
||||
|
||||
b = context.GetBean(this.downloadTokenDao)
|
||||
if c, ok := b.(*DownloadTokenDao); ok {
|
||||
this.downloadTokenDao = c
|
||||
}
|
||||
|
||||
b = context.GetBean(this.matterDao)
|
||||
if c, ok := b.(*MatterDao); ok {
|
||||
this.matterDao = c
|
||||
}
|
||||
|
||||
b = context.GetBean(this.matterService)
|
||||
if c, ok := b.(*MatterService); ok {
|
||||
this.matterService = c
|
||||
}
|
||||
}
|
||||
|
||||
//注册自己的路由。
|
||||
func (this *AlienController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
||||
|
||||
//每个Controller需要主动注册自己的路由。
|
||||
routeMap["/api/alien/fetch/upload/token"] = this.Wrap(this.FetchUploadToken, USER_ROLE_GUEST)
|
||||
routeMap["/api/alien/fetch/download/token"] = this.Wrap(this.FetchDownloadToken, USER_ROLE_GUEST)
|
||||
routeMap["/api/alien/confirm"] = this.Wrap(this.Confirm, USER_ROLE_GUEST)
|
||||
routeMap["/api/alien/upload"] = this.Wrap(this.Upload, USER_ROLE_GUEST)
|
||||
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//处理一些特殊的接口,比如参数包含在路径中,一般情况下,controller不将参数放在url路径中
|
||||
func (this *AlienController) HandleRoutes(writer http.ResponseWriter, request *http.Request) (func(writer http.ResponseWriter, request *http.Request), bool) {
|
||||
|
||||
path := request.URL.Path
|
||||
|
||||
//匹配 /api/alien/download/{uuid}/{filename}
|
||||
reg := regexp.MustCompile(`^/api/alien/download/([^/]+)/([^/]+)$`)
|
||||
strs := reg.FindStringSubmatch(path)
|
||||
if len(strs) != 3 {
|
||||
return nil, false
|
||||
} else {
|
||||
var f = func(writer http.ResponseWriter, request *http.Request) {
|
||||
this.Download(writer, request, strs[1], strs[2])
|
||||
}
|
||||
return f, true
|
||||
}
|
||||
}
|
||||
|
||||
//直接使用邮箱和密码获取用户
|
||||
func (this *AlienController) CheckRequestUser(email, password string) *User {
|
||||
|
||||
if email == "" {
|
||||
panic("邮箱必填啦")
|
||||
}
|
||||
|
||||
if password == "" {
|
||||
panic("密码必填")
|
||||
}
|
||||
|
||||
//验证用户身份合法性。
|
||||
user := this.userDao.FindByEmail(email)
|
||||
if user == nil {
|
||||
panic(`邮箱或密码错误`)
|
||||
} else {
|
||||
if !MatchBcrypt(password, user.Password) {
|
||||
panic(`邮箱或密码错误`)
|
||||
}
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
//系统中的用户x要获取一个UploadToken,用于提供给x信任的用户上传文件。
|
||||
func (this *AlienController) FetchUploadToken(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
//文件名。
|
||||
filename := request.FormValue("filename")
|
||||
if filename == "" {
|
||||
panic("文件名必填")
|
||||
} else if m, _ := regexp.MatchString(`[<>|*?/\\]`, filename); m {
|
||||
panic(fmt.Sprintf(`【%s】不符合要求,文件名中不能包含以下特殊符号:< > | * ? / \`, filename))
|
||||
}
|
||||
|
||||
//什么时间后过期,默认24h
|
||||
expireStr := request.FormValue("expire")
|
||||
expire := 24 * 60 * 60
|
||||
if expireStr != "" {
|
||||
var err error
|
||||
expire, err = strconv.Atoi(expireStr)
|
||||
if err != nil {
|
||||
panic(`过期时间不符合规范`)
|
||||
}
|
||||
if expire < 1 {
|
||||
panic(`过期时间不符合规范`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//文件公有或私有
|
||||
privacyStr := request.FormValue("privacy")
|
||||
var privacy bool
|
||||
if privacyStr == "" {
|
||||
panic(`文件公有性必填`)
|
||||
} else {
|
||||
if privacyStr == "true" {
|
||||
privacy = true
|
||||
} else if privacyStr == "false" {
|
||||
privacy = false
|
||||
} else {
|
||||
panic(`文件公有性不符合规范`)
|
||||
}
|
||||
}
|
||||
|
||||
//文件大小
|
||||
sizeStr := request.FormValue("size")
|
||||
var size int64
|
||||
if sizeStr == "" {
|
||||
panic(`文件大小必填`)
|
||||
} else {
|
||||
|
||||
var err error
|
||||
size, err = strconv.ParseInt(sizeStr, 10, 64)
|
||||
if err != nil {
|
||||
panic(`文件大小不符合规范`)
|
||||
}
|
||||
if size < 1 {
|
||||
panic(`文件大小不符合规范`)
|
||||
}
|
||||
}
|
||||
|
||||
//文件夹路径,以 / 开头。
|
||||
dir := request.FormValue("dir")
|
||||
|
||||
user := this.CheckRequestUser(request.FormValue("email"), request.FormValue("password"))
|
||||
dirUuid := this.matterService.GetDirUuid(user.Uuid, dir)
|
||||
|
||||
mm, _ := time.ParseDuration(fmt.Sprintf("%ds", expire))
|
||||
uploadToken := &UploadToken{
|
||||
UserUuid: user.Uuid,
|
||||
FolderUuid: dirUuid,
|
||||
MatterUuid: "",
|
||||
ExpireTime: time.Now().Add(mm),
|
||||
Filename: filename,
|
||||
Privacy: privacy,
|
||||
Size: size,
|
||||
Ip: GetIpAddress(request),
|
||||
}
|
||||
|
||||
uploadToken = this.uploadTokenDao.Create(uploadToken)
|
||||
|
||||
return this.Success(uploadToken)
|
||||
|
||||
}
|
||||
|
||||
//系统中的用户x 拿着某个文件的uuid来确认是否其信任的用户已经上传好了。
|
||||
func (this *AlienController) Confirm(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
matterUuid := request.FormValue("matterUuid")
|
||||
if matterUuid == "" {
|
||||
panic("matterUuid必填")
|
||||
}
|
||||
|
||||
user := this.CheckRequestUser(request.FormValue("email"), request.FormValue("password"))
|
||||
|
||||
matter := this.matterDao.CheckByUuid(matterUuid)
|
||||
if matter.UserUuid != user.Uuid {
|
||||
panic("文件不属于你")
|
||||
}
|
||||
|
||||
return this.Success(matter)
|
||||
}
|
||||
|
||||
//系统中的用户x 信任的用户上传文件。这个接口需要支持跨域。
|
||||
func (this *AlienController) Upload(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
//允许跨域请求。
|
||||
this.allowCORS(writer)
|
||||
if request.Method == "OPTIONS" {
|
||||
return this.Success("OK")
|
||||
}
|
||||
|
||||
uploadTokenUuid := request.FormValue("uploadTokenUuid")
|
||||
if uploadTokenUuid == "" {
|
||||
panic("uploadTokenUuid必填")
|
||||
}
|
||||
|
||||
uploadToken := this.uploadTokenDao.FindByUuid(uploadTokenUuid)
|
||||
if uploadToken == nil {
|
||||
panic("uploadTokenUuid无效")
|
||||
}
|
||||
|
||||
if uploadToken.ExpireTime.Before(time.Now()) {
|
||||
panic("uploadToken已失效")
|
||||
}
|
||||
|
||||
user := this.userDao.CheckByUuid(uploadToken.UserUuid)
|
||||
|
||||
request.ParseMultipartForm(32 << 20)
|
||||
file, handler, err := request.FormFile("file")
|
||||
this.PanicError(err)
|
||||
defer file.Close()
|
||||
|
||||
if handler.Filename != uploadToken.Filename {
|
||||
panic("文件名称不正确")
|
||||
}
|
||||
|
||||
if handler.Size != uploadToken.Size {
|
||||
panic("文件大小不正确")
|
||||
}
|
||||
|
||||
matter := this.matterService.Upload(file, user, uploadToken.FolderUuid, uploadToken.Filename, uploadToken.Privacy)
|
||||
|
||||
//更新这个uploadToken的信息.
|
||||
uploadToken.ExpireTime = time.Now()
|
||||
this.uploadTokenDao.Save(uploadToken)
|
||||
|
||||
return this.Success(matter)
|
||||
}
|
||||
|
||||
//系统中的用户x要获取一个DownloadToken,用于提供给x信任的用户下载文件。
|
||||
func (this *AlienController) FetchDownloadToken(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
matterUuid := request.FormValue("matterUuid")
|
||||
if matterUuid == "" {
|
||||
panic("matterUuid必填")
|
||||
}
|
||||
|
||||
user := this.CheckRequestUser(request.FormValue("email"), request.FormValue("password"))
|
||||
|
||||
matter := this.matterDao.CheckByUuid(matterUuid)
|
||||
if matter.UserUuid != user.Uuid {
|
||||
panic("文件不属于你")
|
||||
}
|
||||
if matter.Dir {
|
||||
panic("不支持下载文件夹")
|
||||
}
|
||||
|
||||
//什么时间后过期,默认24h
|
||||
expireStr := request.FormValue("expire")
|
||||
expire := 24 * 60 * 60
|
||||
if expireStr != "" {
|
||||
var err error
|
||||
expire, err = strconv.Atoi(expireStr)
|
||||
if err != nil {
|
||||
panic(`过期时间不符合规范`)
|
||||
}
|
||||
if expire < 1 {
|
||||
panic(`过期时间不符合规范`)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mm, _ := time.ParseDuration(fmt.Sprintf("%ds", expire))
|
||||
downloadToken := &DownloadToken{
|
||||
UserUuid: user.Uuid,
|
||||
MatterUuid: matterUuid,
|
||||
ExpireTime: time.Now().Add(mm),
|
||||
Ip: GetIpAddress(request),
|
||||
}
|
||||
|
||||
downloadToken = this.downloadTokenDao.Create(downloadToken)
|
||||
|
||||
return this.Success(downloadToken)
|
||||
|
||||
}
|
||||
|
||||
//下载一个文件。既可以使用登录的方式下载,也可以使用授权的方式下载。
|
||||
func (this *AlienController) Download(writer http.ResponseWriter, request *http.Request, uuid string, filename string) {
|
||||
|
||||
matter := this.matterDao.CheckByUuid(uuid)
|
||||
|
||||
//判断是否是文件夹
|
||||
if matter.Dir {
|
||||
panic("暂不支持下载文件夹")
|
||||
}
|
||||
|
||||
if matter.Name != filename {
|
||||
panic("文件信息错误")
|
||||
}
|
||||
|
||||
//验证用户的权限问题。
|
||||
//文件如果是私有的才需要权限
|
||||
if matter.Privacy {
|
||||
|
||||
//1.如果带有downloadTokenUuid那么就按照token的信息去获取。
|
||||
downloadTokenUuid := request.FormValue("downloadTokenUuid")
|
||||
if downloadTokenUuid != "" {
|
||||
downloadToken := this.downloadTokenDao.CheckByUuid(downloadTokenUuid)
|
||||
if downloadToken.ExpireTime.Before(time.Now()) {
|
||||
panic("downloadToken已失效")
|
||||
}
|
||||
|
||||
if downloadToken.MatterUuid != uuid {
|
||||
panic("token和文件信息不一致")
|
||||
}
|
||||
|
||||
tokenUser := this.userDao.CheckByUuid(downloadToken.UserUuid)
|
||||
if matter.UserUuid != tokenUser.Uuid {
|
||||
panic(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
//下载之后立即过期掉。
|
||||
downloadToken.ExpireTime = time.Now()
|
||||
this.downloadTokenDao.Save(downloadToken)
|
||||
|
||||
} else {
|
||||
|
||||
//判断文件的所属人是否正确
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && matter.UserUuid != user.Uuid {
|
||||
panic(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
diskFile, err := os.Open(GetFilePath() + matter.Path)
|
||||
this.PanicError(err)
|
||||
defer diskFile.Close()
|
||||
// 防止中文乱码
|
||||
fileName := url.QueryEscape(matter.Name)
|
||||
writer.Header().Set("Content-Type", GetMimeType(fileName))
|
||||
|
||||
//如果是图片或者文本就直接打开。
|
||||
mimeType := GetMimeType(matter.Name)
|
||||
if strings.Index(mimeType, "image") != 0 && strings.Index(mimeType, "text") != 0 {
|
||||
writer.Header().Set("content-disposition", "attachment; filename=\""+fileName+"\"")
|
||||
}
|
||||
|
||||
//对图片做缩放处理。
|
||||
imageProcess := request.FormValue("imageProcess")
|
||||
if imageProcess == "resize" {
|
||||
|
||||
//当前的文件是否是图片,只有图片才能处理。
|
||||
extension := GetExtension(matter.Name)
|
||||
formats := map[string]imaging.Format{
|
||||
".jpg": imaging.JPEG,
|
||||
".jpeg": imaging.JPEG,
|
||||
".png": imaging.PNG,
|
||||
".tif": imaging.TIFF,
|
||||
".tiff": imaging.TIFF,
|
||||
".bmp": imaging.BMP,
|
||||
".gif": imaging.GIF,
|
||||
}
|
||||
|
||||
format, ok := formats[extension]
|
||||
if !ok {
|
||||
panic("该图片格式不支持处理")
|
||||
}
|
||||
|
||||
imageResizeM := request.FormValue("imageResizeM")
|
||||
if imageResizeM == "" {
|
||||
imageResizeM = "fit"
|
||||
} else if imageResizeM != "fit" && imageResizeM != "fill" && imageResizeM != "fixed" {
|
||||
panic("imageResizeM参数错误")
|
||||
}
|
||||
imageResizeWStr := request.FormValue("imageResizeW")
|
||||
var imageResizeW int
|
||||
if imageResizeWStr != "" {
|
||||
imageResizeW, err = strconv.Atoi(imageResizeWStr)
|
||||
this.PanicError(err)
|
||||
if imageResizeW < 1 || imageResizeW > 4096 {
|
||||
panic("缩放尺寸不能超过4096")
|
||||
}
|
||||
}
|
||||
imageResizeHStr := request.FormValue("imageResizeH")
|
||||
var imageResizeH int
|
||||
if imageResizeHStr != "" {
|
||||
imageResizeH, err = strconv.Atoi(imageResizeHStr)
|
||||
this.PanicError(err)
|
||||
if imageResizeH < 1 || imageResizeH > 4096 {
|
||||
panic("缩放尺寸不能超过4096")
|
||||
}
|
||||
}
|
||||
|
||||
//单边缩略
|
||||
if imageResizeM == "fit" {
|
||||
//将图缩略成宽度为100,高度按比例处理。
|
||||
if imageResizeW > 0 {
|
||||
src, err := imaging.Decode(diskFile)
|
||||
this.PanicError(err)
|
||||
dst := imaging.Resize(src, imageResizeW, 0, imaging.Lanczos)
|
||||
|
||||
err = imaging.Encode(writer, dst, format)
|
||||
this.PanicError(err)
|
||||
} else if imageResizeH > 0 {
|
||||
//将图缩略成高度为100,宽度按比例处理。
|
||||
src, err := imaging.Decode(diskFile)
|
||||
this.PanicError(err)
|
||||
dst := imaging.Resize(src, 0, imageResizeH, imaging.Lanczos)
|
||||
|
||||
err = imaging.Encode(writer, dst, format)
|
||||
this.PanicError(err)
|
||||
} else {
|
||||
panic("单边缩略必须指定imageResizeW或imageResizeH")
|
||||
}
|
||||
} else if imageResizeM == "fill" {
|
||||
//固定宽高,自动裁剪
|
||||
if imageResizeW > 0 && imageResizeH > 0 {
|
||||
src, err := imaging.Decode(diskFile)
|
||||
this.PanicError(err)
|
||||
dst := imaging.Fill(src, imageResizeW, imageResizeH, imaging.Center, imaging.Lanczos)
|
||||
err = imaging.Encode(writer, dst, format)
|
||||
this.PanicError(err)
|
||||
} else {
|
||||
panic("固定宽高,自动裁剪 必须同时指定imageResizeW和imageResizeH")
|
||||
}
|
||||
} else if imageResizeM == "fixed" {
|
||||
//强制宽高缩略
|
||||
if imageResizeW > 0 && imageResizeH > 0 {
|
||||
src, err := imaging.Decode(diskFile)
|
||||
this.PanicError(err)
|
||||
dst := imaging.Resize(src, imageResizeW, imageResizeH, imaging.Lanczos)
|
||||
|
||||
err = imaging.Encode(writer, dst, format)
|
||||
this.PanicError(err)
|
||||
} else {
|
||||
panic("强制宽高缩略必须同时指定imageResizeW和imageResizeH")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
_, err = io.Copy(writer, diskFile)
|
||||
this.PanicError(err)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/json-iterator/go"
|
||||
"go/types"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IController interface {
|
||||
IBean
|
||||
//注册自己固定的路由。
|
||||
RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request)
|
||||
//处理一些特殊的路由。
|
||||
HandleRoutes(writer http.ResponseWriter, request *http.Request) (func(writer http.ResponseWriter, request *http.Request), bool)
|
||||
}
|
||||
type BaseController struct {
|
||||
Bean
|
||||
userDao *UserDao
|
||||
sessionDao *SessionDao
|
||||
}
|
||||
|
||||
func (this *BaseController) Init(context *Context) {
|
||||
|
||||
this.Bean.Init(context)
|
||||
|
||||
//手动装填本实例的Bean.
|
||||
b := context.GetBean(this.userDao)
|
||||
if b, ok := b.(*UserDao); ok {
|
||||
this.userDao = b
|
||||
}
|
||||
|
||||
b = context.GetBean(this.sessionDao)
|
||||
if b, ok := b.(*SessionDao); ok {
|
||||
this.sessionDao = b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//注册自己的路由。
|
||||
func (this *BaseController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
||||
//每个Controller需要主动注册自己的路由。
|
||||
return make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
||||
}
|
||||
|
||||
//处理一些特殊的接口,比如参数包含在路径中,一般情况下,controller不将参数放在url路径中
|
||||
func (this *BaseController) HandleRoutes(writer http.ResponseWriter, request *http.Request) (func(writer http.ResponseWriter, request *http.Request), bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
//需要进行登录验证的wrap包装
|
||||
func (this *BaseController) Wrap(f func(writer http.ResponseWriter, request *http.Request) *WebResult, role string) func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
return func(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
//writer和request赋值给自己。
|
||||
|
||||
var webResult *WebResult = nil
|
||||
|
||||
//只有游客接口不需要登录
|
||||
if role != USER_ROLE_GUEST {
|
||||
user := this.checkUser(writer, request)
|
||||
if role == USER_ROLE_ADMINISTRATOR && user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
webResult = ConstWebResult(RESULT_CODE_UNAUTHORIZED)
|
||||
} else {
|
||||
webResult = f(writer, request)
|
||||
}
|
||||
} else {
|
||||
webResult = f(writer, request)
|
||||
}
|
||||
|
||||
//输出的是json格式
|
||||
if webResult != nil {
|
||||
//返回的内容申明是json,utf-8
|
||||
writer.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
//用json的方式输出返回值。
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
b, _ := json.Marshal(webResult)
|
||||
|
||||
if webResult.Code == RESULT_CODE_OK {
|
||||
writer.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
|
||||
fmt.Fprintf(writer, string(b))
|
||||
} else {
|
||||
//输出的内容是二进制的。
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//返回成功的结果。
|
||||
func (this *BaseController) Success(data interface{}) *WebResult {
|
||||
var webResult *WebResult = nil
|
||||
if value, ok := data.(string); ok {
|
||||
webResult = &WebResult{Code: RESULT_CODE_OK, Msg: value}
|
||||
} else if value, ok := data.(*WebResult); ok {
|
||||
webResult = value
|
||||
} else if _, ok := data.(types.Nil); ok {
|
||||
webResult = ConstWebResult(RESULT_CODE_OK)
|
||||
} else {
|
||||
webResult = &WebResult{Code: RESULT_CODE_OK, Data: data}
|
||||
}
|
||||
return webResult
|
||||
}
|
||||
|
||||
//返回错误的结果。
|
||||
func (this *BaseController) Error(err interface{}) *WebResult {
|
||||
var webResult *WebResult = nil
|
||||
if value, ok := err.(string); ok {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: value}
|
||||
} else if value, ok := err.(int); ok {
|
||||
webResult = ConstWebResult(value)
|
||||
} else if value, ok := err.(*WebResult); ok {
|
||||
webResult = value
|
||||
} else if value, ok := err.(error); ok {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: value.Error()}
|
||||
} else {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: "服务器未知错误"}
|
||||
}
|
||||
return webResult
|
||||
}
|
||||
|
||||
func (this *BaseController) checkLogin(writer http.ResponseWriter, request *http.Request) (*Session, *User) {
|
||||
|
||||
//验证用户是否已经登录。
|
||||
sessionCookie, err := request.Cookie(COOKIE_AUTH_KEY)
|
||||
if err != nil {
|
||||
panic(ConstWebResult(RESULT_CODE_LOGIN))
|
||||
}
|
||||
|
||||
session := this.sessionDao.FindByUuid(sessionCookie.Value)
|
||||
if session == nil {
|
||||
panic(ConstWebResult(RESULT_CODE_LOGIN))
|
||||
} else {
|
||||
if session.ExpireTime.Before(time.Now()) {
|
||||
panic(ConstWebResult(RESULT_CODE_LOGIN_EXPIRED))
|
||||
} else {
|
||||
|
||||
user := this.userDao.FindByUuid(session.UserUuid)
|
||||
if user == nil {
|
||||
panic(ConstWebResult(RESULT_CODE_LOGIN_INVALID))
|
||||
} else {
|
||||
return session, user
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (this *BaseController) checkUser(writer http.ResponseWriter, request *http.Request) *User {
|
||||
|
||||
_, user := this.checkLogin(writer, request)
|
||||
return user
|
||||
|
||||
}
|
||||
|
||||
//允许跨域请求
|
||||
func (this *BaseController) allowCORS(writer http.ResponseWriter) {
|
||||
writer.Header().Add("Access-Control-Allow-Origin", "*")
|
||||
writer.Header().Add("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE")
|
||||
writer.Header().Add("Access-Control-Max-Age", "3600")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
)
|
||||
|
||||
type BaseDao struct {
|
||||
Bean
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
"reflect"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Time time.Time
|
||||
|
||||
type Base struct {
|
||||
Uuid string `gorm:"primary_key" json:"uuid"`
|
||||
Sort int64 `json:"sort"`
|
||||
ModifyTime time.Time `json:"modifyTime"`
|
||||
CreateTime time.Time `json:"createTime"`
|
||||
}
|
||||
|
||||
//将 Struct 转换成map[string]interface{}类型
|
||||
func (this *Base) Map() map[string]interface{} {
|
||||
t := reflect.TypeOf(this)
|
||||
v := reflect.ValueOf(this)
|
||||
|
||||
var data = make(map[string]interface{})
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
data[t.Field(i).Name] = v.Field(i).Interface()
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
//分页类
|
||||
type Pager struct {
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"pageSize"`
|
||||
TotalItems int `json:"totalItems"`
|
||||
TotalPages int `json:"totalPages"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func NewPager(page int, pageSize int, totalItems int, data interface{}) *Pager {
|
||||
|
||||
return &Pager{
|
||||
Page: page,
|
||||
PageSize: pageSize,
|
||||
TotalItems: totalItems,
|
||||
TotalPages: int(math.Ceil(float64(totalItems) / float64(pageSize))),
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package rest
|
||||
|
||||
type IBean interface {
|
||||
Init(context *Context)
|
||||
PanicError(err error);
|
||||
}
|
||||
|
||||
type Bean struct {
|
||||
context *Context
|
||||
}
|
||||
|
||||
func (this *Bean) Init(context *Context) {
|
||||
this.context = context
|
||||
}
|
||||
|
||||
//处理错误的统一方法
|
||||
func (this *Bean) PanicError(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
+222
@@ -0,0 +1,222 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/json-iterator/go"
|
||||
"time"
|
||||
"unsafe"
|
||||
"io/ioutil"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
)
|
||||
|
||||
const (
|
||||
//用户身份的cookie字段名
|
||||
COOKIE_AUTH_KEY = "_ak"
|
||||
|
||||
//数据库表前缀 tank100表示当前应用版本是tank:1.0.x版,数据库结构发生变化必然是中型升级
|
||||
TABLE_PREFIX = "tank10_"
|
||||
|
||||
//当前版本
|
||||
VERSION = "1.0.0"
|
||||
)
|
||||
|
||||
var (
|
||||
CONFIG = &Config{
|
||||
//以下内容是默认配置项。
|
||||
|
||||
//默认监听端口号
|
||||
ServerPort: 9090,
|
||||
//将日志输出到控制台。
|
||||
LogToConsole: true,
|
||||
//mysql相关配置。
|
||||
//数据库端口
|
||||
MysqlPort: 3306,
|
||||
//数据库Host
|
||||
MysqlHost: "127.0.0.1",
|
||||
//数据库名字
|
||||
MysqlSchema: "tank",
|
||||
//用户名
|
||||
MysqlUserName: "tank",
|
||||
//密码
|
||||
MysqlPassword: "tank123",
|
||||
//数据库连接信息。
|
||||
MysqlUrl: "%MysqlUserName:%MysqlPassword@tcp(%MysqlHost:%MysqlPort)/%MysqlSchema?charset=utf8&parseTime=True&loc=Local",
|
||||
//超级管理员用户名,只能包含英文和数字
|
||||
AdminUsername: "admin",
|
||||
//超级管理员邮箱
|
||||
AdminEmail: "admin@tank.eyeblue.cn",
|
||||
//超级管理员密码
|
||||
AdminPassword: "123456",
|
||||
}
|
||||
)
|
||||
|
||||
//依赖外部定义的变量。
|
||||
type Config struct {
|
||||
//默认监听端口号
|
||||
ServerPort int
|
||||
|
||||
//将日志输出到控制台。
|
||||
LogToConsole bool
|
||||
|
||||
//mysql相关配置。
|
||||
//数据库端口
|
||||
MysqlPort int
|
||||
//数据库Host
|
||||
MysqlHost string
|
||||
//数据库名字
|
||||
MysqlSchema string
|
||||
//用户名
|
||||
MysqlUserName string
|
||||
//密码
|
||||
MysqlPassword string
|
||||
//数据库连接信息。
|
||||
MysqlUrl string
|
||||
|
||||
//超级管理员用户名,只能包含英文和数字
|
||||
AdminUsername string
|
||||
//超级管理员邮箱
|
||||
AdminEmail string
|
||||
//超级管理员密码
|
||||
AdminPassword string
|
||||
}
|
||||
|
||||
//验证配置文件的正确性。
|
||||
func (this *Config) validate() {
|
||||
|
||||
if this.ServerPort == 0 {
|
||||
LogPanic("ServerPort 未配置")
|
||||
}
|
||||
|
||||
if this.MysqlUserName == "" {
|
||||
LogPanic("MysqlUserName 未配置")
|
||||
}
|
||||
|
||||
if this.MysqlPassword == "" {
|
||||
LogPanic("MysqlPassword 未配置")
|
||||
}
|
||||
|
||||
if this.MysqlHost == "" {
|
||||
LogPanic("MysqlHost 未配置")
|
||||
}
|
||||
|
||||
if this.MysqlPort == 0 {
|
||||
LogPanic("MysqlPort 未配置")
|
||||
}
|
||||
|
||||
if this.MysqlSchema == "" {
|
||||
LogPanic("MysqlSchema 未配置")
|
||||
}
|
||||
|
||||
this.MysqlUrl = fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local", this.MysqlUserName, this.MysqlPassword, this.MysqlHost, this.MysqlPort, this.MysqlSchema)
|
||||
|
||||
}
|
||||
|
||||
//init方法只要这个包被引入了就一定会执行。
|
||||
func init() {
|
||||
|
||||
//json中需要去特殊处理时间。
|
||||
jsoniter.RegisterTypeDecoderFunc("time.Time", func(ptr unsafe.Pointer, iter *jsoniter.Iterator) {
|
||||
//如果使用time.UTC,那么时间会相差8小时
|
||||
t, err := time.ParseInLocation("2006-01-02 15:04:05", iter.ReadString(), time.Local)
|
||||
if err != nil {
|
||||
iter.Error = err
|
||||
return
|
||||
}
|
||||
*((*time.Time)(ptr)) = t
|
||||
})
|
||||
|
||||
jsoniter.RegisterTypeEncoderFunc("time.Time", func(ptr unsafe.Pointer, stream *jsoniter.Stream) {
|
||||
t := *((*time.Time)(ptr))
|
||||
//如果使用time.UTC,那么时间会相差8小时
|
||||
stream.WriteString(t.Local().Format("2006-01-02 15:04:05"))
|
||||
}, nil)
|
||||
}
|
||||
|
||||
//从conf/tank.json中获取变量。
|
||||
|
||||
//从flag中或者conf/tank.json中装填变量
|
||||
func PrepareConfigs() {
|
||||
|
||||
//读取配置文件
|
||||
filePath := GetConfPath() + "/tank.json"
|
||||
content, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
LogWarning(fmt.Sprintf("无法找到配置文件:%s,%v", filePath, err))
|
||||
} else {
|
||||
// 用 json.Unmarshal
|
||||
err := json.Unmarshal(content, CONFIG)
|
||||
if err != nil {
|
||||
LogPanic("配置文件格式错误!")
|
||||
}
|
||||
}
|
||||
|
||||
//从运行时参数中读取,运行时参数具有更高优先级。
|
||||
//系统端口号
|
||||
ServerPortPtr := flag.Int("ServerPort", CONFIG.ServerPort, "server port")
|
||||
|
||||
//系统端口号
|
||||
LogToConsolePtr := flag.Bool("LogToConsole", CONFIG.LogToConsole, "write log to console. for debug.")
|
||||
|
||||
//mysql相关配置。
|
||||
MysqlPortPtr := flag.Int("MysqlPort", CONFIG.MysqlPort, "mysql port")
|
||||
MysqlHostPtr := flag.String("MysqlHost", CONFIG.MysqlHost, "mysql host")
|
||||
MysqlSchemaPtr := flag.String("MysqlSchema", CONFIG.MysqlSchema, "mysql schema")
|
||||
MysqlUserNamePtr := flag.String("MysqlUserName", CONFIG.MysqlUserName, "mysql username")
|
||||
MysqlPasswordPtr := flag.String("MysqlPassword", CONFIG.MysqlPassword, "mysql password")
|
||||
|
||||
//超级管理员信息
|
||||
AdminUsernamePtr := flag.String("AdminUsername", CONFIG.AdminUsername, "administrator username")
|
||||
AdminEmailPtr := flag.String("AdminEmail", CONFIG.AdminEmail, "administrator email")
|
||||
AdminPasswordPtr := flag.String("AdminPassword", CONFIG.AdminPassword, "administrator password")
|
||||
|
||||
//flag.Parse()方法必须要在使用之前调用。
|
||||
flag.Parse()
|
||||
|
||||
if *ServerPortPtr != CONFIG.ServerPort {
|
||||
CONFIG.ServerPort = *ServerPortPtr
|
||||
}
|
||||
|
||||
if *LogToConsolePtr != CONFIG.LogToConsole {
|
||||
CONFIG.LogToConsole = *LogToConsolePtr
|
||||
}
|
||||
|
||||
if *MysqlPortPtr != CONFIG.MysqlPort {
|
||||
CONFIG.MysqlPort = *MysqlPortPtr
|
||||
}
|
||||
|
||||
if *MysqlHostPtr != CONFIG.MysqlHost {
|
||||
CONFIG.MysqlHost = *MysqlHostPtr
|
||||
}
|
||||
|
||||
if *MysqlSchemaPtr != CONFIG.MysqlSchema {
|
||||
CONFIG.MysqlSchema = *MysqlSchemaPtr
|
||||
}
|
||||
|
||||
if *MysqlUserNamePtr != CONFIG.MysqlUserName {
|
||||
CONFIG.MysqlUserName = *MysqlUserNamePtr
|
||||
}
|
||||
|
||||
if *MysqlPasswordPtr != CONFIG.MysqlPassword {
|
||||
CONFIG.MysqlPassword = *MysqlPasswordPtr
|
||||
}
|
||||
|
||||
if *AdminUsernamePtr != CONFIG.AdminUsername {
|
||||
CONFIG.AdminUsername = *AdminUsernamePtr
|
||||
}
|
||||
|
||||
if *AdminEmailPtr != CONFIG.AdminEmail {
|
||||
CONFIG.AdminEmail = *AdminEmailPtr
|
||||
}
|
||||
|
||||
if *AdminPasswordPtr != CONFIG.AdminPassword {
|
||||
CONFIG.AdminPassword = *AdminPasswordPtr
|
||||
}
|
||||
|
||||
//验证配置项的正确性
|
||||
CONFIG.validate()
|
||||
|
||||
//安装程序开始导入初始表和初始数据。
|
||||
InstallDatabase()
|
||||
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
//上下文,管理数据库连接,管理所有路由请求,管理所有的单例component.
|
||||
type Context struct {
|
||||
//数据库连接
|
||||
DB *gorm.DB
|
||||
//处理所有路由请求
|
||||
Router *Router
|
||||
//各类的Bean Map。这里面是包含ControllerMap中所有元素
|
||||
BeanMap map[string]IBean
|
||||
//只包含了Controller的map
|
||||
ControllerMap map[string]IController
|
||||
}
|
||||
|
||||
func (this *Context) OpenDb() {
|
||||
|
||||
var err error = nil
|
||||
this.DB, err = gorm.Open("mysql", CONFIG.MysqlUrl)
|
||||
|
||||
//是否打开sql日志
|
||||
this.DB.LogMode(false)
|
||||
if err != nil {
|
||||
panic("failed to connect mysql database")
|
||||
}
|
||||
}
|
||||
|
||||
func (this *Context) CloseDb() {
|
||||
|
||||
if this.DB != nil {
|
||||
this.DB.Close()
|
||||
}
|
||||
}
|
||||
|
||||
//构造方法
|
||||
func NewContext() *Context {
|
||||
|
||||
context := &Context{}
|
||||
|
||||
//处理数据库连接的开关。
|
||||
context.OpenDb()
|
||||
|
||||
//初始化Map
|
||||
context.BeanMap = make(map[string]IBean)
|
||||
context.ControllerMap = make(map[string]IController)
|
||||
|
||||
//注册各类Beans.在这个方法里面顺便把Controller装入ControllerMap中去。
|
||||
context.registerBeans()
|
||||
|
||||
//初始化每个bean.
|
||||
context.initBeans()
|
||||
|
||||
//初始化Router. 这个方法要在Bean注册好了之后才能。
|
||||
context.Router = NewRouter(context)
|
||||
|
||||
return context
|
||||
|
||||
}
|
||||
|
||||
//注册一个Bean
|
||||
func (this *Context) registerBean(bean IBean) {
|
||||
|
||||
typeOf := reflect.TypeOf(bean)
|
||||
typeName := typeOf.String()
|
||||
|
||||
if element, ok := bean.(IBean); ok {
|
||||
|
||||
err := fmt.Sprintf("【%s】已经被注册了,跳过。", typeName)
|
||||
if _, ok := this.BeanMap[typeName]; ok {
|
||||
LogError(fmt.Sprintf(err))
|
||||
} else {
|
||||
this.BeanMap[typeName] = element
|
||||
|
||||
//看看是不是controller类型,如果是,那么单独放在ControllerMap中。
|
||||
if controller, ok1 := bean.(IController); ok1 {
|
||||
this.ControllerMap[typeName] = controller
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
err := fmt.Sprintf("注册的【%s】不是Bean类型。", typeName)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//注册各个Beans
|
||||
func (this *Context) registerBeans() {
|
||||
|
||||
//alien
|
||||
this.registerBean(new(AlienController))
|
||||
|
||||
//downloadToken
|
||||
this.registerBean(new(DownloadTokenDao))
|
||||
|
||||
//matter
|
||||
this.registerBean(new(MatterController))
|
||||
this.registerBean(new(MatterDao))
|
||||
this.registerBean(new(MatterService))
|
||||
|
||||
//session
|
||||
this.registerBean(new(SessionDao))
|
||||
|
||||
//uploadToken
|
||||
this.registerBean(new(UploadTokenDao))
|
||||
|
||||
//user
|
||||
this.registerBean(new(UserController))
|
||||
this.registerBean(new(UserDao))
|
||||
|
||||
}
|
||||
|
||||
//从Map中获取某个Bean.
|
||||
func (this *Context) GetBean(bean IBean) IBean {
|
||||
|
||||
typeOf := reflect.TypeOf(bean)
|
||||
typeName := typeOf.String()
|
||||
|
||||
if val, ok := this.BeanMap[typeName]; ok {
|
||||
return val
|
||||
} else {
|
||||
err := fmt.Sprintf("【%s】没有注册。", typeName)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
//初始化每个Bean
|
||||
func (this *Context) initBeans() {
|
||||
|
||||
for _, bean := range this.BeanMap {
|
||||
bean.Init(this)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//销毁的方法
|
||||
func (this *Context) Destroy() {
|
||||
this.CloseDb()
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type DownloadTokenDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//按照Id查询
|
||||
func (this *DownloadTokenDao) FindByUuid(uuid string) *DownloadToken {
|
||||
|
||||
// Read
|
||||
var downloadToken = &DownloadToken{}
|
||||
db := this.context.DB.Where(&DownloadToken{Base: Base{Uuid: uuid}}).First(downloadToken)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return downloadToken
|
||||
|
||||
}
|
||||
|
||||
//按照Id查询
|
||||
func (this *DownloadTokenDao) CheckByUuid(uuid string) *DownloadToken {
|
||||
|
||||
// Read
|
||||
var downloadToken = &DownloadToken{}
|
||||
db := this.context.DB.Where(&DownloadToken{Base: Base{Uuid: uuid}}).First(downloadToken)
|
||||
this.PanicError(db.Error)
|
||||
return downloadToken
|
||||
|
||||
}
|
||||
|
||||
//创建一个session并且持久化到数据库中。
|
||||
func (this *DownloadTokenDao) Create(downloadToken *DownloadToken) *DownloadToken {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
downloadToken.Uuid = string(timeUUID.String())
|
||||
|
||||
downloadToken.CreateTime = time.Now()
|
||||
downloadToken.ModifyTime = time.Now()
|
||||
|
||||
db := this.context.DB.Create(downloadToken)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return downloadToken
|
||||
}
|
||||
|
||||
//修改一个downloadToken
|
||||
func (this *DownloadTokenDao) Save(downloadToken *DownloadToken) *DownloadToken {
|
||||
|
||||
downloadToken.ModifyTime = time.Now()
|
||||
db := this.context.DB.Save(downloadToken)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return downloadToken
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type DownloadToken struct {
|
||||
Base
|
||||
UserUuid string `json:"userUuid"`
|
||||
MatterUuid string `json:"matterUuid"`
|
||||
ExpireTime time.Time `json:"expireTime"`
|
||||
Ip string `json:"ip"`
|
||||
}
|
||||
|
||||
func (DownloadToken) TableName() string {
|
||||
return TABLE_PREFIX + "download_token"
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
|
||||
"time"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
//首次运行的时候,将自动安装数据库等内容。
|
||||
func InstallDatabase() {
|
||||
|
||||
db, err := gorm.Open("mysql", CONFIG.MysqlUrl)
|
||||
if err != nil {
|
||||
LogPanic(fmt.Sprintf("无法打开%s", CONFIG.MysqlUrl))
|
||||
}
|
||||
if db != nil {
|
||||
defer db.Close()
|
||||
}
|
||||
|
||||
//这个方法只会简单查看表是否存在,不会去比照每个字段的。因此如果用户自己修改表结构将会出现不可预测的错误。
|
||||
var hasTable = true
|
||||
downloadToken := &DownloadToken{}
|
||||
hasTable = db.HasTable(downloadToken)
|
||||
if !hasTable {
|
||||
|
||||
createDownloadToken := "CREATE TABLE `tank10_download_token` (`uuid` char(36) NOT NULL,`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',`matter_uuid` char(36) DEFAULT NULL COMMENT '文件标识',`expire_time` timestamp NULL DEFAULT NULL COMMENT '授权访问的次数',`ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip',`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='下载的token表';"
|
||||
db = db.Exec(createDownloadToken)
|
||||
if db.Error != nil {
|
||||
LogPanic(db.Error)
|
||||
}
|
||||
LogInfo("创建DownloadToken表")
|
||||
|
||||
}
|
||||
|
||||
matter := &Matter{}
|
||||
hasTable = db.HasTable(matter)
|
||||
if !hasTable {
|
||||
createMatter := "CREATE TABLE `tank10_matter` (`uuid` char(36) NOT NULL,`puuid` varchar(45) DEFAULT NULL COMMENT '上一级的uuid',`user_uuid` char(36) DEFAULT NULL COMMENT '上传的用户id',`dir` tinyint(1) DEFAULT NULL COMMENT '是否是文件夹',`name` varchar(255) DEFAULT NULL COMMENT '文件名称',`md5` varchar(45) DEFAULT NULL COMMENT '文件的md5值',`size` bigint(20) DEFAULT '0' COMMENT '文件大小',`privacy` tinyint(1) DEFAULT '0' COMMENT '文件是否是公有的',`path` varchar(255) DEFAULT NULL,`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='file表';"
|
||||
db = db.Exec(createMatter)
|
||||
if db.Error != nil {
|
||||
LogPanic(db.Error)
|
||||
}
|
||||
LogInfo("创建Matter表")
|
||||
|
||||
}
|
||||
session := &Session{}
|
||||
hasTable = db.HasTable(session)
|
||||
if !hasTable {
|
||||
|
||||
createSession := "CREATE TABLE `tank10_session` (`uuid` char(36) NOT NULL,`authentication` char(36) DEFAULT NULL COMMENT '认证身份,存放在cookie中',`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',`ip` varchar(45) DEFAULT NULL COMMENT '用户的ip地址',`expire_time` timestamp NULL DEFAULT NULL,`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='session表';"
|
||||
db = db.Exec(createSession)
|
||||
if db.Error != nil {
|
||||
LogPanic(db.Error)
|
||||
}
|
||||
LogInfo("创建Session表")
|
||||
}
|
||||
|
||||
uploadToken := &UploadToken{}
|
||||
hasTable = db.HasTable(uploadToken)
|
||||
if !hasTable {
|
||||
|
||||
createUploadToken := "CREATE TABLE `tank10_upload_token` (`uuid` char(36) NOT NULL,`user_uuid` char(36) DEFAULT NULL COMMENT '用户uuid',`folder_uuid` char(36) DEFAULT NULL,`matter_uuid` char(36) DEFAULT NULL,`filename` varchar(255) DEFAULT NULL COMMENT '文件后缀名的过滤,可以只允许用户上传特定格式的文件。',`privacy` tinyint(1) DEFAULT '1',`size` bigint(20) DEFAULT '0',`expire_time` timestamp NULL DEFAULT NULL,`ip` varchar(45) DEFAULT NULL COMMENT '消费者的ip',`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='上传的token表';"
|
||||
db = db.Exec(createUploadToken)
|
||||
if db.Error != nil {
|
||||
LogPanic(db.Error)
|
||||
}
|
||||
LogInfo("创建UploadToken表")
|
||||
}
|
||||
|
||||
user := &User{}
|
||||
hasTable = db.HasTable(user)
|
||||
if !hasTable {
|
||||
|
||||
//验证超级管理员的信息
|
||||
if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, CONFIG.AdminUsername); !m {
|
||||
LogPanic(`超级管理员用户名必填,且只能包含字母,数字和'_''`)
|
||||
}
|
||||
|
||||
if len(CONFIG.AdminPassword) < 6 {
|
||||
LogPanic(`超级管理员密码长度至少为6位`)
|
||||
}
|
||||
|
||||
if CONFIG.AdminEmail == "" {
|
||||
LogPanic("超级管理员邮箱必填!")
|
||||
}
|
||||
|
||||
|
||||
createUser := "CREATE TABLE `tank10_user` (`uuid` char(36) NOT NULL,`role` varchar(45) DEFAULT 'USER',`username` varchar(255) DEFAULT NULL COMMENT '昵称',`password` varchar(255) DEFAULT NULL COMMENT '密码',`email` varchar(45) DEFAULT NULL COMMENT '邮箱',`phone` varchar(45) DEFAULT NULL COMMENT '电话',`gender` varchar(45) DEFAULT 'UNKNOWN' COMMENT '性别,默认未知',`city` varchar(45) DEFAULT NULL COMMENT '城市',`avatar_url` varchar(255) DEFAULT NULL COMMENT '头像链接',`last_time` datetime DEFAULT NULL COMMENT '上次登录使劲按',`last_ip` varchar(45) DEFAULT NULL,`status` varchar(45) DEFAULT 'OK',`sort` bigint(20) DEFAULT NULL,`modify_time` timestamp NULL DEFAULT NULL,`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',PRIMARY KEY (`uuid`),UNIQUE KEY `id_UNIQUE` (`uuid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表描述';"
|
||||
db = db.Exec(createUser)
|
||||
if db.Error != nil {
|
||||
LogPanic(db.Error)
|
||||
}
|
||||
LogInfo("创建User表")
|
||||
|
||||
user := &User{}
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
user.Uuid = string(timeUUID.String())
|
||||
user.CreateTime = time.Now()
|
||||
user.ModifyTime = time.Now()
|
||||
user.LastTime = time.Now()
|
||||
user.Sort = time.Now().UnixNano() / 1e6
|
||||
user.Role = USER_ROLE_ADMINISTRATOR
|
||||
user.Username = CONFIG.AdminUsername
|
||||
user.Password = GetBcrypt(CONFIG.AdminPassword)
|
||||
user.Email = CONFIG.AdminEmail
|
||||
user.Phone = ""
|
||||
user.Gender = USER_GENDER_UNKNOWN
|
||||
user.Status = USER_STATUS_OK
|
||||
|
||||
db.Create(user)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type MatterController struct {
|
||||
BaseController
|
||||
matterDao *MatterDao
|
||||
matterService *MatterService
|
||||
downloadTokenDao *DownloadTokenDao
|
||||
}
|
||||
|
||||
//初始化方法
|
||||
func (this *MatterController) Init(context *Context) {
|
||||
this.BaseController.Init(context)
|
||||
|
||||
//手动装填本实例的Bean. 这里必须要用中间变量方可。
|
||||
b := context.GetBean(this.matterDao)
|
||||
if b, ok := b.(*MatterDao); ok {
|
||||
this.matterDao = b
|
||||
}
|
||||
|
||||
b = context.GetBean(this.matterService)
|
||||
if b, ok := b.(*MatterService); ok {
|
||||
this.matterService = b
|
||||
}
|
||||
|
||||
b = context.GetBean(this.downloadTokenDao)
|
||||
if b, ok := b.(*DownloadTokenDao); ok {
|
||||
this.downloadTokenDao = b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//注册自己的路由。
|
||||
func (this *MatterController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
||||
|
||||
//每个Controller需要主动注册自己的路由。
|
||||
routeMap["/api/matter/create/directory"] = this.Wrap(this.CreateDirectory, USER_ROLE_USER)
|
||||
routeMap["/api/matter/upload"] = this.Wrap(this.Upload, USER_ROLE_USER)
|
||||
routeMap["/api/matter/delete"] = this.Wrap(this.Delete, USER_ROLE_USER)
|
||||
routeMap["/api/matter/delete/batch"] = this.Wrap(this.DeleteBatch, USER_ROLE_USER)
|
||||
routeMap["/api/matter/rename"] = this.Wrap(this.Rename, USER_ROLE_USER)
|
||||
routeMap["/api/matter/move"] = this.Wrap(this.Move, USER_ROLE_USER)
|
||||
routeMap["/api/matter/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
||||
routeMap["/api/matter/page"] = this.Wrap(this.Page, USER_ROLE_USER)
|
||||
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//查看某个文件的详情。
|
||||
func (this *MatterController) Detail(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
if uuid == "" {
|
||||
return this.Error("文件的uuid必填")
|
||||
}
|
||||
|
||||
matter := this.matterDao.FindByUuid(uuid)
|
||||
|
||||
//组装file的内容,展示其父组件。
|
||||
puuid := matter.Puuid
|
||||
tmpMatter := matter
|
||||
for puuid != "root" {
|
||||
pFile := this.matterDao.FindByUuid(puuid)
|
||||
|
||||
tmpMatter.Parent = pFile
|
||||
tmpMatter = pFile
|
||||
puuid = pFile.Puuid
|
||||
|
||||
}
|
||||
|
||||
return this.Success(matter)
|
||||
|
||||
}
|
||||
|
||||
//创建一个文件夹。
|
||||
func (this *MatterController) CreateDirectory(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
puuid := request.FormValue("puuid")
|
||||
name := request.FormValue("name")
|
||||
|
||||
userUuid := request.FormValue("userUuid")
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
userUuid = user.Uuid
|
||||
}
|
||||
user = this.userDao.CheckByUuid(userUuid)
|
||||
|
||||
//验证参数。
|
||||
if name == "" {
|
||||
return this.Error("name参数必填")
|
||||
}
|
||||
if m, _ := regexp.MatchString(`[<>|*?/\\]`, name); m {
|
||||
return this.Error(`名称中不能包含以下特殊符号:< > | * ? / \`)
|
||||
}
|
||||
|
||||
if puuid != "" && puuid != "root" {
|
||||
//找出上一级的文件夹。
|
||||
this.matterDao.FindByUuidAndUserUuid(puuid, user.Uuid)
|
||||
}
|
||||
|
||||
//判断同级文件夹中是否有同名的文件。
|
||||
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, true, name)
|
||||
|
||||
if count > 0 {
|
||||
return this.Error("【" + name + "】已经存在了,请使用其他名称。")
|
||||
}
|
||||
|
||||
matter := &Matter{
|
||||
Puuid: puuid,
|
||||
UserUuid: user.Uuid,
|
||||
Dir: true,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
matter = this.matterDao.Create(matter)
|
||||
|
||||
return this.Success(matter)
|
||||
}
|
||||
|
||||
//按照分页的方式获取某个文件夹下文件和子文件夹的列表,通常情况下只有一页。
|
||||
func (this *MatterController) Page(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
puuid := request.FormValue("puuid")
|
||||
pageStr := request.FormValue("page")
|
||||
pageSizeStr := request.FormValue("pageSize")
|
||||
userUuid := request.FormValue("userUuid")
|
||||
name := request.FormValue("name")
|
||||
dir := request.FormValue("dir")
|
||||
orderDir := request.FormValue("orderDir")
|
||||
orderCreateTime := request.FormValue("orderCreateTime")
|
||||
orderSize := request.FormValue("orderSize")
|
||||
orderName := request.FormValue("orderName")
|
||||
extensionsStr := request.FormValue("extensions")
|
||||
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
userUuid = user.Uuid
|
||||
}
|
||||
|
||||
var page int
|
||||
if pageStr != "" {
|
||||
page, _ = strconv.Atoi(pageStr)
|
||||
}
|
||||
|
||||
pageSize := 200
|
||||
if pageSizeStr != "" {
|
||||
tmp, err := strconv.Atoi(pageSizeStr)
|
||||
if err == nil {
|
||||
pageSize = tmp
|
||||
}
|
||||
}
|
||||
|
||||
//筛选后缀名
|
||||
var extensions []string
|
||||
if extensionsStr != "" {
|
||||
extensions = strings.Split(extensionsStr, ",")
|
||||
}
|
||||
|
||||
//文件列表默认文件夹始终在文件的前面。
|
||||
if orderDir == "" {
|
||||
orderDir = "DESC"
|
||||
}
|
||||
|
||||
sortArray := []OrderPair{
|
||||
{
|
||||
key: "dir",
|
||||
value: orderDir,
|
||||
},
|
||||
{
|
||||
key: "create_time",
|
||||
value: orderCreateTime,
|
||||
},
|
||||
{
|
||||
key: "size",
|
||||
value: orderSize,
|
||||
},
|
||||
{
|
||||
key: "name",
|
||||
value: orderName,
|
||||
},
|
||||
}
|
||||
|
||||
pager := this.matterDao.Page(page, pageSize, puuid, userUuid, name, dir, extensions, sortArray)
|
||||
|
||||
return this.Success(pager)
|
||||
}
|
||||
|
||||
//上传文件
|
||||
func (this *MatterController) Upload(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
userUuid := request.FormValue("userUuid")
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
userUuid = user.Uuid
|
||||
}
|
||||
user = this.userDao.CheckByUuid(userUuid)
|
||||
|
||||
puuid := request.FormValue("puuid")
|
||||
if puuid == "" {
|
||||
return this.Error("puuid必填")
|
||||
} else {
|
||||
if puuid != "root" {
|
||||
//找出上一级的文件夹。
|
||||
this.matterDao.FindByUuidAndUserUuid(puuid, userUuid)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
request.ParseMultipartForm(32 << 20)
|
||||
file, handler, err := request.FormFile("file")
|
||||
this.PanicError(err)
|
||||
defer file.Close()
|
||||
|
||||
matter := this.matterService.Upload(file, user, puuid, handler.Filename, true)
|
||||
|
||||
return this.Success(matter)
|
||||
}
|
||||
|
||||
//删除一个文件
|
||||
func (this *MatterController) Delete(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
if uuid == "" {
|
||||
return this.Error("文件的uuid必填")
|
||||
}
|
||||
|
||||
matter := this.matterDao.FindByUuid(uuid)
|
||||
|
||||
//判断文件的所属人是否正确
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && matter.UserUuid != user.Uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
this.matterDao.Delete(matter)
|
||||
|
||||
return this.Success("删除成功!")
|
||||
}
|
||||
|
||||
//删除一系列文件。
|
||||
func (this *MatterController) DeleteBatch(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuids := request.FormValue("uuids")
|
||||
if uuids == "" {
|
||||
return this.Error("文件的uuids必填")
|
||||
}
|
||||
|
||||
uuidArray := strings.Split(uuids, ",")
|
||||
|
||||
for _, uuid := range uuidArray {
|
||||
|
||||
matter := this.matterDao.FindByUuid(uuid)
|
||||
|
||||
//判断文件的所属人是否正确
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && matter.UserUuid != user.Uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
this.matterDao.Delete(matter)
|
||||
|
||||
}
|
||||
|
||||
return this.Success("删除成功!")
|
||||
}
|
||||
|
||||
//重命名一个文件或一个文件夹
|
||||
func (this *MatterController) Rename(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
name := request.FormValue("name")
|
||||
|
||||
//验证参数。
|
||||
if name == "" {
|
||||
return this.Error("name参数必填")
|
||||
}
|
||||
if m, _ := regexp.MatchString(`[<>|*?/\\]`, name); m {
|
||||
return this.Error(`名称中不能包含以下特殊符号:< > | * ? / \`)
|
||||
}
|
||||
|
||||
//找出该文件或者文件夹
|
||||
matter := this.matterDao.FindByUuid(uuid)
|
||||
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && matter.UserUuid != user.Uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
if name == matter.Name {
|
||||
return this.Error("新名称和旧名称一样,操作失败!")
|
||||
}
|
||||
|
||||
//判断同级文件夹中是否有同名的文件
|
||||
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, matter.Puuid, matter.Dir, name)
|
||||
|
||||
if count > 0 {
|
||||
return this.Error("【" + name + "】已经存在了,请使用其他名称。")
|
||||
}
|
||||
|
||||
matter.Name = name
|
||||
matter = this.matterDao.Save(matter)
|
||||
|
||||
return this.Success(matter)
|
||||
}
|
||||
|
||||
//将一个文件夹或者文件移入到另一个文件夹下。
|
||||
func (this *MatterController) Move(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
srcUuidsStr := request.FormValue("srcUuids")
|
||||
destUuid := request.FormValue("destUuid")
|
||||
|
||||
var srcUuids []string
|
||||
//验证参数。
|
||||
if srcUuidsStr == "" {
|
||||
return this.Error("srcUuids参数必填")
|
||||
} else {
|
||||
srcUuids = strings.Split(srcUuidsStr, ",")
|
||||
}
|
||||
|
||||
userUuid := request.FormValue("userUuid")
|
||||
user := this.checkUser(writer, request)
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR {
|
||||
userUuid = user.Uuid
|
||||
}
|
||||
if userUuid == "" {
|
||||
userUuid = user.Uuid
|
||||
}
|
||||
|
||||
user = this.userDao.CheckByUuid(userUuid)
|
||||
|
||||
//验证dest是否有问题
|
||||
if destUuid == "" {
|
||||
return this.Error("destUuid参数必填")
|
||||
} else {
|
||||
if destUuid != "root" {
|
||||
destMatter := this.matterDao.FindByUuid(destUuid)
|
||||
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && destMatter.UserUuid != user.Uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var srcMatters []*Matter
|
||||
//验证src是否有问题。
|
||||
for _, uuid := range srcUuids {
|
||||
//找出该文件或者文件夹
|
||||
srcMatter := this.matterDao.FindByUuid(uuid)
|
||||
|
||||
if user.Role != USER_ROLE_ADMINISTRATOR && srcMatter.UserUuid != user.Uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
if srcMatter.Puuid == destUuid {
|
||||
return this.Error("没有进行移动,操作无效!")
|
||||
}
|
||||
|
||||
//判断同级文件夹中是否有同名的文件
|
||||
count := this.matterDao.CountByUserUuidAndPuuidAndDirAndName(user.Uuid, destUuid, srcMatter.Dir, srcMatter.Name)
|
||||
|
||||
if count > 0 {
|
||||
return this.Error("【" + srcMatter.Name + "】在目标文件夹已经存在了,操作失败。")
|
||||
}
|
||||
|
||||
srcMatters = append(srcMatters, srcMatter)
|
||||
}
|
||||
|
||||
for _, srcMatter := range srcMatters {
|
||||
srcMatter.Puuid = destUuid
|
||||
srcMatter = this.matterDao.Save(srcMatter)
|
||||
}
|
||||
|
||||
return this.Success(nil)
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/jinzhu/gorm"
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"os"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type MatterDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//按照Id查询文件
|
||||
func (this *MatterDao) FindByUuid(uuid string) *Matter {
|
||||
|
||||
// Read
|
||||
var matter Matter
|
||||
db := this.context.DB.Where(&Matter{Base: Base{Uuid: uuid}}).First(&matter)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &matter
|
||||
|
||||
}
|
||||
|
||||
//按照Id查询文件
|
||||
func (this *MatterDao) CheckByUuid(uuid string) *Matter {
|
||||
|
||||
// Read
|
||||
var matter Matter
|
||||
db := this.context.DB.Where(&Matter{Base: Base{Uuid: uuid}}).First(&matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return &matter
|
||||
|
||||
}
|
||||
|
||||
//按照名字查询文件夹
|
||||
func (this *MatterDao) FindByUserUuidAndPuuidAndNameAndDirTrue(userUuid string, puuid string, name string) *Matter {
|
||||
|
||||
var wp = &WherePair{}
|
||||
|
||||
if userUuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
|
||||
}
|
||||
|
||||
if puuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "puuid = ?", Args: []interface{}{puuid}})
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
wp = wp.And(&WherePair{Query: "name = ?", Args: []interface{}{name}})
|
||||
}
|
||||
|
||||
wp = wp.And(&WherePair{Query: "dir = ?", Args: []interface{}{1}})
|
||||
|
||||
var matter = &Matter{}
|
||||
db := this.context.DB.Model(&Matter{}).Where(wp.Query, wp.Args...).First(matter)
|
||||
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
//按照id和userUuid来查找。
|
||||
func (this *MatterDao) FindByUuidAndUserUuid(uuid string, userUuid string) *Matter {
|
||||
|
||||
// Read
|
||||
var matter = &Matter{}
|
||||
db := this.context.DB.Where(&Matter{Base: Base{Uuid: uuid}, UserUuid: userUuid}).First(matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return matter
|
||||
|
||||
}
|
||||
|
||||
//统计某个用户的某个文件夹下的某个名字的文件(或文件夹)数量。
|
||||
func (this *MatterDao) CountByUserUuidAndPuuidAndDirAndName(userUuid string, puuid string, dir bool, name string) int {
|
||||
|
||||
var matter Matter
|
||||
var count int
|
||||
|
||||
var wp = &WherePair{}
|
||||
|
||||
if puuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "puuid = ?", Args: []interface{}{puuid}})
|
||||
}
|
||||
|
||||
if userUuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
wp = wp.And(&WherePair{Query: "name = ?", Args: []interface{}{name}})
|
||||
}
|
||||
|
||||
wp = wp.And(&WherePair{Query: "dir = ?", Args: []interface{}{dir}})
|
||||
|
||||
db := this.context.DB.
|
||||
Model(&matter).
|
||||
Where(wp.Query, wp.Args...).
|
||||
Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
//获取某个用户的某个文件夹下的某个名字的文件(或文件夹)列表
|
||||
func (this *MatterDao) ListByUserUuidAndPuuidAndDirAndName(userUuid string, puuid string, dir bool, name string) []*Matter {
|
||||
|
||||
var matters []*Matter
|
||||
|
||||
db := this.context.DB.
|
||||
Where(Matter{UserUuid: userUuid, Puuid: puuid, Dir: dir, Name: name}).
|
||||
Find(&matters)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return matters
|
||||
}
|
||||
|
||||
//获取某个文件夹下所有的文件和子文件
|
||||
func (this *MatterDao) List(puuid string, userUuid string, sortArray []OrderPair) []*Matter {
|
||||
var matters []*Matter
|
||||
|
||||
db := this.context.DB.Where(Matter{UserUuid: userUuid, Puuid: puuid}).Order(this.GetSortString(sortArray)).Find(&matters)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return matters
|
||||
}
|
||||
|
||||
//获取某个文件夹下所有的文件和子文件
|
||||
func (this *MatterDao) Page(page int, pageSize int, puuid string, userUuid string, name string, dir string, extensions []string, sortArray []OrderPair) *Pager {
|
||||
|
||||
var wp = &WherePair{}
|
||||
|
||||
if puuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "puuid = ?", Args: []interface{}{puuid}})
|
||||
}
|
||||
|
||||
if userUuid != "" {
|
||||
wp = wp.And(&WherePair{Query: "user_uuid = ?", Args: []interface{}{userUuid}})
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
wp = wp.And(&WherePair{Query: "name LIKE ?", Args: []interface{}{"%" + name + "%"}})
|
||||
}
|
||||
|
||||
if dir == "true" {
|
||||
wp = wp.And(&WherePair{Query: "dir = ?", Args: []interface{}{1}})
|
||||
} else if dir == "false" {
|
||||
wp = wp.And(&WherePair{Query: "dir = ?", Args: []interface{}{0}})
|
||||
}
|
||||
|
||||
var conditionDB *gorm.DB
|
||||
if extensions != nil && len(extensions) > 0 {
|
||||
var orWp = &WherePair{}
|
||||
|
||||
for _, v := range extensions {
|
||||
orWp = orWp.Or(&WherePair{Query: "name LIKE ?", Args: []interface{}{"%." + v}})
|
||||
}
|
||||
|
||||
conditionDB = this.context.DB.Model(&Matter{}).Where(wp.Query, wp.Args...).Where(orWp.Query, orWp.Args...)
|
||||
} else {
|
||||
conditionDB = this.context.DB.Model(&Matter{}).Where(wp.Query, wp.Args...)
|
||||
}
|
||||
|
||||
count := 0
|
||||
db := conditionDB.Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
var matters []*Matter
|
||||
db = conditionDB.Order(this.GetSortString(sortArray)).Offset(page * pageSize).Limit(pageSize).Find(&matters)
|
||||
this.PanicError(db.Error)
|
||||
pager := NewPager(page, pageSize, count, matters)
|
||||
|
||||
return pager
|
||||
}
|
||||
|
||||
//创建
|
||||
func (this *MatterDao) Create(matter *Matter) *Matter {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
matter.Uuid = string(timeUUID.String())
|
||||
matter.CreateTime = time.Now()
|
||||
matter.ModifyTime = time.Now()
|
||||
db := this.context.DB.Create(matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
//修改一个文件
|
||||
func (this *MatterDao) Save(matter *Matter) *Matter {
|
||||
|
||||
matter.ModifyTime = time.Now()
|
||||
db := this.context.DB.Save(matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return matter
|
||||
}
|
||||
|
||||
//删除一个文件,数据库中删除,物理磁盘上删除。
|
||||
func (this *MatterDao) Delete(matter *Matter) {
|
||||
|
||||
//目录的话递归删除。
|
||||
if matter.Dir {
|
||||
matters := this.List(matter.Uuid, matter.UserUuid, nil)
|
||||
|
||||
for _, f := range matters {
|
||||
this.Delete(f)
|
||||
|
||||
}
|
||||
|
||||
//删除文件夹本身
|
||||
db := this.context.DB.Delete(&matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
} else {
|
||||
db := this.context.DB.Delete(&matter)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
//删除文件
|
||||
err := os.Remove(GetFilePath() + matter.Path)
|
||||
|
||||
LogError(fmt.Sprintf("删除磁盘上的文件出错,不做任何处理"))
|
||||
|
||||
this.PanicError(err)
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package rest
|
||||
|
||||
type Matter struct {
|
||||
Base
|
||||
Puuid string `json:"puuid"`
|
||||
UserUuid string `json:"userUuid"`
|
||||
Dir bool `json:"dir"`
|
||||
Name string `json:"name"`
|
||||
Md5 string `json:"md5"`
|
||||
Size int64 `json:"size"`
|
||||
Privacy bool `json:"privacy"`
|
||||
Path string `json:"path"`
|
||||
Parent *Matter `gorm:"-" json:"parent"`
|
||||
}
|
||||
|
||||
// set File's table name to be `profiles`
|
||||
func (Matter) TableName() string {
|
||||
return TABLE_PREFIX + "matter"
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
)
|
||||
|
||||
//@Service
|
||||
type MatterService struct {
|
||||
Bean
|
||||
matterDao *MatterDao
|
||||
}
|
||||
|
||||
//初始化方法
|
||||
func (this *MatterService) Init(context *Context) {
|
||||
|
||||
//手动装填本实例的Bean. 这里必须要用中间变量方可。
|
||||
|
||||
b := context.GetBean(this.matterDao)
|
||||
if b, ok := b.(*MatterDao); ok {
|
||||
this.matterDao = b
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//根据一个文件夹路径,找到最后一个文件夹的uuid,如果中途出错,返回err.
|
||||
func (this *MatterService) GetDirUuid(userUuid string, dir string) string {
|
||||
|
||||
if dir == "" {
|
||||
panic(`文件夹不能为空`)
|
||||
} else if dir[0:1] != "/" {
|
||||
panic(`文件夹必须以/开头`)
|
||||
} else if strings.Index(dir, "//") != -1 {
|
||||
panic(`文件夹不能出现连续的//`)
|
||||
} else if m, _ := regexp.MatchString(`[<>|*?\\]`, dir); m {
|
||||
panic(`文件夹中不能包含以下特殊符号:< > | * ? \`)
|
||||
}
|
||||
|
||||
if dir == "/" {
|
||||
return "root"
|
||||
}
|
||||
|
||||
if dir[len(dir)-1] == '/' {
|
||||
dir = dir[:len(dir)-1]
|
||||
}
|
||||
|
||||
//递归找寻文件的上级目录uuid.
|
||||
folders := strings.Split(dir, "/")
|
||||
|
||||
puuid := "root"
|
||||
for k, name := range folders {
|
||||
if k == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
matter := this.matterDao.FindByUserUuidAndPuuidAndNameAndDirTrue(userUuid, puuid, name)
|
||||
if matter == nil {
|
||||
//创建一个文件夹。
|
||||
matter = &Matter{
|
||||
Puuid: puuid,
|
||||
UserUuid: userUuid,
|
||||
Dir: true,
|
||||
Name: name,
|
||||
}
|
||||
matter = this.matterDao.Create(matter)
|
||||
}
|
||||
|
||||
puuid = matter.Uuid
|
||||
}
|
||||
|
||||
return puuid
|
||||
}
|
||||
|
||||
//开始上传文件
|
||||
//上传文件
|
||||
func (this *MatterService) Upload(file multipart.File, user *User, puuid string, filename string, privacy bool) *Matter {
|
||||
|
||||
//获取文件应该存放在的物理路径的绝对路径和相对路径。
|
||||
absolutePath, relativePath := GetUserFilePath(user.Username)
|
||||
absolutePath = absolutePath + "/" + filename
|
||||
relativePath = relativePath + "/" + filename
|
||||
|
||||
distFile, err := os.OpenFile(absolutePath, os.O_WRONLY|os.O_CREATE, 0777)
|
||||
this.PanicError(err)
|
||||
|
||||
defer distFile.Close()
|
||||
|
||||
written, err := io.Copy(distFile, file)
|
||||
this.PanicError(err)
|
||||
|
||||
//查找文件夹下面是否有同名文件。
|
||||
matters := this.matterDao.ListByUserUuidAndPuuidAndDirAndName(user.Uuid, puuid, false, filename)
|
||||
//如果有同名的文件,那么我们直接覆盖同名文件。
|
||||
for _, dbFile := range matters {
|
||||
this.matterDao.Delete(dbFile)
|
||||
}
|
||||
|
||||
//将文件信息存入数据库中。
|
||||
matter := &Matter{
|
||||
Puuid: puuid,
|
||||
UserUuid: user.Uuid,
|
||||
Dir: false,
|
||||
Name: filename,
|
||||
Md5: "",
|
||||
Size: written,
|
||||
Privacy: privacy,
|
||||
Path: relativePath,
|
||||
}
|
||||
|
||||
matter = this.matterDao.Create(matter)
|
||||
|
||||
return matter
|
||||
}
|
||||
+138
@@ -0,0 +1,138 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/json-iterator/go"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
)
|
||||
|
||||
//用于处理所有前来的请求
|
||||
type Router struct {
|
||||
context *Context
|
||||
routeMap map[string]func(writer http.ResponseWriter, request *http.Request)
|
||||
}
|
||||
|
||||
//构造方法
|
||||
func NewRouter(context *Context) *Router {
|
||||
router := &Router{
|
||||
context: context,
|
||||
routeMap: make(map[string]func(writer http.ResponseWriter, request *http.Request)),
|
||||
}
|
||||
|
||||
for _, controller := range context.ControllerMap {
|
||||
routes := controller.RegisterRoutes()
|
||||
for k, v := range routes {
|
||||
router.routeMap[k] = v
|
||||
}
|
||||
}
|
||||
return router
|
||||
|
||||
}
|
||||
|
||||
//全局的异常捕获
|
||||
func (this *Router) GlobalPanicHandler(writer http.ResponseWriter, request *http.Request) {
|
||||
if err := recover(); err != nil {
|
||||
|
||||
LogError(fmt.Sprintf("全局异常: %v", err))
|
||||
|
||||
var webResult *WebResult = nil
|
||||
if value, ok := err.(string); ok {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: value}
|
||||
} else if value, ok := err.(int); ok {
|
||||
webResult = ConstWebResult(value)
|
||||
} else if value, ok := err.(*WebResult); ok {
|
||||
webResult = value
|
||||
} else if value, ok := err.(WebResult); ok {
|
||||
webResult = &value
|
||||
} else if value, ok := err.(error); ok {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: value.Error()}
|
||||
} else {
|
||||
webResult = &WebResult{Code: RESULT_CODE_UTIL_EXCEPTION, Msg: "服务器未知错误"}
|
||||
}
|
||||
|
||||
//输出的是json格式 返回的内容申明是json,utf-8
|
||||
writer.Header().Set("Content-Type", "application/json;charset=UTF-8")
|
||||
|
||||
//用json的方式输出返回值。
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
b, _ := json.Marshal(webResult)
|
||||
|
||||
if webResult.Code == RESULT_CODE_OK {
|
||||
writer.WriteHeader(http.StatusOK)
|
||||
} else {
|
||||
writer.WriteHeader(http.StatusBadRequest)
|
||||
}
|
||||
fmt.Fprintf(writer, string(b))
|
||||
}
|
||||
}
|
||||
|
||||
//让Router具有处理请求的功能。
|
||||
func (this *Router) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
//每个请求的入口在这里
|
||||
//全局异常处理。
|
||||
defer this.GlobalPanicHandler(writer, request)
|
||||
|
||||
path := request.URL.Path
|
||||
if strings.HasPrefix(path, "/api") {
|
||||
|
||||
if handler, ok := this.routeMap[path]; ok {
|
||||
|
||||
handler(writer, request)
|
||||
|
||||
} else {
|
||||
//直接将请求扔给每个controller,看看他们能不能处理,如果都不能处理,那就算了。
|
||||
canHandle := false
|
||||
for _, controller := range this.context.ControllerMap {
|
||||
if handler, exist := controller.HandleRoutes(writer, request); exist {
|
||||
canHandle = true
|
||||
|
||||
handler(writer, request)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !canHandle {
|
||||
panic(fmt.Sprintf("没有找到能够处理%s的方法\n", path))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
//当作静态资源处理。默认从当前文件下面的static文件夹中取东西。
|
||||
dir := GetHtmlPath()
|
||||
|
||||
requestURI := request.RequestURI
|
||||
if requestURI == "" || request.RequestURI == "/" {
|
||||
requestURI = "index.html"
|
||||
}
|
||||
|
||||
filePath := dir + requestURI
|
||||
exists, _ := PathExists(filePath)
|
||||
if !exists {
|
||||
filePath = dir + "/index.html"
|
||||
exists, _ = PathExists(filePath)
|
||||
if !exists {
|
||||
panic("404 not found")
|
||||
}
|
||||
}
|
||||
|
||||
writer.Header().Set("Content-Type", GetMimeType(GetExtension(filePath)))
|
||||
|
||||
diskFile, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
panic("cannot get file.")
|
||||
}
|
||||
defer diskFile.Close()
|
||||
_, err = io.Copy(writer, diskFile)
|
||||
if err != nil {
|
||||
panic("cannot get file.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SessionDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//构造函数
|
||||
func NewSessionDao(context *Context) *SessionDao {
|
||||
|
||||
var sessionDao = &SessionDao{}
|
||||
sessionDao.Init(context)
|
||||
return sessionDao
|
||||
}
|
||||
|
||||
//按照Id查询session.
|
||||
func (this *SessionDao) FindByUuid(uuid string) *Session {
|
||||
|
||||
// Read
|
||||
var session = &Session{}
|
||||
db := this.context.DB.Where(&Session{Base: Base{Uuid: uuid}}).First(session)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return session
|
||||
}
|
||||
|
||||
//按照Id查询session.
|
||||
func (this *SessionDao) CheckByUuid(uuid string) *Session {
|
||||
|
||||
// Read
|
||||
var session = &Session{}
|
||||
db := this.context.DB.Where(&Session{Base: Base{Uuid: uuid}}).First(session)
|
||||
this.PanicError(db.Error)
|
||||
return session
|
||||
}
|
||||
|
||||
//按照authentication查询用户。
|
||||
func (this *SessionDao) FindByAuthentication(authentication string) *Session {
|
||||
|
||||
var session = &Session{}
|
||||
db := this.context.DB.Where(&Session{Authentication: authentication}).First(session)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return session
|
||||
|
||||
}
|
||||
|
||||
//创建一个session并且持久化到数据库中。
|
||||
func (this *SessionDao) Create(session *Session) *Session {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
session.Uuid = string(timeUUID.String())
|
||||
db := this.context.DB.Create(session)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return session
|
||||
}
|
||||
|
||||
func (this *SessionDao) Delete(uuid string) {
|
||||
|
||||
session := this.CheckByUuid(uuid)
|
||||
|
||||
session.ExpireTime = time.Now()
|
||||
db := this.context.DB.Delete(session)
|
||||
|
||||
this.PanicError(db.Error)
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type Session struct {
|
||||
Base
|
||||
Authentication string `json:"authentication"`
|
||||
UserUuid string `json:"userUuid"`
|
||||
Ip string `json:"ip"`
|
||||
ExpireTime time.Time `json:"expireTime"`
|
||||
}
|
||||
|
||||
// set User's table name to be `profiles`
|
||||
func (Session) TableName() string {
|
||||
return TABLE_PREFIX + "session"
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package rest
|
||||
|
||||
type OrderPair struct {
|
||||
key string
|
||||
value string
|
||||
}
|
||||
|
||||
type WherePair struct {
|
||||
Query string
|
||||
Args []interface{}
|
||||
}
|
||||
|
||||
func (this *WherePair) And(where *WherePair) *WherePair {
|
||||
if this.Query == "" {
|
||||
return where
|
||||
} else {
|
||||
return &WherePair{Query: this.Query + " AND " + where.Query, Args: append(this.Args, where.Args...)}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (this *WherePair) Or(where *WherePair) *WherePair {
|
||||
if this.Query == "" {
|
||||
return where
|
||||
} else {
|
||||
return &WherePair{Query: this.Query + " OR " + where.Query, Args: append(this.Args, where.Args...)}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//根据一个sortMap,获取到order字符串
|
||||
func (this *BaseDao) GetSortString(sortArray []OrderPair) string {
|
||||
|
||||
if sortArray == nil || len(sortArray) == 0 {
|
||||
return ""
|
||||
}
|
||||
str := ""
|
||||
for _, pair := range sortArray {
|
||||
if pair.value == "DESC" || pair.value == "ASC" {
|
||||
if str != "" {
|
||||
str = str + ","
|
||||
}
|
||||
str = str + " " + pair.key + " " + pair.value
|
||||
}
|
||||
}
|
||||
|
||||
return str
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UploadTokenDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//按照Id查询
|
||||
func (this *UploadTokenDao) FindByUuid(uuid string) *UploadToken {
|
||||
|
||||
// Read
|
||||
var uploadToken = &UploadToken{}
|
||||
db := this.context.DB.Where(&UploadToken{Base: Base{Uuid: uuid}}).First(uploadToken)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return uploadToken
|
||||
|
||||
}
|
||||
|
||||
//创建一个session并且持久化到数据库中。
|
||||
func (this *UploadTokenDao) Create(uploadToken *UploadToken) *UploadToken {
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
uploadToken.Uuid = string(timeUUID.String())
|
||||
|
||||
uploadToken.CreateTime = time.Now()
|
||||
uploadToken.ModifyTime = time.Now()
|
||||
|
||||
db := this.context.DB.Create(uploadToken)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return uploadToken
|
||||
}
|
||||
|
||||
//修改一个uploadToken
|
||||
func (this *UploadTokenDao) Save(uploadToken *UploadToken) *UploadToken {
|
||||
|
||||
uploadToken.ModifyTime = time.Now()
|
||||
db := this.context.DB.Save(uploadToken)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return uploadToken
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type UploadToken struct {
|
||||
Base
|
||||
UserUuid string `json:"userUuid"`
|
||||
FolderUuid string `json:"folderUuid"`
|
||||
MatterUuid string `json:"matterUuid"`
|
||||
ExpireTime time.Time `json:"expireTime"`
|
||||
Filename string `json:"filename"`
|
||||
Privacy bool `json:"privacy"`
|
||||
Size int64 `json:"size"`
|
||||
Ip string `json:"ip"`
|
||||
}
|
||||
|
||||
func (UploadToken) TableName() string {
|
||||
return TABLE_PREFIX + "upload_token"
|
||||
}
|
||||
@@ -0,0 +1,322 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserController struct {
|
||||
BaseController
|
||||
}
|
||||
|
||||
//初始化方法
|
||||
func (this *UserController) Init(context *Context) {
|
||||
this.BaseController.Init(context)
|
||||
}
|
||||
|
||||
//注册自己的路由。
|
||||
func (this *UserController) RegisterRoutes() map[string]func(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
routeMap := make(map[string]func(writer http.ResponseWriter, request *http.Request))
|
||||
|
||||
//每个Controller需要主动注册自己的路由。
|
||||
routeMap["/api/user/create"] = this.Wrap(this.Create, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/user/edit"] = this.Wrap(this.Edit, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/user/change/password"] = this.Wrap(this.ChangePassword, USER_ROLE_USER)
|
||||
routeMap["/api/user/reset/password"] = this.Wrap(this.ResetPassword, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/user/login"] = this.Wrap(this.Login, USER_ROLE_GUEST)
|
||||
routeMap["/api/user/logout"] = this.Wrap(this.Logout, USER_ROLE_USER)
|
||||
routeMap["/api/user/detail"] = this.Wrap(this.Detail, USER_ROLE_USER)
|
||||
routeMap["/api/user/page"] = this.Wrap(this.Page, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/user/disable"] = this.Wrap(this.Disable, USER_ROLE_ADMINISTRATOR)
|
||||
routeMap["/api/user/enable"] = this.Wrap(this.Enable, USER_ROLE_ADMINISTRATOR)
|
||||
|
||||
return routeMap
|
||||
}
|
||||
|
||||
//使用用户名和密码进行登录。
|
||||
//参数:
|
||||
// @email:邮箱
|
||||
// @password:密码
|
||||
func (this *UserController) Login(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
email := request.FormValue("email")
|
||||
password := request.FormValue("password")
|
||||
|
||||
if "" == email || "" == password {
|
||||
|
||||
return this.Error("请输入邮箱和密码")
|
||||
}
|
||||
|
||||
user := this.userDao.FindByEmail(email)
|
||||
if user == nil {
|
||||
|
||||
return this.Error("邮箱或密码错误")
|
||||
} else {
|
||||
if !MatchBcrypt(password, user.Password) {
|
||||
|
||||
return this.Error("邮箱或密码错误")
|
||||
}
|
||||
}
|
||||
|
||||
//登录成功,设置Cookie。有效期7天。
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(0, 0, 7)
|
||||
|
||||
//持久化用户的session.
|
||||
|
||||
session := &Session{
|
||||
UserUuid: user.Uuid,
|
||||
Ip: GetIpAddress(request),
|
||||
ExpireTime: expiration,
|
||||
}
|
||||
session.ModifyTime = time.Now()
|
||||
session.CreateTime = time.Now()
|
||||
session = this.sessionDao.Create(session)
|
||||
|
||||
//设置用户的cookie.
|
||||
cookie := http.Cookie{
|
||||
Name: COOKIE_AUTH_KEY,
|
||||
Path: "/",
|
||||
Value: session.Uuid,
|
||||
Expires: expiration}
|
||||
http.SetCookie(writer, &cookie)
|
||||
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//创建一个用户
|
||||
func (this *UserController) Create(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
username := request.FormValue("username")
|
||||
if m, _ := regexp.MatchString(`^[0-9a-zA-Z_]+$`, username); !m {
|
||||
return this.Error(`用户名必填,且只能包含字母,数字和'_''`)
|
||||
}
|
||||
password := request.FormValue("password")
|
||||
if len(password) < 6 {
|
||||
return this.Error(`密码长度至少为6位`)
|
||||
}
|
||||
|
||||
email := request.FormValue("email")
|
||||
if email == "" {
|
||||
return this.Error("邮箱必填!")
|
||||
}
|
||||
|
||||
phone := request.FormValue("phone")
|
||||
gender := request.FormValue("gender")
|
||||
role := request.FormValue("role")
|
||||
city := request.FormValue("city")
|
||||
|
||||
//判断重名。
|
||||
if this.userDao.CountByUsername(username) > 0 {
|
||||
return this.Error(username + "已经被其他用户占用。")
|
||||
}
|
||||
//判断邮箱重名
|
||||
if this.userDao.CountByEmail(email) > 0 {
|
||||
return this.Error(email + "已经被其他用户占用。")
|
||||
}
|
||||
|
||||
user := &User{
|
||||
Role: GetRole(role),
|
||||
Username: username,
|
||||
Password: GetBcrypt(password),
|
||||
Email: email,
|
||||
Phone: phone,
|
||||
Gender: gender,
|
||||
City: city,
|
||||
Status: USER_STATUS_OK,
|
||||
}
|
||||
|
||||
user = this.userDao.Create(user)
|
||||
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//编辑一个用户的资料。
|
||||
func (this *UserController) Edit(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
phone := request.FormValue("phone")
|
||||
gender := request.FormValue("gender")
|
||||
city := request.FormValue("city")
|
||||
|
||||
currentUser := this.checkUser(writer, request)
|
||||
if currentUser.Role != USER_ROLE_ADMINISTRATOR {
|
||||
if currentUser.Uuid != uuid {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
}
|
||||
|
||||
user := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
user.Phone = phone
|
||||
user.Gender = GetGender(gender)
|
||||
user.City = city
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//获取用户详情
|
||||
func (this *UserController) Detail(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
|
||||
user := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
return this.Success(user)
|
||||
|
||||
}
|
||||
|
||||
//退出登录
|
||||
func (this *UserController) Logout(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
session, _ := this.checkLogin(writer, request)
|
||||
|
||||
//删除session
|
||||
this.sessionDao.Delete(session.Uuid)
|
||||
|
||||
//清空客户端的cookie.
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(-1, 0, 0)
|
||||
cookie := http.Cookie{
|
||||
Name: COOKIE_AUTH_KEY,
|
||||
Path: "/",
|
||||
Value: session.Uuid,
|
||||
Expires: expiration}
|
||||
http.SetCookie(writer, &cookie)
|
||||
|
||||
return this.Success("退出成功!")
|
||||
}
|
||||
|
||||
//获取用户列表 管理员的权限。
|
||||
func (this *UserController) Page(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
//如果是根目录,那么就传入root.
|
||||
pageStr := request.FormValue("page")
|
||||
pageSizeStr := request.FormValue("pageSize")
|
||||
username := request.FormValue("username")
|
||||
email := request.FormValue("email")
|
||||
phone := request.FormValue("phone")
|
||||
orderLastTime := request.FormValue("orderLastTime")
|
||||
orderCreateTime := request.FormValue("orderCreateTime")
|
||||
|
||||
var page int
|
||||
if pageStr != "" {
|
||||
page, _ = strconv.Atoi(pageStr)
|
||||
}
|
||||
|
||||
pageSize := 200
|
||||
if pageSizeStr != "" {
|
||||
tmp, err := strconv.Atoi(pageSizeStr)
|
||||
if err == nil {
|
||||
pageSize = tmp
|
||||
}
|
||||
}
|
||||
|
||||
sortArray := []OrderPair{
|
||||
{
|
||||
key: "last_time",
|
||||
value: orderLastTime,
|
||||
},
|
||||
{
|
||||
key: "create_time",
|
||||
value: orderCreateTime,
|
||||
},
|
||||
}
|
||||
|
||||
pager := this.userDao.Page(page, pageSize, username, email, phone, sortArray)
|
||||
|
||||
return this.Success(pager)
|
||||
}
|
||||
|
||||
//禁用用户
|
||||
func (this *UserController) Disable(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
|
||||
user := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
if user.Status == USER_STATUS_DISABLED {
|
||||
return this.Error("用户已经被禁用,操作无效。")
|
||||
}
|
||||
|
||||
user.Status = USER_STATUS_DISABLED
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
|
||||
return this.Success(user)
|
||||
|
||||
}
|
||||
|
||||
//启用用户
|
||||
func (this *UserController) Enable(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
uuid := request.FormValue("uuid")
|
||||
|
||||
user := this.userDao.CheckByUuid(uuid)
|
||||
|
||||
if user.Status == USER_STATUS_OK {
|
||||
return this.Error("用户已经是正常状态,操作无效。")
|
||||
}
|
||||
|
||||
user.Status = USER_STATUS_OK
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
|
||||
return this.Success(user)
|
||||
|
||||
}
|
||||
|
||||
//用户修改密码
|
||||
func (this *UserController) ChangePassword(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
oldPassword := request.FormValue("oldPassword")
|
||||
newPassword := request.FormValue("newPassword")
|
||||
if oldPassword == "" || newPassword == "" {
|
||||
return this.Error("旧密码和新密码都不能为空")
|
||||
}
|
||||
|
||||
user := this.checkUser(writer, request)
|
||||
|
||||
if !MatchBcrypt(oldPassword, user.Password) {
|
||||
return this.Error("旧密码不正确!")
|
||||
}
|
||||
|
||||
user.Password = GetBcrypt(newPassword)
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
|
||||
return this.Success(user)
|
||||
}
|
||||
|
||||
//管理员重置用户密码
|
||||
func (this *UserController) ResetPassword(writer http.ResponseWriter, request *http.Request) *WebResult {
|
||||
|
||||
userUuid := request.FormValue("userUuid")
|
||||
password := request.FormValue("password")
|
||||
if userUuid == "" {
|
||||
return this.Error("用户不能为空")
|
||||
}
|
||||
if password == "" {
|
||||
return this.Error("密码不能为空")
|
||||
}
|
||||
|
||||
currentUser := this.checkUser(writer, request)
|
||||
|
||||
if currentUser.Role != USER_ROLE_ADMINISTRATOR {
|
||||
return this.Error(RESULT_CODE_UNAUTHORIZED)
|
||||
}
|
||||
|
||||
user := this.userDao.CheckByUuid(userUuid)
|
||||
|
||||
user.Password = GetBcrypt(password)
|
||||
|
||||
user = this.userDao.Save(user)
|
||||
|
||||
return this.Success(currentUser)
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"github.com/nu7hatch/gouuid"
|
||||
"time"
|
||||
)
|
||||
|
||||
type UserDao struct {
|
||||
BaseDao
|
||||
}
|
||||
|
||||
//创建用户
|
||||
func (this *UserDao) Create(user *User) *User {
|
||||
|
||||
if user == nil {
|
||||
panic("参数不能为nil")
|
||||
}
|
||||
|
||||
timeUUID, _ := uuid.NewV4()
|
||||
user.Uuid = string(timeUUID.String())
|
||||
user.CreateTime = time.Now()
|
||||
user.ModifyTime = time.Now()
|
||||
user.LastTime = time.Now()
|
||||
user.Sort = time.Now().UnixNano() / 1e6
|
||||
|
||||
db := this.context.DB.Create(user)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
return user
|
||||
}
|
||||
|
||||
//按照Id查询用户,找不到返回nil
|
||||
func (this *UserDao) FindByUuid(uuid string) *User {
|
||||
|
||||
// Read
|
||||
var user *User = &User{}
|
||||
db := this.context.DB.Where(&User{Base: Base{Uuid: uuid}}).First(user)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
//按照Id查询用户,找不到抛panic
|
||||
func (this *UserDao) CheckByUuid(uuid string) *User {
|
||||
|
||||
// Read
|
||||
var user *User = &User{}
|
||||
db := this.context.DB.Where(&User{Base: Base{Uuid: uuid}}).First(user)
|
||||
this.PanicError(db.Error)
|
||||
return user
|
||||
}
|
||||
|
||||
//按照邮箱查询用户。
|
||||
func (this *UserDao) FindByEmail(email string) *User {
|
||||
|
||||
var user *User = &User{}
|
||||
db := this.context.DB.Where(&User{Email: email}).First(user)
|
||||
if db.Error != nil {
|
||||
return nil
|
||||
}
|
||||
return user
|
||||
}
|
||||
|
||||
//显示用户列表。
|
||||
func (this *UserDao) Page(page int, pageSize int, username string, email string, phone string, sortArray []OrderPair) *Pager {
|
||||
|
||||
var wp = &WherePair{}
|
||||
|
||||
if username != "" {
|
||||
wp = wp.And(&WherePair{Query: "username LIKE ?", Args: []interface{}{"%" + username + "%"}})
|
||||
}
|
||||
|
||||
if email != "" {
|
||||
wp = wp.And(&WherePair{Query: "email LIKE ?", Args: []interface{}{"%" + email + "%"}})
|
||||
}
|
||||
|
||||
if phone != "" {
|
||||
wp = wp.And(&WherePair{Query: "phone = ?", Args: []interface{}{phone}})
|
||||
}
|
||||
|
||||
count := 0
|
||||
db := this.context.DB.Model(&User{}).Where(wp.Query, wp.Args...).Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
|
||||
var users []*User
|
||||
orderStr := this.GetSortString(sortArray)
|
||||
if orderStr == "" {
|
||||
db = this.context.DB.Where(wp.Query, wp.Args...).Offset(page * pageSize).Limit(pageSize).Find(&users)
|
||||
} else {
|
||||
db = this.context.DB.Where(wp.Query, wp.Args...).Order(orderStr).Offset(page * pageSize).Limit(pageSize).Find(&users)
|
||||
}
|
||||
|
||||
this.PanicError(db.Error)
|
||||
|
||||
pager := NewPager(page, pageSize, count, users)
|
||||
|
||||
return pager
|
||||
}
|
||||
|
||||
//查询某个用户名是否已经有用户了
|
||||
func (this *UserDao) CountByUsername(username string) int {
|
||||
var count int
|
||||
db := this.context.DB.
|
||||
Model(&User{}).
|
||||
Where("username = ?", username).
|
||||
Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
return count
|
||||
}
|
||||
|
||||
//查询某个邮箱是否已经有用户了
|
||||
func (this *UserDao) CountByEmail(email string) int {
|
||||
var count int
|
||||
db := this.context.DB.
|
||||
Model(&User{}).
|
||||
Where("email = ?", email).
|
||||
Count(&count)
|
||||
this.PanicError(db.Error)
|
||||
return count
|
||||
}
|
||||
|
||||
//保存用户
|
||||
func (this *UserDao) Save(user *User) *User {
|
||||
|
||||
user.ModifyTime = time.Now()
|
||||
db := this.context.DB.
|
||||
Save(user)
|
||||
this.PanicError(db.Error)
|
||||
return user
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
//游客身份
|
||||
USER_ROLE_GUEST = "GUEST"
|
||||
//普通注册用户
|
||||
USER_ROLE_USER = "USER"
|
||||
//管理员
|
||||
USER_ROLE_ADMINISTRATOR = "ADMINISTRATOR"
|
||||
)
|
||||
|
||||
const (
|
||||
USER_GENDER_MALE = "MALE"
|
||||
USER_GENDER_FEMALE = "FEMALE"
|
||||
USER_GENDER_UNKNOWN = "UNKNOWN"
|
||||
)
|
||||
|
||||
const (
|
||||
USER_STATUS_OK = "OK"
|
||||
USER_STATUS_DISABLED = "DISABLED"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Base
|
||||
Role string `json:"role"`
|
||||
Username string `json:"username"`
|
||||
Password string `json:"-"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Gender string `json:"gender"`
|
||||
City string `json:"city"`
|
||||
AvatarUrl string `json:"avatarUrl"`
|
||||
LastIp string `json:"lastIp"`
|
||||
LastTime time.Time `json:"lastTime"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// set User's table name to be `profiles`
|
||||
func (User) TableName() string {
|
||||
return TABLE_PREFIX + "user"
|
||||
}
|
||||
|
||||
//通过一个字符串获取性别
|
||||
func GetGender(genderString string) string {
|
||||
if genderString == USER_GENDER_MALE || genderString == USER_GENDER_FEMALE || genderString == USER_GENDER_UNKNOWN {
|
||||
return genderString
|
||||
} else {
|
||||
return USER_GENDER_UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
//通过一个字符串获取角色
|
||||
func GetRole(roleString string) string {
|
||||
if roleString == USER_ROLE_USER || roleString == USER_ROLE_ADMINISTRATOR {
|
||||
return roleString
|
||||
} else {
|
||||
return USER_ROLE_USER
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
"fmt"
|
||||
"crypto/md5"
|
||||
)
|
||||
|
||||
//给密码字符串加密
|
||||
func GetMd5(raw string) string {
|
||||
return fmt.Sprintf("%x", md5.Sum([]byte(raw)))
|
||||
}
|
||||
|
||||
func GetBcrypt(raw string) string {
|
||||
|
||||
password := []byte(raw)
|
||||
hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return string(hashedPassword)
|
||||
}
|
||||
|
||||
func MatchBcrypt(raw string, bcryptStr string) bool {
|
||||
|
||||
err := bcrypt.CompareHashAndPassword([]byte(bcryptStr), []byte(raw))
|
||||
|
||||
return err == nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Log(prefix string, content string) {
|
||||
|
||||
//日志输出到文件中
|
||||
filePath := GetLogPath() + "/tank-" + time.Now().Local().Format("2006-01-02") + ".log"
|
||||
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
fmt.Errorf("error opening file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
log.SetOutput(f)
|
||||
log.SetPrefix(prefix)
|
||||
log.Println(content)
|
||||
|
||||
//如果需要输出到控制台。
|
||||
if CONFIG.LogToConsole {
|
||||
fmt.Println(content)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func LogDebug(content string) {
|
||||
go Log("[Debug]", content)
|
||||
}
|
||||
|
||||
func LogInfo(content string) {
|
||||
go Log("[Info]", content)
|
||||
}
|
||||
|
||||
func LogWarning(content string) {
|
||||
go Log("[Warning]", content)
|
||||
}
|
||||
|
||||
func LogError(content string) {
|
||||
go Log("[Error]", content)
|
||||
}
|
||||
|
||||
func LogPanic(content interface{}) {
|
||||
Log("[Panic]", fmt.Sprintf("%v", content))
|
||||
panic(content)
|
||||
}
|
||||
@@ -0,0 +1,634 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//根据文件名字获取后缀名,均是小写。
|
||||
func GetExtension(filename string) string {
|
||||
|
||||
var extension = filepath.Ext(filename)
|
||||
|
||||
return strings.ToLower(extension)
|
||||
|
||||
}
|
||||
|
||||
//根据一个后缀名获取MimeType
|
||||
func GetMimeType(filename string) string {
|
||||
|
||||
extension := GetExtension(filename)
|
||||
|
||||
mimeMap := map[string]string{
|
||||
".323": "text/h323",
|
||||
".3g2": "video/3gpp2",
|
||||
".3gp": "video/3gpp",
|
||||
".3gp2": "video/3gpp2",
|
||||
".3gpp": "video/3gpp",
|
||||
".7z": "application/x-7z-compressed",
|
||||
".aa": "audio/audible",
|
||||
".AAC": "audio/aac",
|
||||
".aaf": "application/octet-stream",
|
||||
".aax": "audio/vnd.audible.aax",
|
||||
".ac3": "audio/ac3",
|
||||
".aca": "application/octet-stream",
|
||||
".accda": "application/msaccess.addin",
|
||||
".accdb": "application/msaccess",
|
||||
".accdc": "application/msaccess.cab",
|
||||
".accde": "application/msaccess",
|
||||
".accdr": "application/msaccess.runtime",
|
||||
".accdt": "application/msaccess",
|
||||
".accdw": "application/msaccess.webapplication",
|
||||
".accft": "application/msaccess.ftemplate",
|
||||
".acx": "application/internet-property-stream",
|
||||
".AddIn": "text/xml",
|
||||
".ade": "application/msaccess",
|
||||
".adobebridge": "application/x-bridge-url",
|
||||
".adp": "application/msaccess",
|
||||
".ADT": "audio/vnd.dlna.adts",
|
||||
".ADTS": "audio/aac",
|
||||
".afm": "application/octet-stream",
|
||||
".ai": "application/postscript",
|
||||
".aif": "audio/aiff",
|
||||
".aifc": "audio/aiff",
|
||||
".aiff": "audio/aiff",
|
||||
".air": "application/vnd.adobe.air-application-installer-package+zip",
|
||||
".amc": "application/mpeg",
|
||||
".anx": "application/annodex",
|
||||
".apk": "application/vnd.android.package-archive",
|
||||
".application": "application/x-ms-application",
|
||||
".art": "image/x-jg",
|
||||
".asa": "application/xml",
|
||||
".asax": "application/xml",
|
||||
".ascx": "application/xml",
|
||||
".asd": "application/octet-stream",
|
||||
".asf": "video/x-ms-asf",
|
||||
".ashx": "application/xml",
|
||||
".asi": "application/octet-stream",
|
||||
".asm": "text/plain",
|
||||
".asmx": "application/xml",
|
||||
".aspx": "application/xml",
|
||||
".asr": "video/x-ms-asf",
|
||||
".asx": "video/x-ms-asf",
|
||||
".atom": "application/atom+xml",
|
||||
".au": "audio/basic",
|
||||
".avi": "video/x-msvideo",
|
||||
".axa": "audio/annodex",
|
||||
".axs": "application/olescript",
|
||||
".axv": "video/annodex",
|
||||
".bas": "text/plain",
|
||||
".bcpio": "application/x-bcpio",
|
||||
".bin": "application/octet-stream",
|
||||
".bmp": "image/bmp",
|
||||
".c": "text/plain",
|
||||
".cab": "application/octet-stream",
|
||||
".caf": "audio/x-caf",
|
||||
".calx": "application/vnd.ms-office.calx",
|
||||
".cat": "application/vnd.ms-pki.seccat",
|
||||
".cc": "text/plain",
|
||||
".cd": "text/plain",
|
||||
".cdda": "audio/aiff",
|
||||
".cdf": "application/x-cdf",
|
||||
".cer": "application/x-x509-ca-cert",
|
||||
".cfg": "text/plain",
|
||||
".chm": "application/octet-stream",
|
||||
".class": "application/x-java-applet",
|
||||
".clp": "application/x-msclip",
|
||||
".cmd": "text/plain",
|
||||
".cmx": "image/x-cmx",
|
||||
".cnf": "text/plain",
|
||||
".cod": "image/cis-cod",
|
||||
".config": "application/xml",
|
||||
".contact": "text/x-ms-contact",
|
||||
".coverage": "application/xml",
|
||||
".cpio": "application/x-cpio",
|
||||
".cpp": "text/plain",
|
||||
".crd": "application/x-mscardfile",
|
||||
".crl": "application/pkix-crl",
|
||||
".crt": "application/x-x509-ca-cert",
|
||||
".cs": "text/plain",
|
||||
".csdproj": "text/plain",
|
||||
".csh": "application/x-csh",
|
||||
".csproj": "text/plain",
|
||||
".css": "text/css",
|
||||
".csv": "text/csv",
|
||||
".cur": "application/octet-stream",
|
||||
".cxx": "text/plain",
|
||||
".dat": "application/octet-stream",
|
||||
".datasource": "application/xml",
|
||||
".dbproj": "text/plain",
|
||||
".dcr": "application/x-director",
|
||||
".def": "text/plain",
|
||||
".deploy": "application/octet-stream",
|
||||
".der": "application/x-x509-ca-cert",
|
||||
".dgml": "application/xml",
|
||||
".dib": "image/bmp",
|
||||
".dif": "video/x-dv",
|
||||
".dir": "application/x-director",
|
||||
".disco": "text/xml",
|
||||
".divx": "video/divx",
|
||||
".dll": "application/x-msdownload",
|
||||
".dll.config": "text/xml",
|
||||
".dlm": "text/dlm",
|
||||
".doc": "application/msword",
|
||||
".docm": "application/vnd.ms-word.document.macroEnabled.12",
|
||||
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
||||
".dot": "application/msword",
|
||||
".dotm": "application/vnd.ms-word.template.macroEnabled.12",
|
||||
".dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
|
||||
".dsp": "application/octet-stream",
|
||||
".dsw": "text/plain",
|
||||
".dtd": "text/xml",
|
||||
".dtsConfig": "text/xml",
|
||||
".dv": "video/x-dv",
|
||||
".dvi": "application/x-dvi",
|
||||
".dwf": "drawing/x-dwf",
|
||||
".dwg": "application/acad",
|
||||
".dwp": "application/octet-stream",
|
||||
".dxf": "application/x-dxf",
|
||||
".dxr": "application/x-director",
|
||||
".eml": "message/rfc822",
|
||||
".emz": "application/octet-stream",
|
||||
".eot": "application/vnd.ms-fontobject",
|
||||
".eps": "application/postscript",
|
||||
".etl": "application/etl",
|
||||
".etx": "text/x-setext",
|
||||
".evy": "application/envoy",
|
||||
".exe": "application/octet-stream",
|
||||
".exe.config": "text/xml",
|
||||
".fdf": "application/vnd.fdf",
|
||||
".fif": "application/fractals",
|
||||
".filters": "application/xml",
|
||||
".fla": "application/octet-stream",
|
||||
".flac": "audio/flac",
|
||||
".flr": "x-world/x-vrml",
|
||||
".flv": "video/x-flv",
|
||||
".fsscript": "application/fsharp-script",
|
||||
".fsx": "application/fsharp-script",
|
||||
".generictest": "application/xml",
|
||||
".gif": "image/gif",
|
||||
".gpx": "application/gpx+xml",
|
||||
".group": "text/x-ms-group",
|
||||
".gsm": "audio/x-gsm",
|
||||
".gtar": "application/x-gtar",
|
||||
".gz": "application/x-gzip",
|
||||
".h": "text/plain",
|
||||
".hdf": "application/x-hdf",
|
||||
".hdml": "text/x-hdml",
|
||||
".hhc": "application/x-oleobject",
|
||||
".hhk": "application/octet-stream",
|
||||
".hhp": "application/octet-stream",
|
||||
".hlp": "application/winhlp",
|
||||
".hpp": "text/plain",
|
||||
".hqx": "application/mac-binhex40",
|
||||
".hta": "application/hta",
|
||||
".htc": "text/x-component",
|
||||
".htm": "text/html",
|
||||
".html": "text/html",
|
||||
".htt": "text/webviewhtml",
|
||||
".hxa": "application/xml",
|
||||
".hxc": "application/xml",
|
||||
".hxd": "application/octet-stream",
|
||||
".hxe": "application/xml",
|
||||
".hxf": "application/xml",
|
||||
".hxh": "application/octet-stream",
|
||||
".hxi": "application/octet-stream",
|
||||
".hxk": "application/xml",
|
||||
".hxq": "application/octet-stream",
|
||||
".hxr": "application/octet-stream",
|
||||
".hxs": "application/octet-stream",
|
||||
".hxt": "text/html",
|
||||
".hxv": "application/xml",
|
||||
".hxw": "application/octet-stream",
|
||||
".hxx": "text/plain",
|
||||
".i": "text/plain",
|
||||
".ico": "image/x-icon",
|
||||
".ics": "application/octet-stream",
|
||||
".idl": "text/plain",
|
||||
".ief": "image/ief",
|
||||
".iii": "application/x-iphone",
|
||||
".inc": "text/plain",
|
||||
".inf": "application/octet-stream",
|
||||
".ini": "text/plain",
|
||||
".inl": "text/plain",
|
||||
".ins": "application/x-internet-signup",
|
||||
".ipa": "application/x-itunes-ipa",
|
||||
".ipg": "application/x-itunes-ipg",
|
||||
".ipproj": "text/plain",
|
||||
".ipsw": "application/x-itunes-ipsw",
|
||||
".iqy": "text/x-ms-iqy",
|
||||
".isp": "application/x-internet-signup",
|
||||
".ite": "application/x-itunes-ite",
|
||||
".itlp": "application/x-itunes-itlp",
|
||||
".itms": "application/x-itunes-itms",
|
||||
".itpc": "application/x-itunes-itpc",
|
||||
".IVF": "video/x-ivf",
|
||||
".jar": "application/java-archive",
|
||||
".java": "application/octet-stream",
|
||||
".jck": "application/liquidmotion",
|
||||
".jcz": "application/liquidmotion",
|
||||
".jfif": "image/pjpeg",
|
||||
".jnlp": "application/x-java-jnlp-file",
|
||||
".jpb": "application/octet-stream",
|
||||
".jpe": "image/jpeg",
|
||||
".jpeg": "image/jpeg",
|
||||
".jpg": "image/jpeg",
|
||||
".js": "application/javascript",
|
||||
".json": "application/json",
|
||||
".jsx": "text/jscript",
|
||||
".jsxbin": "text/plain",
|
||||
".latex": "application/x-latex",
|
||||
".library-ms": "application/windows-library+xml",
|
||||
".lit": "application/x-ms-reader",
|
||||
".loadtest": "application/xml",
|
||||
".lpk": "application/octet-stream",
|
||||
".lsf": "video/x-la-asf",
|
||||
".lst": "text/plain",
|
||||
".lsx": "video/x-la-asf",
|
||||
".lzh": "application/octet-stream",
|
||||
".m13": "application/x-msmediaview",
|
||||
".m14": "application/x-msmediaview",
|
||||
".m1v": "video/mpeg",
|
||||
".m2t": "video/vnd.dlna.mpeg-tts",
|
||||
".m2ts": "video/vnd.dlna.mpeg-tts",
|
||||
".m2v": "video/mpeg",
|
||||
".m3u": "audio/x-mpegurl",
|
||||
".m3u8": "audio/x-mpegurl",
|
||||
".m4a": "audio/m4a",
|
||||
".m4b": "audio/m4b",
|
||||
".m4p": "audio/m4p",
|
||||
".m4r": "audio/x-m4r",
|
||||
".m4v": "video/x-m4v",
|
||||
".mac": "image/x-macpaint",
|
||||
".mak": "text/plain",
|
||||
".man": "application/x-troff-man",
|
||||
".manifest": "application/x-ms-manifest",
|
||||
".map": "text/plain",
|
||||
".master": "application/xml",
|
||||
".mbox": "application/mbox",
|
||||
".mda": "application/msaccess",
|
||||
".mdb": "application/x-msaccess",
|
||||
".mde": "application/msaccess",
|
||||
".mdp": "application/octet-stream",
|
||||
".me": "application/x-troff-me",
|
||||
".mfp": "application/x-shockwave-flash",
|
||||
".mht": "message/rfc822",
|
||||
".mhtml": "message/rfc822",
|
||||
".mid": "audio/mid",
|
||||
".midi": "audio/mid",
|
||||
".mix": "application/octet-stream",
|
||||
".mk": "text/plain",
|
||||
".mmf": "application/x-smaf",
|
||||
".mno": "text/xml",
|
||||
".mny": "application/x-msmoney",
|
||||
".mod": "video/mpeg",
|
||||
".mov": "video/quicktime",
|
||||
".movie": "video/x-sgi-movie",
|
||||
".mp2": "video/mpeg",
|
||||
".mp2v": "video/mpeg",
|
||||
".mp3": "audio/mpeg",
|
||||
".mp4": "video/mp4",
|
||||
".mp4v": "video/mp4",
|
||||
".mpa": "video/mpeg",
|
||||
".mpe": "video/mpeg",
|
||||
".mpeg": "video/mpeg",
|
||||
".mpf": "application/vnd.ms-mediapackage",
|
||||
".mpg": "video/mpeg",
|
||||
".mpp": "application/vnd.ms-project",
|
||||
".mpv2": "video/mpeg",
|
||||
".mqv": "video/quicktime",
|
||||
".ms": "application/x-troff-ms",
|
||||
".msg": "application/vnd.ms-outlook",
|
||||
".msi": "application/octet-stream",
|
||||
".mso": "application/octet-stream",
|
||||
".mts": "video/vnd.dlna.mpeg-tts",
|
||||
".mtx": "application/xml",
|
||||
".mvb": "application/x-msmediaview",
|
||||
".mvc": "application/x-miva-compiled",
|
||||
".mxp": "application/x-mmxp",
|
||||
".nc": "application/x-netcdf",
|
||||
".nsc": "video/x-ms-asf",
|
||||
".nws": "message/rfc822",
|
||||
".ocx": "application/octet-stream",
|
||||
".oda": "application/oda",
|
||||
".odb": "application/vnd.oasis.opendocument.database",
|
||||
".odc": "application/vnd.oasis.opendocument.chart",
|
||||
".odf": "application/vnd.oasis.opendocument.formula",
|
||||
".odg": "application/vnd.oasis.opendocument.graphics",
|
||||
".odh": "text/plain",
|
||||
".odi": "application/vnd.oasis.opendocument.image",
|
||||
".odl": "text/plain",
|
||||
".odm": "application/vnd.oasis.opendocument.text-master",
|
||||
".odp": "application/vnd.oasis.opendocument.presentation",
|
||||
".ods": "application/vnd.oasis.opendocument.spreadsheet",
|
||||
".odt": "application/vnd.oasis.opendocument.text",
|
||||
".oga": "audio/ogg",
|
||||
".ogg": "audio/ogg",
|
||||
".ogv": "video/ogg",
|
||||
".ogx": "application/ogg",
|
||||
".one": "application/onenote",
|
||||
".onea": "application/onenote",
|
||||
".onepkg": "application/onenote",
|
||||
".onetmp": "application/onenote",
|
||||
".onetoc": "application/onenote",
|
||||
".onetoc2": "application/onenote",
|
||||
".opus": "audio/ogg",
|
||||
".orderedtest": "application/xml",
|
||||
".osdx": "application/opensearchdescription+xml",
|
||||
".otf": "application/font-sfnt",
|
||||
".otg": "application/vnd.oasis.opendocument.graphics-template",
|
||||
".oth": "application/vnd.oasis.opendocument.text-web",
|
||||
".otp": "application/vnd.oasis.opendocument.presentation-template",
|
||||
".ots": "application/vnd.oasis.opendocument.spreadsheet-template",
|
||||
".ott": "application/vnd.oasis.opendocument.text-template",
|
||||
".oxt": "application/vnd.openofficeorg.extension",
|
||||
".p10": "application/pkcs10",
|
||||
".p12": "application/x-pkcs12",
|
||||
".p7b": "application/x-pkcs7-certificates",
|
||||
".p7c": "application/pkcs7-mime",
|
||||
".p7m": "application/pkcs7-mime",
|
||||
".p7r": "application/x-pkcs7-certreqresp",
|
||||
".p7s": "application/pkcs7-signature",
|
||||
".pbm": "image/x-portable-bitmap",
|
||||
".pcast": "application/x-podcast",
|
||||
".pct": "image/pict",
|
||||
".pcx": "application/octet-stream",
|
||||
".pcz": "application/octet-stream",
|
||||
".pdf": "application/pdf",
|
||||
".pfb": "application/octet-stream",
|
||||
".pfm": "application/octet-stream",
|
||||
".pfx": "application/x-pkcs12",
|
||||
".pgm": "image/x-portable-graymap",
|
||||
".pic": "image/pict",
|
||||
".pict": "image/pict",
|
||||
".pkgdef": "text/plain",
|
||||
".pkgundef": "text/plain",
|
||||
".pko": "application/vnd.ms-pki.pko",
|
||||
".pls": "audio/scpls",
|
||||
".pma": "application/x-perfmon",
|
||||
".pmc": "application/x-perfmon",
|
||||
".pml": "application/x-perfmon",
|
||||
".pmr": "application/x-perfmon",
|
||||
".pmw": "application/x-perfmon",
|
||||
".png": "image/png",
|
||||
".pnm": "image/x-portable-anymap",
|
||||
".pnt": "image/x-macpaint",
|
||||
".pntg": "image/x-macpaint",
|
||||
".pnz": "image/png",
|
||||
".pot": "application/vnd.ms-powerpoint",
|
||||
".potm": "application/vnd.ms-powerpoint.template.macroEnabled.12",
|
||||
".potx": "application/vnd.openxmlformats-officedocument.presentationml.template",
|
||||
".ppa": "application/vnd.ms-powerpoint",
|
||||
".ppam": "application/vnd.ms-powerpoint.addin.macroEnabled.12",
|
||||
".ppm": "image/x-portable-pixmap",
|
||||
".pps": "application/vnd.ms-powerpoint",
|
||||
".ppsm": "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
|
||||
".ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
|
||||
".ppt": "application/vnd.ms-powerpoint",
|
||||
".pptm": "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
|
||||
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
".prf": "application/pics-rules",
|
||||
".prm": "application/octet-stream",
|
||||
".prx": "application/octet-stream",
|
||||
".ps": "application/postscript",
|
||||
".psc1": "application/PowerShell",
|
||||
".psd": "application/octet-stream",
|
||||
".psess": "application/xml",
|
||||
".psm": "application/octet-stream",
|
||||
".psp": "application/octet-stream",
|
||||
".pst": "application/vnd.ms-outlook",
|
||||
".pub": "application/x-mspublisher",
|
||||
".pwz": "application/vnd.ms-powerpoint",
|
||||
".qht": "text/x-html-insertion",
|
||||
".qhtm": "text/x-html-insertion",
|
||||
".qt": "video/quicktime",
|
||||
".qti": "image/x-quicktime",
|
||||
".qtif": "image/x-quicktime",
|
||||
".qtl": "application/x-quicktimeplayer",
|
||||
".qxd": "application/octet-stream",
|
||||
".ra": "audio/x-pn-realaudio",
|
||||
".ram": "audio/x-pn-realaudio",
|
||||
".rar": "application/x-rar-compressed",
|
||||
".ras": "image/x-cmu-raster",
|
||||
".rat": "application/rat-file",
|
||||
".rc": "text/plain",
|
||||
".rc2": "text/plain",
|
||||
".rct": "text/plain",
|
||||
".rdlc": "application/xml",
|
||||
".reg": "text/plain",
|
||||
".resx": "application/xml",
|
||||
".rf": "image/vnd.rn-realflash",
|
||||
".rgb": "image/x-rgb",
|
||||
".rgs": "text/plain",
|
||||
".rm": "application/vnd.rn-realmedia",
|
||||
".rmi": "audio/mid",
|
||||
".rmp": "application/vnd.rn-rn_music_package",
|
||||
".roff": "application/x-troff",
|
||||
".rpm": "audio/x-pn-realaudio-plugin",
|
||||
".rqy": "text/x-ms-rqy",
|
||||
".rtf": "application/rtf",
|
||||
".rtx": "text/richtext",
|
||||
".rvt": "application/octet-stream",
|
||||
".ruleset": "application/xml",
|
||||
".s": "text/plain",
|
||||
".safariextz": "application/x-safari-safariextz",
|
||||
".scd": "application/x-msschedule",
|
||||
".scr": "text/plain",
|
||||
".sct": "text/scriptlet",
|
||||
".sd2": "audio/x-sd2",
|
||||
".sdp": "application/sdp",
|
||||
".sea": "application/octet-stream",
|
||||
".searchConnector-ms": "application/windows-search-connector+xml",
|
||||
".setpay": "application/set-payment-initiation",
|
||||
".setreg": "application/set-registration-initiation",
|
||||
".settings": "application/xml",
|
||||
".sgimb": "application/x-sgimb",
|
||||
".sgml": "text/sgml",
|
||||
".sh": "application/x-sh",
|
||||
".shar": "application/x-shar",
|
||||
".shtml": "text/html",
|
||||
".sit": "application/x-stuffit",
|
||||
".sitemap": "application/xml",
|
||||
".skin": "application/xml",
|
||||
".skp": "application/x-koan",
|
||||
".sldm": "application/vnd.ms-powerpoint.slide.macroEnabled.12",
|
||||
".sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide",
|
||||
".slk": "application/vnd.ms-excel",
|
||||
".sln": "text/plain",
|
||||
".slupkg-ms": "application/x-ms-license",
|
||||
".smd": "audio/x-smd",
|
||||
".smi": "application/octet-stream",
|
||||
".smx": "audio/x-smd",
|
||||
".smz": "audio/x-smd",
|
||||
".snd": "audio/basic",
|
||||
".snippet": "application/xml",
|
||||
".snp": "application/octet-stream",
|
||||
".sol": "text/plain",
|
||||
".sor": "text/plain",
|
||||
".spc": "application/x-pkcs7-certificates",
|
||||
".spl": "application/futuresplash",
|
||||
".spx": "audio/ogg",
|
||||
".src": "application/x-wais-source",
|
||||
".srf": "text/plain",
|
||||
".SSISDeploymentManifest": "text/xml",
|
||||
".ssm": "application/streamingmedia",
|
||||
".sst": "application/vnd.ms-pki.certstore",
|
||||
".stl": "application/vnd.ms-pki.stl",
|
||||
".sv4cpio": "application/x-sv4cpio",
|
||||
".sv4crc": "application/x-sv4crc",
|
||||
".svc": "application/xml",
|
||||
".svg": "image/svg+xml",
|
||||
".swf": "application/x-shockwave-flash",
|
||||
".step": "application/step",
|
||||
".stp": "application/step",
|
||||
".t": "application/x-troff",
|
||||
".tar": "application/x-tar",
|
||||
".tcl": "application/x-tcl",
|
||||
".testrunconfig": "application/xml",
|
||||
".testsettings": "application/xml",
|
||||
".tex": "application/x-tex",
|
||||
".texi": "application/x-texinfo",
|
||||
".texinfo": "application/x-texinfo",
|
||||
".tgz": "application/x-compressed",
|
||||
".thmx": "application/vnd.ms-officetheme",
|
||||
".thn": "application/octet-stream",
|
||||
".tif": "image/tiff",
|
||||
".tiff": "image/tiff",
|
||||
".tlh": "text/plain",
|
||||
".tli": "text/plain",
|
||||
".toc": "application/octet-stream",
|
||||
".tr": "application/x-troff",
|
||||
".trm": "application/x-msterminal",
|
||||
".trx": "application/xml",
|
||||
".ts": "video/vnd.dlna.mpeg-tts",
|
||||
".tsv": "text/tab-separated-values",
|
||||
".ttf": "application/font-sfnt",
|
||||
".tts": "video/vnd.dlna.mpeg-tts",
|
||||
".txt": "text/plain",
|
||||
".u32": "application/octet-stream",
|
||||
".uls": "text/iuls",
|
||||
".user": "text/plain",
|
||||
".ustar": "application/x-ustar",
|
||||
".vb": "text/plain",
|
||||
".vbdproj": "text/plain",
|
||||
".vbk": "video/mpeg",
|
||||
".vbproj": "text/plain",
|
||||
".vbs": "text/vbscript",
|
||||
".vcf": "text/x-vcard",
|
||||
".vcproj": "application/xml",
|
||||
".vcs": "text/plain",
|
||||
".vcxproj": "application/xml",
|
||||
".vddproj": "text/plain",
|
||||
".vdp": "text/plain",
|
||||
".vdproj": "text/plain",
|
||||
".vdx": "application/vnd.ms-visio.viewer",
|
||||
".vml": "text/xml",
|
||||
".vscontent": "application/xml",
|
||||
".vsct": "text/xml",
|
||||
".vsd": "application/vnd.visio",
|
||||
".vsi": "application/ms-vsi",
|
||||
".vsix": "application/vsix",
|
||||
".vsixlangpack": "text/xml",
|
||||
".vsixmanifest": "text/xml",
|
||||
".vsmdi": "application/xml",
|
||||
".vspscc": "text/plain",
|
||||
".vss": "application/vnd.visio",
|
||||
".vsscc": "text/plain",
|
||||
".vssettings": "text/xml",
|
||||
".vssscc": "text/plain",
|
||||
".vst": "application/vnd.visio",
|
||||
".vstemplate": "text/xml",
|
||||
".vsto": "application/x-ms-vsto",
|
||||
".vsw": "application/vnd.visio",
|
||||
".vsx": "application/vnd.visio",
|
||||
".vtx": "application/vnd.visio",
|
||||
".wav": "audio/wav",
|
||||
".wave": "audio/wav",
|
||||
".wax": "audio/x-ms-wax",
|
||||
".wbk": "application/msword",
|
||||
".wbmp": "image/vnd.wap.wbmp",
|
||||
".wcm": "application/vnd.ms-works",
|
||||
".wdb": "application/vnd.ms-works",
|
||||
".wdp": "image/vnd.ms-photo",
|
||||
".webarchive": "application/x-safari-webarchive",
|
||||
".webm": "video/webm",
|
||||
".webp": "image/webp", /* https"://en.wikipedia.org/wiki/WebP */
|
||||
".webtest": "application/xml",
|
||||
".wiq": "application/xml",
|
||||
".wiz": "application/msword",
|
||||
".wks": "application/vnd.ms-works",
|
||||
".WLMP": "application/wlmoviemaker",
|
||||
".wlpginstall": "application/x-wlpg-detect",
|
||||
".wlpginstall3": "application/x-wlpg3-detect",
|
||||
".wm": "video/x-ms-wm",
|
||||
".wma": "audio/x-ms-wma",
|
||||
".wmd": "application/x-ms-wmd",
|
||||
".wmf": "application/x-msmetafile",
|
||||
".wml": "text/vnd.wap.wml",
|
||||
".wmlc": "application/vnd.wap.wmlc",
|
||||
".wmls": "text/vnd.wap.wmlscript",
|
||||
".wmlsc": "application/vnd.wap.wmlscriptc",
|
||||
".wmp": "video/x-ms-wmp",
|
||||
".wmv": "video/x-ms-wmv",
|
||||
".wmx": "video/x-ms-wmx",
|
||||
".wmz": "application/x-ms-wmz",
|
||||
".woff": "application/font-woff",
|
||||
".wpl": "application/vnd.ms-wpl",
|
||||
".wps": "application/vnd.ms-works",
|
||||
".wri": "application/x-mswrite",
|
||||
".wrl": "x-world/x-vrml",
|
||||
".wrz": "x-world/x-vrml",
|
||||
".wsc": "text/scriptlet",
|
||||
".wsdl": "text/xml",
|
||||
".wvx": "video/x-ms-wvx",
|
||||
".x": "application/directx",
|
||||
".xaf": "x-world/x-vrml",
|
||||
".xaml": "application/xaml+xml",
|
||||
".xap": "application/x-silverlight-app",
|
||||
".xbap": "application/x-ms-xbap",
|
||||
".xbm": "image/x-xbitmap",
|
||||
".xdr": "text/plain",
|
||||
".xht": "application/xhtml+xml",
|
||||
".xhtml": "application/xhtml+xml",
|
||||
".xla": "application/vnd.ms-excel",
|
||||
".xlam": "application/vnd.ms-excel.addin.macroEnabled.12",
|
||||
".xlc": "application/vnd.ms-excel",
|
||||
".xld": "application/vnd.ms-excel",
|
||||
".xlk": "application/vnd.ms-excel",
|
||||
".xll": "application/vnd.ms-excel",
|
||||
".xlm": "application/vnd.ms-excel",
|
||||
".xls": "application/vnd.ms-excel",
|
||||
".xlsb": "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
|
||||
".xlsm": "application/vnd.ms-excel.sheet.macroEnabled.12",
|
||||
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
".xlt": "application/vnd.ms-excel",
|
||||
".xltm": "application/vnd.ms-excel.template.macroEnabled.12",
|
||||
".xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
|
||||
".xlw": "application/vnd.ms-excel",
|
||||
".xml": "text/xml",
|
||||
".xmp": "application/octet-stream",
|
||||
".xmta": "application/xml",
|
||||
".xof": "x-world/x-vrml",
|
||||
".XOML": "text/plain",
|
||||
".xpm": "image/x-xpixmap",
|
||||
".xps": "application/vnd.ms-xpsdocument",
|
||||
".xrm-ms": "text/xml",
|
||||
".xsc": "application/xml",
|
||||
".xsd": "text/xml",
|
||||
".xsf": "text/xml",
|
||||
".xsl": "text/xml",
|
||||
".xslt": "text/xml",
|
||||
".xsn": "application/octet-stream",
|
||||
".xss": "application/xml",
|
||||
".xspf": "application/xspf+xml",
|
||||
".xtp": "application/octet-stream",
|
||||
".xwd": "image/x-xwindowdump",
|
||||
".z": "application/x-compress",
|
||||
".zip": "application/zip"}
|
||||
|
||||
if mimeType, ok := mimeMap[extension]; ok {
|
||||
return mimeType
|
||||
} else {
|
||||
return "application/octet-stream"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//根据一个请求,获取ip.
|
||||
func GetIpAddress(r *http.Request) string {
|
||||
var ipAddress string
|
||||
|
||||
ipAddress = r.RemoteAddr
|
||||
|
||||
if ipAddress != "" {
|
||||
ipAddress = strings.Split(ipAddress, ":")[0]
|
||||
}
|
||||
|
||||
for _, h := range []string{"X-Forwarded-For", "X-Real-Ip"} {
|
||||
for _, ip := range strings.Split(r.Header.Get(h), ",") {
|
||||
if ip != "" {
|
||||
ipAddress = ip
|
||||
}
|
||||
}
|
||||
}
|
||||
return ipAddress
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
//判断文件或文件夹是否已经存在
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
//获取该应用可执行文件的位置。
|
||||
//例如:C:\Users\lishuang\AppData\Local\Temp
|
||||
func GetHomePath() string {
|
||||
ex, err := os.Executable()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
exPath := filepath.Dir(ex)
|
||||
return exPath
|
||||
}
|
||||
|
||||
//获取前端静态资源的位置。如果你在开发模式下,可以将这里直接返回tank/build下面的html路径。
|
||||
//例如:C:/Users/lishuang/AppData/Local/Temp/html
|
||||
func GetHtmlPath() string {
|
||||
|
||||
homePath := GetHomePath()
|
||||
filePath := homePath + "/html"
|
||||
exists, err := PathExists(filePath)
|
||||
if err != nil {
|
||||
panic("判断上传文件是否存在时出错!")
|
||||
}
|
||||
if !exists {
|
||||
err = os.MkdirAll(filePath, 0777)
|
||||
if err != nil {
|
||||
panic("创建上传文件夹时出错!")
|
||||
}
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
|
||||
//获取上传文件存放的位置。
|
||||
//例如:C:\Users\lishuang\AppData\Local\Temp/matter
|
||||
func GetFilePath() string {
|
||||
|
||||
homePath := GetHomePath()
|
||||
filePath := homePath + "/matter"
|
||||
exists, err := PathExists(filePath)
|
||||
if err != nil {
|
||||
panic("判断上传文件是否存在时出错!")
|
||||
}
|
||||
if !exists {
|
||||
err = os.MkdirAll(filePath, 0777)
|
||||
if err != nil {
|
||||
panic("创建上传文件夹时出错!")
|
||||
}
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
|
||||
//获取日志存放的位置。
|
||||
//例如:C:\Users\lishuang\AppData\Local\Temp/log
|
||||
func GetLogPath() string {
|
||||
|
||||
homePath := GetHomePath()
|
||||
filePath := homePath + "/log"
|
||||
exists, err := PathExists(filePath)
|
||||
if err != nil {
|
||||
panic("判断日志文件夹是否存在时出错!")
|
||||
}
|
||||
if !exists {
|
||||
err = os.MkdirAll(filePath, 0666)
|
||||
if err != nil {
|
||||
panic("创建日志文件夹时出错!")
|
||||
}
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
|
||||
//获取配置文件存放的位置
|
||||
//例如:C:\Users\lishuang\AppData\Local\Temp/conf
|
||||
func GetConfPath() string {
|
||||
|
||||
homePath := GetHomePath()
|
||||
filePath := homePath + "/conf"
|
||||
exists, err := PathExists(filePath)
|
||||
if err != nil {
|
||||
panic("判断日志文件夹是否存在时出错!")
|
||||
}
|
||||
if !exists {
|
||||
err = os.MkdirAll(filePath, 0666)
|
||||
if err != nil {
|
||||
panic("创建日志文件夹时出错!")
|
||||
}
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
|
||||
//获取某个用户文件应该存放的位置。这个是相对GetFilePath的路径
|
||||
//例如:/zicla/2006-01-02/1510122428000
|
||||
func GetUserFilePath(username string) (string, string) {
|
||||
|
||||
now := time.Now()
|
||||
datePath := now.Format("2006-01-02")
|
||||
//毫秒时间戳
|
||||
timestamp := now.UnixNano() / 1e6
|
||||
|
||||
filePath := GetFilePath()
|
||||
absolutePath := fmt.Sprintf("%s/%s/%s/%d", filePath, username, datePath, timestamp)
|
||||
relativePath := fmt.Sprintf("/%s/%s/%d", username, datePath, timestamp)
|
||||
|
||||
exists, err := PathExists(absolutePath)
|
||||
if err != nil {
|
||||
panic("判断上传文件是否存在时出错!")
|
||||
}
|
||||
if !exists {
|
||||
err = os.MkdirAll(absolutePath, 0777)
|
||||
if err != nil {
|
||||
panic("创建上传文件夹时出错!")
|
||||
}
|
||||
}
|
||||
|
||||
return absolutePath, relativePath
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
package rest
|
||||
|
||||
type WebResult struct {
|
||||
Code int `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func (this *WebResult) Error() string {
|
||||
return this.Msg
|
||||
}
|
||||
|
||||
const (
|
||||
//正常
|
||||
RESULT_CODE_OK = 200
|
||||
|
||||
//未登录
|
||||
RESULT_CODE_LOGIN = -400
|
||||
|
||||
//没有权限
|
||||
RESULT_CODE_UNAUTHORIZED = -401
|
||||
|
||||
//请求错误
|
||||
RESULT_CODE_BAD_REQUEST = -402
|
||||
|
||||
//没有找到
|
||||
RESULT_CODE_NOT_FOUND = -404
|
||||
|
||||
//登录过期
|
||||
RESULT_CODE_LOGIN_EXPIRED = -405
|
||||
|
||||
//该登录用户不是有效用户
|
||||
RESULT_CODE_LOGIN_INVALID = -406
|
||||
|
||||
//提交的表单验证不通过
|
||||
RESULT_CODE_FORM_INVALID = -410
|
||||
|
||||
//请求太频繁
|
||||
RESULT_CODE_FREQUENCY = -420
|
||||
|
||||
//服务器出错。
|
||||
RESULT_CODE_SERVER_ERROR = -500
|
||||
|
||||
//远程服务不可用
|
||||
RESULT_CODE_NOT_AVAILABLE = -501
|
||||
|
||||
//并发异常
|
||||
RESULT_CODE_CONCURRENCY = -511
|
||||
|
||||
//远程微服务没有找到
|
||||
RESULT_CODE_SERVICE_NOT_FOUND = -600
|
||||
|
||||
//远程微服务连接超时
|
||||
RESULT_CODE_SERVICE_TIME_OUT = -610
|
||||
|
||||
//通用的异常
|
||||
RESULT_CODE_UTIL_EXCEPTION = -700
|
||||
)
|
||||
|
||||
func ConstWebResult(code int) *WebResult {
|
||||
|
||||
wr := &WebResult{}
|
||||
switch code {
|
||||
//正常
|
||||
case RESULT_CODE_OK:
|
||||
wr.Msg = "成功"
|
||||
//未登录
|
||||
case RESULT_CODE_LOGIN:
|
||||
wr.Msg = "没有登录,禁止访问"
|
||||
//没有权限
|
||||
case RESULT_CODE_UNAUTHORIZED:
|
||||
wr.Msg = "没有权限"
|
||||
//请求错误
|
||||
case RESULT_CODE_BAD_REQUEST:
|
||||
wr.Msg = "请求错误"
|
||||
//没有找到
|
||||
case RESULT_CODE_NOT_FOUND:
|
||||
wr.Msg = "没有找到"
|
||||
//登录过期
|
||||
case RESULT_CODE_LOGIN_EXPIRED:
|
||||
wr.Msg = "登录过期"
|
||||
|
||||
//该登录用户不是有效用户
|
||||
case RESULT_CODE_LOGIN_INVALID:
|
||||
wr.Msg = "该登录用户不是有效用户"
|
||||
|
||||
//提交的表单验证不通过
|
||||
case RESULT_CODE_FORM_INVALID:
|
||||
wr.Msg = "提交的表单验证不通过"
|
||||
//请求太频繁
|
||||
case RESULT_CODE_FREQUENCY:
|
||||
wr.Msg = "请求太频繁"
|
||||
//服务器出错。
|
||||
case RESULT_CODE_SERVER_ERROR:
|
||||
wr.Msg = "服务器出错"
|
||||
//远程服务不可用
|
||||
case RESULT_CODE_NOT_AVAILABLE:
|
||||
wr.Msg = "远程服务不可用"
|
||||
//并发异常
|
||||
case RESULT_CODE_CONCURRENCY:
|
||||
wr.Msg = "并发异常"
|
||||
//远程微服务没有找到
|
||||
case RESULT_CODE_SERVICE_NOT_FOUND:
|
||||
wr.Msg = "远程微服务没有找到"
|
||||
//远程微服务连接超时
|
||||
case RESULT_CODE_SERVICE_TIME_OUT:
|
||||
wr.Msg = "远程微服务连接超时"
|
||||
default:
|
||||
code = RESULT_CODE_UTIL_EXCEPTION
|
||||
wr.Msg = "服务器未知错误"
|
||||
}
|
||||
wr.Code = code
|
||||
return wr
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user