sa.js 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389
  1. // =========================== sa对象封装一系列工具方法 ===========================
  2. var sa = {
  3. version: '2.4.3',
  4. update_time: '2020-10-2',
  5. info: '新增双击layer标题处全屏'
  6. };
  7. // =========================== 当前环境配置 =======================================
  8. (function(){
  9. // 公司开发环境
  10. var cfg_dev = {
  11. api_url: 'http://192.168.3.217:8099/pro', // 所有ajax请求接口父地址
  12. web_url: 'http://www.baidu.com' // 此项目前台地址 (此配置项非必须)
  13. }
  14. // 服务器测试环境
  15. var cfg_test = {
  16. api_url: 'http://www.baidu.com',
  17. web_url: 'http://www.baidu.com'
  18. }
  19. // 正式生产环境
  20. var cfg_prod = {
  21. api_url: 'http://www.baidu.com',
  22. web_url: 'http://www.baidu.com'
  23. }
  24. sa.cfg = cfg_dev; // 最终环境 , 上线前请选择正确的环境
  25. })();
  26. // =========================== ajax的封装 =======================================
  27. (function(){
  28. sa.ajaxNoLoading = function(url, data, success200, cfg){
  29. // 如果是简写模式(省略了data参数)
  30. if(typeof data === 'function'){
  31. cfg = success200;
  32. success200 = data;
  33. data = {};
  34. }
  35. // 默认配置
  36. var defaultCfg = {
  37. baseUrl: (url.indexOf('http') === 0 ? '' : sa.cfg.api_url),// 父url,拼接在url前面
  38. sleep: 0, // 休眠n毫秒处理回调函数
  39. type: 'post', // 默认请求类型
  40. success200: success200, // code=200, 代表成功
  41. success500: function(res){ // code=500, 代表失败
  42. return layer.alert('失败:' + res.msg);
  43. },
  44. success403: function(res){ // code=403, 代表权限不足
  45. return layer.alert("权限不足," + res.msg, {icon: 5});
  46. },
  47. success401: function(res){ // code=401, 代表未登录
  48. return layer.confirm("您当前暂未登录,是否立即登录?", {}, function(){
  49. layer.closeAll();
  50. return sa.$page.openLogin(cfg.login_url);
  51. });
  52. },
  53. errorfn: function(xhr, type, errorThrown){ // ajax发生异常时的默认处理函数
  54. if(xhr.status == 0){
  55. return layer.alert('无法连接到服务器,请检查网络');
  56. }
  57. return layer.alert("异常:" + JSON.stringify(xhr));
  58. },
  59. complete: function(xhr, ts) { // 成功失败都会执行
  60. }
  61. }
  62. // 将调用者的配置和默认配置合并
  63. cfg = sa.extendJson(cfg, defaultCfg);
  64. // 开始显示loading图标
  65. if(cfg.msg != null){
  66. sa.loading(cfg.msg);
  67. }
  68. // 开始请求ajax
  69. return $.ajax({
  70. url: cfg.baseUrl + url,
  71. type: cfg.type,
  72. data: data,
  73. dataType: 'json',
  74. // xhrFields: {
  75. // withCredentials: true // 携带跨域cookie
  76. // },
  77. // crossDomain: true,
  78. beforeSend: function(xhr) {
  79. xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
  80. // 追加token
  81. if(localStorage.tokenName) {
  82. xhr.setRequestHeader(localStorage.tokenName, localStorage.tokenValue);
  83. }
  84. },
  85. success: function(res){
  86. console.log('返回数据:', res);
  87. setTimeout(function() {
  88. sa.hideLoading();
  89. // 如果相应的处理函数存在
  90. if(cfg['success' + res.code] != undefined) {
  91. return cfg['success' + res.code](res);
  92. }
  93. layer.alert('未知状态码:' + JSON.stringify(res));
  94. }, cfg.sleep);
  95. },
  96. error: function(xhr, type, errorThrown){
  97. setTimeout(function() {
  98. sa.hideLoading();
  99. return cfg.errorfn(xhr, type, errorThrown);
  100. }, cfg.sleep);
  101. },
  102. complete: cfg.complete
  103. });
  104. };
  105. /** 对ajax的再封装, 这个ajax假设你的接口会返回以下格式的内容
  106. {
  107. "code": 200,
  108. "msg": "ok",
  109. "data": []
  110. }
  111. 如果返回的不是这个格式, 你可能需要改动一下源码, 要么改动服务端适应此ajax, 要么改动这个ajax适应你的服务端
  112. * @param {Object} url 请求地址
  113. * @param {Object} data 请求参数
  114. * @param {Object} success200 当返回的code码==200时的回调函数
  115. * @param {Object} 其它配置,可配置项有:
  116. {
  117. msg: '', // 默认的提示文字 填null为不提示
  118. type: 'get', // 设定请求类型 默认post
  119. baseUrl: '', // ajax请求拼接的父路径 默认取 sa.cfg.api_url
  120. sleep: 0, // ajax模拟的延时毫秒数, 默认0
  121. success500: fn, // code码等于500时的回调函数 (一般代表服务器错误)
  122. success403: fn, // code码等于403时的回调函数 (一般代表无权限)
  123. success401: fn, // code码等于401时的回调函数 (一般代表未登录)
  124. errorfn: fn, // ajax发生错误时的回调函数 (一般是ajax请求本身发生了错误)
  125. complete: fn, // ajax无论成功还是失败都会执行的回调函数
  126. }
  127. */
  128. sa.ajax = function(url, data, success200, cfg){
  129. // 如果是简写模式(省略了data参数)
  130. if(typeof data === 'function'){
  131. cfg = success200;
  132. success200 = data;
  133. data = {};
  134. }
  135. // 默认配置
  136. var defaultCfg = {
  137. msg: '努力加载中...', // 提示语
  138. baseUrl: (url.indexOf('http') === 0 ? '' : sa.cfg.api_url),// 父url,拼接在url前面
  139. sleep: 0, // 休眠n毫秒处理回调函数
  140. type: 'post', // 默认请求类型
  141. success200: success200, // code=200, 代表成功
  142. success500: function(res){ // code=500, 代表失败
  143. return layer.alert('失败:' + res.msg);
  144. },
  145. success403: function(res){ // code=403, 代表权限不足
  146. return layer.alert("权限不足," + res.msg, {icon: 5});
  147. },
  148. success401: function(res){ // code=401, 代表未登录
  149. return layer.confirm("您当前暂未登录,是否立即登录?", {}, function(){
  150. layer.closeAll();
  151. return sa.$page.openLogin(cfg.login_url);
  152. });
  153. },
  154. errorfn: function(xhr, type, errorThrown){ // ajax发生异常时的默认处理函数
  155. if(xhr.status == 0){
  156. return layer.alert('无法连接到服务器,请检查网络');
  157. }
  158. return layer.alert("异常:" + JSON.stringify(xhr));
  159. },
  160. complete: function(xhr, ts) { // 成功失败都会执行
  161. }
  162. }
  163. // 将调用者的配置和默认配置合并
  164. cfg = sa.extendJson(cfg, defaultCfg);
  165. // 开始显示loading图标
  166. if(cfg.msg != null){
  167. sa.loading(cfg.msg);
  168. }
  169. // 开始请求ajax
  170. return $.ajax({
  171. url: cfg.baseUrl + url,
  172. type: cfg.type,
  173. data: data,
  174. dataType: 'json',
  175. // xhrFields: {
  176. // withCredentials: true // 携带跨域cookie
  177. // },
  178. // crossDomain: true,
  179. beforeSend: function(xhr) {
  180. xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
  181. // 追加token
  182. if(localStorage.tokenName) {
  183. xhr.setRequestHeader(localStorage.tokenName, localStorage.tokenValue);
  184. }
  185. },
  186. success: function(res){
  187. console.log('返回数据:', res);
  188. setTimeout(function() {
  189. sa.hideLoading();
  190. // 如果相应的处理函数存在
  191. if(cfg['success' + res.code] != undefined) {
  192. return cfg['success' + res.code](res);
  193. }
  194. layer.alert('未知状态码:' + JSON.stringify(res));
  195. }, cfg.sleep);
  196. },
  197. error: function(xhr, type, errorThrown){
  198. setTimeout(function() {
  199. sa.hideLoading();
  200. return cfg.errorfn(xhr, type, errorThrown);
  201. }, cfg.sleep);
  202. },
  203. complete: cfg.complete
  204. });
  205. };
  206. // 模拟一个ajax
  207. // 请注意: 本模板中所有ajax请求调用的均为此模拟函数
  208. sa.ajax2 = function(url, data, success200, cfg){
  209. // 如果是简写模式(省略了data参数)
  210. if(typeof data === 'function'){
  211. cfg = success200;
  212. success200 = data;
  213. data = {};
  214. }
  215. // 几个默认配置
  216. cfg = cfg || {};
  217. cfg.baseUrl = (url.indexOf('http') === 0 ? '' : sa.cfg.api_url); // 父url,拼接在url前面
  218. // 设定一个默认的提示文字
  219. if(cfg.msg == undefined || cfg.msg == null || cfg.msg == '') {
  220. cfg.msg = '正在努力加载...';
  221. }
  222. // 默认延时函数
  223. if(cfg.sleep == undefined || cfg.sleep == null || cfg.sleep == '' || cfg.sleep == 0) {
  224. cfg.sleep = 600;
  225. }
  226. // 默认的模拟数据
  227. cfg.res = cfg.res || {
  228. code: 200,
  229. msg: 'ok',
  230. data: []
  231. }
  232. // 开始loding
  233. sa.loading(cfg.msg);
  234. // 打印请求地址和参数, 以便调试
  235. console.log("======= 模拟ajax =======");
  236. console.log("请求地址:" + cfg.baseUrl + url);
  237. console.log("请求参数:" + JSON.stringify(data));
  238. // 模拟ajax的延时
  239. setTimeout(function() {
  240. sa.hideLoading(); // 隐藏掉转圈圈
  241. console.log('返回数据:', cfg.res);
  242. success200(cfg.res);
  243. }, cfg.sleep)
  244. };
  245. })();
  246. // =========================== 封装弹窗相关函数 =======================================
  247. (function() {
  248. var me = sa;
  249. if(window.layer) {
  250. layer.ready(function(){});
  251. }
  252. // tips提示文字
  253. me.msg = function(msg, cfg) {
  254. msg = msg || '操作成功';
  255. layer.msg(msg, cfg);
  256. };
  257. // 操作成功的提示
  258. me.ok = function(msg) {
  259. msg = msg || '操作成功';
  260. layer.msg(msg, {anim: 0, icon: 1 });
  261. }
  262. me.ok2 = function(msg) {
  263. msg = msg || '操作成功';
  264. layer.msg(msg, {anim: 0, icon: 6 });
  265. }
  266. // 操作失败的提示
  267. me.error = function(msg) {
  268. msg = msg || '操作失败';
  269. layer.msg(msg, {anim: 6, icon: 2 });
  270. }
  271. me.error2 = function(msg) {
  272. msg = msg || '操作失败';
  273. layer.msg(msg, {anim: 6, icon: 5 });
  274. }
  275. // alert弹窗 [text=提示文字, okFn=点击确定之后的回调函数]
  276. me.alert = function(text, okFn) {
  277. // 开始弹窗
  278. layer.alert(text, function(index) {
  279. layer.close(index);
  280. if(okFn) {
  281. okFn();
  282. }
  283. });
  284. };
  285. // 询问框 [text=提示文字, okFn=点击确定之后的回调函数]
  286. me.confirm = function(text, okFn) {
  287. layer.confirm(text, {}, function(index) {
  288. layer.close(index);
  289. if(okFn) {
  290. okFn();
  291. }
  292. }.bind(this));
  293. };
  294. // 输入框 [title=提示文字, okFn=点击确定后的回调函数, formType=输入框类型(0=文本,1=密码,2=多行文本域) 可省略, value=默认值 可省略 ]
  295. me.prompt = function(title, okFn, formType, value) {
  296. layer.prompt({
  297. title: title,
  298. formType: formType,
  299. value: value
  300. }, function(pass, index){
  301. layer.close(index);
  302. if(okFn) {
  303. okFn(pass);
  304. }
  305. });
  306. }
  307. // 打开loading
  308. me.loading = function(msg) {
  309. layer.closeAll(); // 开始前先把所有弹窗关了
  310. return layer.msg(msg, {icon: 16, shade: 0.3, time: 1000 * 20, skin: 'ajax-layer-load' });
  311. };
  312. // 隐藏loading
  313. me.hideLoading = function() {
  314. layer.closeAll();
  315. };
  316. // ============== 一些常用弹窗 =====================
  317. // 大窗显示一个图片
  318. // 参数: src=地址、w=宽度(默认80%)、h=高度(默认80%)
  319. me.showImage = function(src, w, h) {
  320. w = w || '80%';
  321. h = h || '80%';
  322. var content = '<div style="height: 100%; overflow: hidden !important;">' +
  323. '<img src="' + src + ' " style="width: 100%; height: 100%;" />' +
  324. '</div>';
  325. layer.open({
  326. type: 1,
  327. title: false,
  328. shadeClose: true,
  329. closeBtn: 0,
  330. area: [w, h], //宽高
  331. content: content
  332. });
  333. }
  334. // 预览一组图片
  335. // srcList=图片路径数组(可以是json样,也可以是逗号切割式), index=打开立即显示哪张(可填下标, 也可填写src路径)
  336. me.showImageList = function(srcList, index) {
  337. // 如果填的是个string
  338. srcList = srcList || [];
  339. if(typeof srcList === 'string') {
  340. try{
  341. srcList = JSON.parse(srcList);
  342. }catch(e){
  343. try{
  344. srcList = srcList.split(','); // 尝试字符串切割
  345. }catch(e){
  346. srcList = [];
  347. }
  348. }
  349. }
  350. // 如果填的是路径
  351. index = index || 0;
  352. if(typeof index === 'string') {
  353. index = srcList.indexOf(index);
  354. index = (index == -1 ? 0 : index);
  355. }
  356. // 开始展示
  357. var arr_list = [];
  358. srcList.forEach(function(item) {
  359. arr_list.push({
  360. alt: '左右键切换',
  361. pid: 1,
  362. src: item,
  363. thumb: item
  364. })
  365. })
  366. layer.photos({
  367. photos: {
  368. title: '',
  369. id: new Date().getTime(),
  370. start: index,
  371. data: arr_list
  372. }
  373. ,anim: 5 //0-6的选择,指定弹出图片动画类型,默认随机(请注意,3.0之前的版本用shift参数)
  374. });
  375. }
  376. // 显示一个iframe
  377. // 参数: 标题,地址,宽,高 , 点击遮罩是否关闭, 默认false
  378. me.showIframe = function(title, url, w, h, shadeClose) {
  379. // 参数修正
  380. w = w || '95%';
  381. h = h || '95%';
  382. shadeClose = (shadeClose === undefined ? false : shadeClose);
  383. // 弹出面板
  384. var index = layer.open({
  385. type: 2,
  386. title: title, // 标题
  387. shadeClose: shadeClose, // 是否点击遮罩关闭
  388. maxmin: true, // 显示最大化按钮
  389. shade: 0.8, // 遮罩透明度
  390. scrollbar: false, // 屏蔽掉外层的滚动条
  391. moveOut: true, // 是否可拖动到外面
  392. area: [w, h], // 大小
  393. content: url, // 传值
  394. // 解决拉伸或者最大化的时候,iframe高度不能自适应的问题
  395. resizing: function(layero) {
  396. solveLayerBug(index);
  397. }
  398. });
  399. // 解决拉伸或者最大化的时候,iframe高度不能自适应的问题
  400. $('#layui-layer' + index + ' .layui-layer-max').click(function() {
  401. setTimeout(function() {
  402. solveLayerBug(index);
  403. }, 200)
  404. })
  405. }
  406. me.showView = me.showIframe;
  407. // 显示一个iframe, 底部按钮方式
  408. // 参数: 标题,地址,点击确定按钮执行的代码(在子窗口执行),宽,高
  409. me.showIframe2 = function(title, url, evalStr, w, h) {
  410. // 参数修正
  411. w = w || '95%';
  412. h = h || '95%';
  413. // 弹出面板
  414. var index = layer.open({
  415. type: 2,
  416. title: title, // 标题
  417. closeBtn: (title ? 1 : 0), // 是否显示关闭按钮
  418. btn: ['确定', '取消'],
  419. shadeClose: false, // 是否点击遮罩关闭
  420. maxmin: true, // 显示最大化按钮
  421. shade: 0.8, // 遮罩透明度
  422. scrollbar: false, // 屏蔽掉外层的滚动条
  423. moveOut: true, // 是否可拖动到外面
  424. area: [w, h], // 大小
  425. content: url, // 传值
  426. // 解决拉伸或者最大化的时候,iframe高度不能自适应的问题
  427. resizing: function(layero) {
  428. },
  429. yes: function(index, layero) {
  430. var iframe = document.getElementById('layui-layer-iframe' + index);
  431. var iframeWindow = iframe.contentWindow;
  432. iframeWindow.eval(evalStr);
  433. }
  434. });
  435. }
  436. // 当前iframe关闭自身 (在iframe中调用)
  437. me.closeCurrIframe = function() {
  438. try{
  439. var index = parent.layer.getFrameIndex(window.name); //先得到当前iframe层的索引
  440. parent.layer.close(index); //再执行关闭
  441. }catch(e){
  442. //TODO handle the exception
  443. }
  444. }
  445. me.closeCurrView = me.closeCurrIframe;
  446. //执行一个函数, 解决layer拉伸或者最大化的时候,iframe高度不能自适应的问题
  447. function solveLayerBug(index) {
  448. var selected = '#layui-layer' + index;
  449. var height = $(selected).height();
  450. var title_height = $(selected).find('.layui-layer-title').height();
  451. $(selected).find('iframe').css('height', (height - title_height) + 'px');
  452. }
  453. // 监听回车事件,达到回车关闭弹窗的效果
  454. if(window.$) {
  455. $(document).on('keydown', function() {
  456. if(event.keyCode === 13 && $(".layui-layer-btn0").length == 1 && !window.is_not_watch_enter && $(this).find('.layui-layer-input').length == 0){
  457. $(".layui-layer-btn0").click();
  458. return false;
  459. }
  460. });
  461. }
  462. })();
  463. // =========================== 常用util函数封装 =======================================
  464. (function () {
  465. // 超级对象
  466. var me = sa;
  467. // =========================== 常用util函数封装 =======================================
  468. if(true) {
  469. // 从url中查询到指定参数值
  470. me.p = function(name, defaultValue){
  471. var query = window.location.search.substring(1);
  472. var vars = query.split("&");
  473. for (var i=0;i<vars.length;i++) {
  474. var pair = vars[i].split("=");
  475. if(pair[0] == name){return pair[1];}
  476. }
  477. return(defaultValue == undefined ? null : defaultValue);
  478. }
  479. me.q = function(name, defaultValue){
  480. var query = window.location.search.substring(1);
  481. var vars = query.split("&");
  482. for (var i=0;i<vars.length;i++) {
  483. var pair = vars[i].split("=");
  484. if(pair[0] == name){return pair[1];}
  485. }
  486. return(defaultValue == undefined ? null : defaultValue);
  487. }
  488. // 判断一个变量是否为null
  489. // 返回true或false,如果return_obj有值,则在true的情况下返回return_obj
  490. me.isNull = function(obj, return_obj){
  491. var flag = [null, undefined, '', 'null', 'undefined'].indexOf(obj) != -1;
  492. if(return_obj === undefined){
  493. return flag;
  494. } else {
  495. if(flag){
  496. return return_obj;
  497. } else {
  498. return obj;
  499. }
  500. }
  501. }
  502. // 将时间戳转化为指定时间
  503. // way:方式(1=年月日,2=年月日时分秒)默认1, 也可以指定格式:yyyy-MM-dd HH:mm:ss
  504. me.forDate = function(inputTime, way) {
  505. if(me.isNull(inputTime) == true){
  506. return "";
  507. }
  508. var date = new Date(inputTime);
  509. var y = date.getFullYear();
  510. var m = date.getMonth() + 1;
  511. m = m < 10 ? ('0' + m) : m;
  512. var d = date.getDate();
  513. d = d < 10 ? ('0' + d) : d;
  514. var h = date.getHours();
  515. h = h < 10 ? ('0' + h) : h;
  516. var minute = date.getMinutes();
  517. var second = date.getSeconds();
  518. minute = minute < 10 ? ('0' + minute) : minute;
  519. second = second < 10 ? ('0' + second) : second;
  520. var ms = date.getMilliseconds();
  521. way = way || 1;
  522. // way == 1 年月日
  523. if(way === 1) {
  524. return y + '-' + m + '-' + d;
  525. }
  526. // way == 1 年月日时分秒
  527. if(way === 2){
  528. return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
  529. }
  530. // way == 具体格式 标准格式: yyyy-MM-dd HH:mm:ss
  531. if(typeof way == 'string') {
  532. return way.replace("yyyy", y).replace("MM", m).replace("dd", d).replace("HH", h).replace("mm", minute).replace("ss", second).replace("ms", ms);
  533. }
  534. return y + '-' + m + '-' + d;
  535. };
  536. // 时间日期
  537. me.forDatetime = function(inputTime) {
  538. return me.forDate(inputTime, 2);
  539. }
  540. // 将时间转化为 个性化 如:3小时前,
  541. // d1 之于 d2 ,d2不填则默认取当前时间
  542. me.forDate2 = function(d, d2){
  543. var hou = "前";
  544. if(d == null || d == '') {
  545. return '';
  546. }
  547. if(d2 == null || d2 == '') {
  548. d2 = new Date();
  549. }
  550. d2 = new Date(d2).getTime();
  551. var timestamp = new Date(d).getTime() - 1000;
  552. var mistiming = Math.round((d2 - timestamp) / 1000);
  553. if(mistiming < 0) {
  554. mistiming = 0 - mistiming;
  555. hou = '后'
  556. }
  557. var arrr = ['年', '月', '周', '天', '小时', '分钟', '秒'];
  558. var arrn = [31536000, 2592000, 604800, 86400, 3600, 60, 1];
  559. for (var i = 0; i < arrn.length; i++) {
  560. var inm = Math.floor(mistiming / arrn[i]);
  561. if (inm != 0) {
  562. return inm + arrr[i] + hou;
  563. }
  564. }
  565. }
  566. // 综合以上两种方式,进行格式化
  567. // 小于24小时的走forDate2,否则forDat
  568. me.forDate3 = function(d, way) {
  569. if(d == null || d == '' ) {
  570. return '';
  571. }
  572. var cha = new Date().getTime() - new Date(d).getTime();
  573. cha = (cha > 0 ? cha : 0 - cha);
  574. if(cha < (86400 * 1000)) {
  575. return me.forDate2(d);
  576. }
  577. return me.forDate(d, way);
  578. }
  579. // 返回时间差, 此格式数组:[x, x, x, 天, 时, 分, 秒]
  580. me.getSJC = function (small_time, big_time) {
  581. var date1 = new Date(small_time); //开始时间
  582. var date2 = new Date(big_time); //结束时间
  583. var date3 = date2.getTime() - date1.getTime(); //时间差秒
  584. //计算出相差天数
  585. var days = Math.floor(date3 / (24 * 3600 * 1000));
  586. //计算出小时数
  587. var leave1 = date3 % (24 * 3600 * 1000); //计算天数后剩余的毫秒数
  588. var hours = Math.floor(leave1 / (3600 * 1000));
  589. //计算相差分钟数
  590. var leave2 = leave1 % (3600 * 1000); //计算小时数后剩余的毫秒数
  591. var minutes = Math.floor(leave2 / (60 * 1000));
  592. //计算相差秒数
  593. var leave3 = leave2 % (60 * 1000); //计算分钟数后剩余的毫秒数
  594. var seconds = Math.round(leave3 / 1000);
  595. // 返回数组
  596. return [0, 0, 0, days, hours, minutes, seconds];
  597. }
  598. // 将日期,加上指定天数
  599. me.dateAdd = function(d, n) {
  600. var s = new Date(d).getTime();
  601. s += 86400000 * n;
  602. return new Date(s);
  603. }
  604. // 转化json,出错返回默认值
  605. me.JSONParse = function(obj, default_obj){
  606. try{
  607. return JSON.parse(obj) || default_obj;
  608. }catch(e){
  609. return default_obj || {};
  610. }
  611. }
  612. // 截取指定长度字符,默认50
  613. me.maxLength = function (str, length) {
  614. length = length || 50;
  615. if(!str){
  616. return "";
  617. }
  618. return (str.length > length) ? str.substr(0, length) + ' ...' : str;
  619. },
  620. // 过滤掉标签
  621. me.text = function(str){
  622. if(!str){
  623. return "";
  624. }
  625. return str.replace(/<[^>]+>/g,"");
  626. }
  627. // 为指定集合的每一项元素添加上is_update属性
  628. me.listAU = function(list){
  629. list.forEach(function(ts){
  630. ts.is_update = false;
  631. })
  632. return list;
  633. }
  634. // 获得一段文字中所有图片的路径
  635. me.getSrcList = function(str){
  636. try{
  637. var imgReg = /<img.*?(?:>|\/>)/gi; //匹配图片(g表示匹配所有结果i表示区分大小写)
  638. var srcReg = /src=[\'\"]?([^\'\"]*)[\'\"]?/i; //匹配src属性
  639. var arr = str.match(imgReg); // 图片数组
  640. var srcList = [];
  641. for (var i = 0; i < arr.length; i++) {
  642. var src = arr[i].match(srcReg);
  643. srcList.push(src[1]);
  644. }
  645. return srcList;
  646. } catch (e){
  647. return [];
  648. }
  649. }
  650. // 无精度损失的乘法
  651. me.accMul = function(arg1, arg2) {
  652. var m = 0,
  653. s1 = arg1.toString(),
  654. s2 = arg2.toString(),
  655. t;
  656. t = s1.split(".");
  657. // 判断有没有小数位,避免出错
  658. if (t[1]) {
  659. m += t[1].length
  660. }
  661. t = s2.split(".");
  662. if (t[1]) {
  663. m += t[1].length
  664. }
  665. return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
  666. }
  667. // 正则验证是否为手机号
  668. me.isPhone = function(str) {
  669. str = str + '';
  670. if((/^1[34578]\d{9}$/.test(str))){
  671. return true;
  672. }
  673. return false;
  674. }
  675. me.isNum = function(str) {
  676. str = str + '';
  677. if((/^[0-9]*$/.test(str))||(/^[0-9]+(.[0-9]{1})?$/.test(str))){
  678. return true;
  679. }
  680. return false;
  681. }
  682. // 产生随机字符串
  683. me.randomString = function(len) {
  684.   len = len || 32;
  685.   var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
  686.   var maxPos = $chars.length;
  687.   var str = '';
  688.   for (i = 0; i < len; i++) {
  689.     str += $chars.charAt(Math.floor(Math.random() * maxPos));
  690.   }
  691.   return str;
  692. }
  693. // 刷新页面
  694. me.f5 = function() {
  695. location.reload();
  696. }
  697. // 动态加载js
  698. me.loadJS = function(src, onload) {
  699. var script = document.createElement("script");
  700. script.setAttribute("type", "text/javascript");
  701. script.src = src;
  702. script.onload = onload;
  703. document.body.appendChild(script);
  704. }
  705. // 产生随机数字
  706. me.randomNum = function(min, max) {
  707. return parseInt(Math.random() * (max - min + 1) + min, 10);
  708. }
  709. // 打开页面
  710. me.open = function(url) {
  711. window.open(url);
  712. }
  713. // == if 结束
  714. }
  715. // =========================== 数组操作 =======================================
  716. if (true) {
  717. // 从数组里获取数据,根据指定数据
  718. me.getArrayField = function(arr, prop){
  719. var propArr = [];
  720. for (var i = 0; i < arr.length; i++) {
  721. propArr.push(arr[i][prop]);
  722. }
  723. return propArr;
  724. }
  725. // 从数组里获取数据,根据指定数据
  726. me.arrayGet = function(arr, prop, value){
  727. for (var i = 0; i < arr.length; i++) {
  728. if(arr[i][prop] == value){
  729. return arr[i];
  730. }
  731. }
  732. return null;
  733. }
  734. // 正则验证是否为手机号
  735. me.isPhone = function(str) {
  736. str = str + '';
  737. if ((/^1[3456789]\d{9}$/.test(str))) {
  738. return true;
  739. }
  740. return false;
  741. }
  742. // 从数组删除指定记录
  743. me.arrayDelete = function(arr, item){
  744. if(item instanceof Array) {
  745. for (let i = 0; i < item.length; i++) {
  746. let ite = item[i];
  747. let index = arr.indexOf(ite);
  748. if (index > -1) {
  749. arr.splice(index, 1);
  750. }
  751. }
  752. } else {
  753. var index = arr.indexOf(item);
  754. if (index > -1) {
  755. arr.splice(index, 1);
  756. }
  757. }
  758. }
  759. // 从数组删除指定id的记录
  760. me.arrayDeleteById = function(arr, id){
  761. var item = me.arrayGet(arr, 'id', id);
  762. me.arrayDelete(arr, item);
  763. }
  764. // 将数组B添加到数组A的开头
  765. me.unshiftArray = function(arrA, arrB){
  766. if(arrB){
  767. arrB.reverse().forEach(function(ts){
  768. arrA.unshift(ts);
  769. })
  770. }
  771. return arrA;
  772. }
  773. // 将数组B添加到数组A的末尾
  774. me.pushArray = function(arrA, arrB){
  775. if(arrB){
  776. arrB.forEach(function(ts){
  777. arrA.push(ts);
  778. })
  779. }
  780. return arrA;
  781. }
  782. // == if 结束
  783. }
  784. // =========================== 浏览器相关 =======================================
  785. if (true) {
  786. // set cookie 值
  787. me.setCookie = function setCookie(cname, cvalue, exdays) {
  788. exdays = exdays || 30;
  789. var d = new Date();
  790. d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
  791. var expires = "expires=" + d.toGMTString();
  792. document.cookie = cname + "=" + escape(cvalue) + "; " + expires + "; path=/";
  793. }
  794. // get cookie 值
  795. me.getCookie = function(objName){
  796. var arrStr = document.cookie.split("; ");
  797. for (var i = 0; i < arrStr.length; i++) {
  798. var temp = arrStr[i].split("=");
  799. if (temp[0] == objName){
  800. return unescape(temp[1])
  801. };
  802. }
  803. return "";
  804. }
  805. // 复制指定文本
  806. me.copyText = function(str){
  807. var oInput = document.createElement('input');
  808. oInput.value = str;
  809. document.body.appendChild(oInput);
  810. oInput.select(); // 选择对象
  811. document.execCommand("Copy"); // 执行浏览器复制命令
  812. oInput.className = 'oInput';
  813. oInput.style.display='none';
  814. }
  815. // jquery序列化表单增强版: 排除空值
  816. me.serializeNotNull = function(selected){
  817. var serStr = $(selected).serialize();
  818. return serStr.split("&").filter(function(str){return !str.endsWith("=")}).join("&");
  819. }
  820. // 将cookie序列化为k=v形式
  821. me.strCookie = function(){
  822. return document.cookie.replace(/; /g,"&");
  823. }
  824. // 回到顶部
  825. me.goTop = function() {
  826. function smoothscroll(){
  827. var currentScroll = document.documentElement.scrollTop || document.body.scrollTop;
  828. if (currentScroll > 0) {
  829. window.requestAnimationFrame(smoothscroll);
  830. window.scrollTo (0,currentScroll - (currentScroll/5));
  831. }
  832. };
  833. smoothscroll();
  834. }
  835. // == if 结束
  836. }
  837. // =========================== javascript对象操作 =======================================
  838. if (true) {
  839. // 去除json对象中的空值
  840. me.removeNull = function(obj){
  841. var newObj = {};
  842. if(obj != undefined && obj != null) {
  843. for(var key in obj) {
  844. if(obj[key] === undefined || obj[key] === null || obj[key] === '') {
  845. //
  846. } else {
  847. newObj[key] = obj[key];
  848. }
  849. }
  850. }
  851. return newObj;
  852. }
  853. // JSON 浅拷贝, 返回拷贝后的obj
  854. me.copyJSON = function(obj){
  855. if(obj === null || obj === undefined) {
  856. return obj;
  857. };
  858. var new_obj = {};
  859. for(var key in obj) {
  860. new_obj[key] = obj [key];
  861. }
  862. return new_obj;
  863. }
  864. // json合并, 将 defaulet配置项 转移到 user配置项里 并返回 user配置项
  865. me.extendJson = function(userOption, defaultOption) {
  866. if(!userOption) {
  867. return defaultOption;
  868. };
  869. for(var key in defaultOption) {
  870. if(userOption[key] === undefined) {
  871. userOption[key] = defaultOption[key];
  872. } else if(userOption[key] == null){
  873. } else if(typeof userOption[key] == "object") {
  874. me.extendJson(userOption[key], defaultOption[key]); //深度匹配
  875. }
  876. }
  877. return userOption;
  878. }
  879. // == if 结束
  880. }
  881. // =========================== 本地集合存储 =======================================
  882. if (true) {
  883. // 获取指定key的list
  884. me.keyListGet = function(key){
  885. try{
  886. var str = localStorage.getItem('LIST_' + key);
  887. if(str == undefined || str == null || str =='' || str == 'undefined' || typeof(JSON.parse(str)) == 'string'){
  888. //alert('key' + str);
  889. str = '[]';
  890. }
  891. return JSON.parse(str);
  892. }catch(e){
  893. return [];
  894. }
  895. },
  896. me.keyListSet = function(key, list){
  897. localStorage.setItem('LIST_' + key, JSON.stringify(list));
  898. },
  899. me.keyListHas = function(key, item){
  900. var arr2 = me.keyListGet(key);
  901. return arr2.indexOf(item) != -1;
  902. },
  903. me.keyListAdd = function(key, item){
  904. var arr = me.keyListGet(key);
  905. arr.push(item);
  906. me.keyListSet(key,arr);
  907. },
  908. me.keyListRemove = function(key, item){
  909. var arr = me.keyListGet(key);
  910. var index = arr.indexOf(item);
  911. if (index > -1) {
  912. arr.splice(index, 1);
  913. }
  914. me.keyListSet(key,arr);
  915. }
  916. // == if 结束
  917. }
  918. // =========================== 对sa-admin的优化 =======================================
  919. if (true) {
  920. // 封装element-ui的导出表格
  921. // 参数:选择器(默认.data-count),fileName=导出的文件名称
  922. me.exportExcel = function(select, fileName) {
  923. // 声明函数
  924. let exportExcel_fn = function(select, fileName) {
  925. // 赋默认值
  926. select = select || '.data-table';
  927. fileName = fileName || 'table.xlsx';
  928. // 开始导出
  929. let wb = XLSX.utils.table_to_book(document.querySelector(select)); // 这里就是表格
  930. let sheet = wb.Sheets.Sheet1; // 单元表
  931. try{
  932. // 强改宽度
  933. sheet['!cols'] = sheet['!cols'] || [];
  934. let thList = document.querySelector(select).querySelectorAll('.el-table__header-wrapper tr th');
  935. for (var i = 0; i < thList.length; i++) {
  936. // 如果是多选框
  937. if(thList[i].querySelector('.el-checkbox')) {
  938. sheet['!cols'].push({ wch: 5 }); // 强改宽度
  939. continue;
  940. }
  941. sheet['!cols'].push({ wch: 15 }); // 强改宽度
  942. }
  943. // 强改高度
  944. sheet['!rows'] = sheet['!rows'] || [];
  945. let trList = document.querySelector(select).querySelectorAll('.el-table__body-wrapper tbody tr');
  946. for (var i = 0; i < trList.length + 1; i++) {
  947. sheet['!rows'].push({ hpx: 20 }); // 强改高度
  948. }
  949. } catch(e) {
  950. console.err(e);
  951. }
  952. // 开始制作并输出
  953. let wbout = XLSX.write(wb, { bookType: 'xlsx', bookSST: true, type: 'array' });
  954. // 点击
  955. let blob = new Blob([wbout], { type: 'application/octet-stream'});
  956. const a= document.createElement("a")
  957. a.href = URL.createObjectURL(blob)
  958. a.download = fileName // 这里填保存成的文件名
  959. a.click()
  960. URL.revokeObjectURL(a.href)
  961. a.remove();
  962. sa.hideLoading();
  963. }
  964. sa.loading('正在导出...');
  965. // 判断是否首次加载
  966. if(window.XLSX) {
  967. return exportExcel_fn(select, fileName);
  968. } else {
  969. me.loadJS('https://unpkg.com/xlsx@0.16.6/dist/xlsx.core.min.js', function() {
  970. return exportExcel_fn(select, fileName);
  971. });
  972. }
  973. }
  974. // 刷新表格高度, 请务必在所有表格高度发生变化的地方调用此方法
  975. me.f5TableHeight = function() {
  976. Vue.nextTick(function() {
  977. if($('.el-table.data-table .el-table__body-wrapper table').length == 0) {
  978. return;
  979. }
  980. var _f5Height = function() {
  981. var height = $('.el-table .el-table__body-wrapper table').height();
  982. height = height == 0 ? 60 : height;
  983. // 判断是否有滚动条
  984. var tw = $('.el-table .el-table__body-wrapper').get(0);
  985. if(tw.scrollWidth > tw.clientWidth) {
  986. height = height + 16;
  987. }
  988. if($('.el-table .el-table__body-wrapper table td').width() == 0) {
  989. return;
  990. }
  991. // 设置高度
  992. $('.el-table .el-table__body-wrapper').css('min-height', height);
  993. $('.el-table .el-table__body-wrapper').css('max-height', height);
  994. };
  995. setTimeout(_f5Height, 0)
  996. setTimeout(_f5Height, 200)
  997. })
  998. }
  999. // 在表格查询的页面,监听input回车事件,提交查询
  1000. me.onInputEnter = function(app) {
  1001. Vue.nextTick(function() {
  1002. app = app || window.app;
  1003. // document.querySelectorAll('.el-form input').forEach(function(item) {
  1004. // item.onkeydown = function(e) {
  1005. // var theEvent = e || window.event;
  1006. // var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
  1007. // if (code == 13) {
  1008. // app.p.pageNo = 1;
  1009. // app.f5();
  1010. // }
  1011. // }
  1012. // })
  1013. document.querySelectorAll('.el-form').forEach(function(item) {
  1014. item.onkeydown = function(e) {
  1015. var theEvent = e || window.event;
  1016. var code = theEvent.keyCode || theEvent.which || theEvent.charCode;
  1017. if (code == 13) {
  1018. var target = e.target||e.srcElement;
  1019. if(target.tagName.toLowerCase()=="input") {
  1020. app.p.pageNo = 1;
  1021. app.f5();
  1022. }
  1023. }
  1024. }
  1025. })
  1026. })
  1027. }
  1028. // 如果value为true,则抛出异常
  1029. me.check = function(value, errorMsg) {
  1030. if(value === true) {
  1031. throw {type: 'sa-error', msg: errorMsg};
  1032. }
  1033. }
  1034. // 如果value为null,则抛出异常
  1035. me.checkNull = function(value, errorMsg) {
  1036. if(me.isNull(value)) {
  1037. throw {type: 'sa-error', msg: errorMsg};
  1038. }
  1039. }
  1040. // 监听窗口变动
  1041. if(!window.onresize) {
  1042. window.onresize = function() {
  1043. try{
  1044. me.f5TableHeight();
  1045. }catch(e){
  1046. // console.log(e);
  1047. }
  1048. }
  1049. }
  1050. // 双击layer标题处全屏
  1051. if(window.$) {
  1052. $(document).on('mousedown', '.layui-layer-title', function(e) {
  1053. // console.log('单击中');
  1054. if(window.layer_title_last_click_time) {
  1055. var cz = new Date().getTime() - window.layer_title_last_click_time;
  1056. if(cz < 250) {
  1057. console.log('双击');
  1058. $(this).parent().find('.layui-layer-max').click();
  1059. }
  1060. }
  1061. window.layer_title_last_click_time = new Date().getTime();
  1062. })
  1063. }
  1064. // == if 结束
  1065. }
  1066. })();
  1067. // =========================== $sys 有关当前系统的方法 一般不能复制到别的项目中用 =======================================
  1068. (function(){
  1069. // 超级对象
  1070. var me = {};
  1071. sa.$sys = me;
  1072. // ======================= 登录相关 ============================
  1073. // 写入当前已登陆用户信息
  1074. me.setCurrUser = function(currUser){
  1075. localStorage.setItem('currUser', JSON.stringify(currUser));
  1076. }
  1077. // 获得当前已登陆用户信息
  1078. me.getCurrUser = function(){
  1079. var user = localStorage.getItem("currUser");
  1080. if(user == undefined || user == null || user == 'null' || user == '' || user == '{}' || user.length < 10){
  1081. user = {
  1082. id: '0',
  1083. username: '未登录'
  1084. }
  1085. }else{
  1086. user = JSON.parse(user);
  1087. }
  1088. return user;
  1089. }
  1090. // 如果未登录,则强制跳转到登录
  1091. me.checkLogin = function(not_login_url){
  1092. console.log(me.getCurrUser());
  1093. if(me.getCurrUser().id == 0) {
  1094. location.href= not_login_url || '../../login.html';
  1095. throw '未登录,请先登录';
  1096. }
  1097. }
  1098. // 同上, 只不过是以弹窗的形式显示未登录
  1099. me.checkLoginTs = function(not_login_url){
  1100. if(me.getCurrUser().id == 0) {
  1101. sa.$page.openLogin(not_login_url || '../../login.html');
  1102. throw '未登录,请先登录';
  1103. }
  1104. }
  1105. // ========================= 权限验证 =========================
  1106. // 定义key
  1107. var pcode_key = 'permission_code';
  1108. // 写入当前会话的权限码集合
  1109. sa.setAuth = function(codeList) {
  1110. sa.keyListSet(pcode_key, codeList);
  1111. }
  1112. // 清除当前会话的权限码集合
  1113. sa.clearAuth = function() {
  1114. sa.keyListSet(pcode_key, []);
  1115. }
  1116. // 检查当前会话是否拥有一个权限码, 返回true和false
  1117. sa.isAuth = function(pcode) {
  1118. return sa.keyListHas(pcode_key, pcode);
  1119. }
  1120. // 检查当前会话是否拥有一个权限码, 如果没有, 则跳转到无权限页面
  1121. // 注意: 非二级目录页面请注意调整路径问题
  1122. sa.checkAuth = function(pcode, not_pcode_url) {
  1123. var is_have = sa.keyListHas(pcode_key, pcode);
  1124. if(is_have == false) {
  1125. location.href= not_pcode_url || '../../sa-view/error-page/403.html';
  1126. throw '暂无权限: ' + pcode;
  1127. }
  1128. }
  1129. // 同上, 只不过是以弹窗的形式显示出来无权限来
  1130. sa.checkAuthTs = function(pcode, not_pcode_url) {
  1131. var is_have = sa.keyListHas(pcode_key, pcode);
  1132. if(is_have == false) {
  1133. var url = not_pcode_url || '../../sa-view/error-page/403.html';
  1134. layer.open({
  1135. type: 2,
  1136. title: false, // 标题
  1137. shadeClose: true, // 是否点击遮罩关闭
  1138. shade: 0.8, // 遮罩透明度
  1139. scrollbar: false, // 屏蔽掉外层的滚动条
  1140. closeBtn: false,
  1141. area: ['700px', '600px'], // 大小
  1142. content: url // 传值
  1143. });
  1144. throw '暂无权限: ' + pcode;
  1145. }
  1146. }
  1147. // ======================= 配置相关 ============================
  1148. // 写入配置信息
  1149. me.setAppCfg = function(cfg) {
  1150. if(typeof cfg != 'string') {
  1151. cfg = JSON.stringify(cfg);
  1152. }
  1153. localStorage.setItem('app_cfg', cfg);
  1154. }
  1155. // 获取配置信息
  1156. me.getAppCfg = function() {
  1157. var app_cfg = sa.JSONParse(localStorage.getItem('app_cfg'), {}) || {};
  1158. return app_cfg;
  1159. }
  1160. })();
  1161. // =========================== $page 跳页面相关 避免一次变动,到处乱改 =======================================
  1162. (function(){
  1163. // 超级对象
  1164. var me={};
  1165. sa.$page = me;
  1166. // 打开登录页面
  1167. me.openLogin = function(login_url) {
  1168. layer.open({
  1169. type: 2,
  1170. // title: '登录',
  1171. title: false,
  1172. closeBtn: false,
  1173. shadeClose: true,
  1174. shade: 0.8,
  1175. // area: ['90%', '100%'],
  1176. area: ['70%', '80%'],
  1177. // area: ['450px', '360px'],
  1178. resize: false,
  1179. content: login_url || '../../login.html'
  1180. });
  1181. }
  1182. // 打开admin信息界面
  1183. me.openAdminInfo = function(id, username) {
  1184. var title = username + ' - 账号详情';
  1185. if(username === undefined) {
  1186. title = '账号详情';
  1187. }
  1188. sa.showIframe(title, '../sp-admin/admin-info.html?id=' + id, '700px', '600px');
  1189. }
  1190. })();
  1191. // 如果是sa_admin环境
  1192. window.sa_admin = window.sa_admin || parent.sa_admin || top.sa_admin;
  1193. window.saAdmin = window.sa_admin;
  1194. // 如果当前是Vue环境, 则挂在到 Vue 示例
  1195. if(window.Vue) {
  1196. // 全局的 sa 对象
  1197. Vue.prototype.sa = window.sa;
  1198. Vue.prototype.sa_admin = window.sa_admin;
  1199. Vue.prototype.saAdmin = window.saAdmin;
  1200. // 表单校验异常捕获
  1201. Vue.config.errorHandler = function(err, vm) {
  1202. if(err.type == 'sa-error') {
  1203. return sa.error(err.msg);
  1204. }
  1205. throw err;
  1206. }
  1207. // Element-UI 全局组件样式
  1208. Vue.prototype.$ELEMENT = { size: 'mini', zIndex: 3000 };
  1209. // 加载全局组件 (注意路径问题)
  1210. // if(window.httpVueLoader && window.loadComponent !== false) {
  1211. // Vue.component("sa-item", httpVueLoader('../../sa-frame/com/sa-item.vue'));
  1212. // Vue.component("sa-td", httpVueLoader('../../sa-frame/com/sa-td.vue'));
  1213. // }
  1214. }
  1215. // 对外开放, 在模块化时解开此注释
  1216. // export default sa;