AdminLTE.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. <template>
  2. <div class="wrapper">
  3. <NaviBar :logoText="serverInfo.LogoText" :logoMiniText="serverInfo.LogoMiniText" :versionText="versionText" @modify-password="$refs['modify-password-dlg'].show()"></NaviBar>
  4. <Sider :menus="menus"></Sider>
  5. <VideoDlg ref="videoDlg" fade></VideoDlg>
  6. <ModifyPasswordDlg ref="modify-password-dlg"></ModifyPasswordDlg>
  7. <div class="content-wrapper">
  8. <section class="content">
  9. <router-view @play="play"></router-view>
  10. </section>
  11. </div>
  12. <footer class="main-footer">
  13. <div class="pull-right hidden-xs hide">
  14. {{serverInfo.LogoText}}
  15. </div>
  16. <span v-html="serverInfo.CopyrightText"></span>
  17. </footer>
  18. <back-to-top text="返回顶部" class="hidden-xs"></back-to-top>
  19. <resize-observer @notify="handleResize"/>
  20. </div>
  21. </template>
  22. <script>
  23. import "font-awesome/css/font-awesome.css"
  24. import "bootstrap/dist/css/bootstrap.css"
  25. import "admin-lte/dist/css/AdminLTE.css"
  26. import "admin-lte/dist/css/skins/_all-skins.css"
  27. import "assets/styles/custom.less"
  28. import 'vue-resize/dist/vue-resize.css'
  29. import "bootstrap/dist/js/bootstrap.js"
  30. import "admin-lte/dist/js/adminlte.js"
  31. import { mapState, mapActions } from "vuex"
  32. import Vue from 'vue'
  33. import moment from 'moment'
  34. import Sider from 'components/Sider.vue'
  35. import NaviBar from 'components/NaviBar.vue'
  36. import VideoDlg from 'components/VideoDlg.vue'
  37. import ModifyPasswordDlg from 'components/ModifyPasswordDlg.vue'
  38. import ElementUI from "element-ui"
  39. import 'assets/styles/element-custom.scss'
  40. Vue.use(ElementUI);
  41. import VCharts from 'v-charts'
  42. Vue.use(VCharts);
  43. import VueClipboards from 'vue-clipboards';
  44. Vue.use(VueClipboards);
  45. import fullscreen from 'vue-fullscreen'
  46. Vue.use(fullscreen);
  47. import BackToTop from 'vue-backtotop'
  48. Vue.use(BackToTop);
  49. import VueResize from 'vue-resize'
  50. Vue.use(VueResize);
  51. import VeeValidate, { Validator } from "vee-validate";
  52. import zh_CN from "vee-validate/dist/locale/zh_CN";
  53. Validator.localize("zh_CN", zh_CN);
  54. Vue.use(VeeValidate, {
  55. locale: "zh_CN",
  56. // delay: 500,
  57. dictionary: {
  58. zh_CN: {
  59. messages: {
  60. required: field => `${field} 不能为空`,
  61. integer: field => `${field} 不是有效值`,
  62. confirmed: (field, targetField) => `${field} 和 ${targetField} 不匹配`,
  63. regex: field => `${field} 不符合要求格式`
  64. }
  65. }
  66. }
  67. });
  68. Vue.prototype.$updateQueryString = (uri, key, value) => {
  69. var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
  70. var separator = uri.indexOf('?') !== -1 ? "&" : "?";
  71. if (uri.match(re)) {
  72. return uri.replace(re, '$1' + key + "=" + value + '$2');
  73. } else {
  74. return uri + separator + key + "=" + value;
  75. }
  76. }
  77. Vue.prototype.$iframe = (link, w, h) => {
  78. var _link = Vue.prototype.$updateQueryString(link, "aspect", `${w}x${h}`)
  79. return `<iframe src="${_link}" width="${w}" height="${h}" allowfullscreen allow="autoplay; fullscreen"></iframe>`
  80. }
  81. Vue.prototype.isMobile = () => {
  82. return videojs.browser.IS_IOS || videojs.browser.IS_ANDROID;
  83. }
  84. Vue.prototype.isIE = () => {
  85. return !!videojs.browser.IE_VERSION;
  86. }
  87. Vue.prototype.flvSupported = () => {
  88. return videojs.browser.IE_VERSION || (flvjs.getFeatureList() && flvjs.getFeatureList().mseLiveFlvPlayback);
  89. }
  90. Vue.prototype.canTalk = () => {
  91. return location.protocol.indexOf("https") == 0 || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
  92. }
  93. Vue.prototype.hasAnyRole = (serverInfo, userInfo, ...roles) => {
  94. if (serverInfo && serverInfo.APIAuth === false && !userInfo) {
  95. return true;
  96. }
  97. var userRoles = [];
  98. if (userInfo) {
  99. userRoles = userInfo.Roles || [];
  100. }
  101. var checked = false;
  102. for(var role of (roles||[])) {
  103. if (!role || userRoles.some(ur => (ur == role || ur == '超级管理员'))) {
  104. checked = true;
  105. break;
  106. }
  107. }
  108. return checked;
  109. }
  110. Vue.prototype.hasAllChannel = (serverInfo, userInfo) => {
  111. if (serverInfo && serverInfo.APIAuth === false && !userInfo) {
  112. return true;
  113. }
  114. if (userInfo) {
  115. return userInfo.HasAllChannel;
  116. }
  117. return false;
  118. }
  119. Vue.prototype.isDemoUser = (serverInfo, userInfo) => {
  120. if (serverInfo && userInfo && serverInfo.IsDemo && userInfo.Name == serverInfo.DemoUser) return true;
  121. return false;
  122. }
  123. import $ from "jquery"
  124. import "@penggy/jquery.nicescroll"
  125. $.ajaxSetup({ cache: false });
  126. export default {
  127. data() {
  128. return {
  129. nice: null,
  130. }
  131. },
  132. watch: {
  133. serverInfo(val) {
  134. if (val) {
  135. document.title = val.LogoText || "LiveGBS";
  136. }
  137. }
  138. },
  139. mounted() {
  140. $(document).ajaxError((evt, xhr, opts, ex) => {
  141. if (xhr.status == 401) {
  142. location.href = `/login.html?r=${encodeURIComponent(window.location.href)}`;
  143. return false;
  144. } else if (xhr.status) {
  145. let msg = xhr.responseText || "网络请求失败";
  146. if (xhr.status == 404) {
  147. msg = "请求服务不存在或已停止";
  148. } else if (xhr.status == 504) {
  149. msg = "Gateway Timeout";
  150. }
  151. try {
  152. msg = JSON.parse(msg)
  153. } catch (error) {}
  154. this.$message({
  155. type: 'error',
  156. message: msg
  157. })
  158. } else {
  159. console.log(`ajax error: ${xhr.status} ${xhr.responseText}`);
  160. }
  161. }).on("click", ".main-header .sidebar-toggle", function () {
  162. setTimeout(() => {
  163. localStorage["sidebar-collapse"] = $("body").hasClass("sidebar-collapse") ? "sidebar-collapse" : "";
  164. }, 500)
  165. }).ready(() => {
  166. this.$nextTick(() => {
  167. $("body").layout("fix");
  168. this.fixHover();
  169. if(!this.isIE() && !this.isMobile()) {
  170. this.nice = $("body").niceScroll({
  171. zindex: 999999,
  172. cursorwidth: "10px",
  173. cursoropacitymax: 0.5,
  174. enablekeyboard: false,
  175. });
  176. }
  177. });
  178. });
  179. $("body").addClass(localStorage["sidebar-collapse"]);
  180. },
  181. components: {
  182. NaviBar, Sider, VideoDlg, ModifyPasswordDlg
  183. },
  184. computed: {
  185. ...mapState([
  186. "menus",
  187. "userInfo",
  188. "serverInfo",
  189. ]),
  190. versionText(){
  191. var text = "";
  192. if(this.serverInfo){
  193. text = this.serverInfo.Server || ""
  194. }
  195. var matchs = text.match(/LiveGBS\/(.+?)\s/i);
  196. if(matchs) {
  197. return matchs[1];
  198. }
  199. return ""
  200. }
  201. },
  202. methods: {
  203. ...mapActions([
  204. "getServerInfo"
  205. ]),
  206. fixHover() {
  207. if(videojs.browser.IS_IOS||videojs.browser.IS_ANDROID) {
  208. for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
  209. var sheet = document.styleSheets[sheetI];
  210. if(sheet.cssRules) {
  211. for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
  212. var rule = sheet.cssRules[ruleI];
  213. if(rule.selectorText) {
  214. rule.selectorText = rule.selectorText.replace(":hover", ":active");
  215. rule.selectorText = rule.selectorText.replace(":focus", ":active");
  216. }
  217. }
  218. }
  219. }
  220. }
  221. },
  222. handleResize() {
  223. this.nice && this.nice.resize();
  224. },
  225. play(video){
  226. this.$refs['videoDlg'].play(video.videoUrl, video.videoTitle, video.snapUrl);
  227. },
  228. thisYear() {
  229. return moment().format('YYYY');
  230. }
  231. },
  232. beforeRouteUpdate(to, from, next) {
  233. $('.modal').modal('hide') // closes all active pop ups.
  234. next();
  235. }
  236. }
  237. </script>
  238. <style lang="less" scoped>
  239. .content-wrapper, .right-side, .main-footer {
  240. transition: none;
  241. }
  242. </style>
  243. <style lang="less">
  244. .vue-back-to-top {
  245. background-color: transparent;
  246. left: 30px;
  247. bottom: 10px;
  248. }
  249. .sidebar-collapse .vue-back-to-top {
  250. display: none;
  251. }
  252. </style>