2
0

AdminLTE.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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.rtcSupported = () => {
  91. return !!RTCPeerConnection;
  92. }
  93. Vue.prototype.canTalk = () => {
  94. return location.protocol.indexOf("https") == 0 || location.hostname === 'localhost' || location.hostname === '127.0.0.1';
  95. }
  96. Vue.prototype.hasAnyRole = (serverInfo, userInfo, ...roles) => {
  97. roles = roles||[];
  98. if (serverInfo && serverInfo.APIAuth === false && !userInfo) {
  99. if(roles.length == 1 && roles[0] == '管理员') {
  100. return false;
  101. } else {
  102. return true;
  103. }
  104. }
  105. var userRoles = [];
  106. if (userInfo) {
  107. userRoles = userInfo.Roles || [];
  108. }
  109. var checked = false;
  110. for(var role of roles) {
  111. if (!role || userRoles.some(ur => (ur == role || ur == '超级管理员'))) {
  112. checked = true;
  113. break;
  114. }
  115. }
  116. return checked;
  117. }
  118. Vue.prototype.hasAllChannel = (serverInfo, userInfo) => {
  119. if (serverInfo && serverInfo.APIAuth === false && !userInfo) {
  120. return true;
  121. }
  122. if (userInfo) {
  123. return userInfo.HasAllChannel;
  124. }
  125. return false;
  126. }
  127. Vue.prototype.isDemoUser = (serverInfo, userInfo) => {
  128. if (serverInfo && userInfo && serverInfo.IsDemo && userInfo.Name == serverInfo.DemoUser) return true;
  129. return false;
  130. }
  131. import $ from "jquery"
  132. import "@penggy/jquery.nicescroll"
  133. $.ajaxSetup({ cache: false });
  134. export default {
  135. data() {
  136. return {
  137. nice: null,
  138. }
  139. },
  140. mounted() {
  141. $(document).ajaxError((evt, xhr, opts, ex) => {
  142. if (xhr.status == 401) {
  143. location.href = `/login.html?r=${encodeURIComponent(window.location.href)}`;
  144. return false;
  145. } else if (xhr.status) {
  146. let msg = xhr.responseText || "网络请求失败";
  147. if (xhr.status == 404) {
  148. msg = "请求服务不存在或已停止";
  149. } else if (xhr.status == 504) {
  150. msg = "Gateway Timeout";
  151. }
  152. try {
  153. msg = JSON.parse(msg)
  154. } catch (error) {}
  155. this.$message({
  156. type: 'error',
  157. message: msg
  158. })
  159. } else {
  160. console.log(`ajax error: ${xhr.status} ${xhr.responseText}`);
  161. }
  162. }).on("click", ".main-header .sidebar-toggle", function () {
  163. setTimeout(() => {
  164. localStorage["sidebar-collapse"] = $("body").hasClass("sidebar-collapse") ? "sidebar-collapse" : "";
  165. }, 500)
  166. }).ready(() => {
  167. this.$nextTick(() => {
  168. $("body").layout("fix");
  169. this.fixHover();
  170. this.initNiceScroll();
  171. });
  172. }).on('shown.bs.modal', () => {
  173. this.removeNiceScroll();
  174. }).on('hidden.bs.modal', () => {
  175. this.initNiceScroll();
  176. });
  177. $("body").addClass(localStorage["sidebar-collapse"]);
  178. },
  179. components: {
  180. NaviBar, Sider, VideoDlg, ModifyPasswordDlg
  181. },
  182. computed: {
  183. ...mapState([
  184. "menus",
  185. "userInfo",
  186. "serverInfo",
  187. ]),
  188. versionText(){
  189. var text = "";
  190. if(this.serverInfo){
  191. text = this.serverInfo.Server || ""
  192. }
  193. var matchs = text.match(/LiveGBS\/(.+?)\s/i);
  194. if(matchs) {
  195. return matchs[1];
  196. }
  197. return ""
  198. }
  199. },
  200. methods: {
  201. ...mapActions([
  202. "getServerInfo"
  203. ]),
  204. initNiceScroll() {
  205. if(!this.isIE() && !this.isMobile() && !this.nice) {
  206. this.nice = $('body').niceScroll({
  207. zindex: 999999,
  208. cursorwidth: "10px",
  209. cursoropacitymax: 0.5,
  210. preservenativescrolling: false,
  211. enablekeyboard: false,
  212. });
  213. }
  214. },
  215. removeNiceScroll() {
  216. if (this.nice) {
  217. this.nice.remove();
  218. this.nice = null;
  219. }
  220. },
  221. fixHover() {
  222. if(videojs.browser.IS_IOS||videojs.browser.IS_ANDROID) {
  223. for(var sheetI = document.styleSheets.length - 1; sheetI >= 0; sheetI--) {
  224. var sheet = document.styleSheets[sheetI];
  225. if(sheet.cssRules) {
  226. for(var ruleI = sheet.cssRules.length - 1; ruleI >= 0; ruleI--) {
  227. var rule = sheet.cssRules[ruleI];
  228. if(rule.selectorText) {
  229. rule.selectorText = rule.selectorText.replace(":hover", ":active");
  230. rule.selectorText = rule.selectorText.replace(":focus", ":active");
  231. }
  232. }
  233. }
  234. }
  235. }
  236. },
  237. handleResize() {
  238. this.nice && this.nice.resize();
  239. },
  240. play(video){
  241. this.$refs['videoDlg'].play(video.videoUrl, video.videoTitle, video.snapUrl);
  242. },
  243. thisYear() {
  244. return moment().format('YYYY');
  245. }
  246. },
  247. beforeRouteUpdate(to, from, next) {
  248. $('.modal').modal('hide') // closes all active pop ups.
  249. next();
  250. }
  251. }
  252. </script>
  253. <style lang="less" scoped>
  254. .content-wrapper, .right-side, .main-footer {
  255. transition: none;
  256. }
  257. </style>
  258. <style lang="less">
  259. .vue-back-to-top {
  260. background-color: transparent;
  261. left: 30px;
  262. bottom: 10px;
  263. }
  264. .sidebar-collapse .vue-back-to-top {
  265. display: none;
  266. }
  267. </style>