gaoshuaixing 5 years ago
parent
commit
be06d62916
83 changed files with 1667 additions and 0 deletions
  1. 6 0
      app/config/openAuthConfig.js
  2. 0 0
      app/const/common.js
  3. 10 0
      app/const/statusCode.js
  4. 6 0
      app/const/storageKey.js
  5. 57 0
      app/controller/base.js
  6. 22 0
      app/controller/test.js
  7. 28 0
      app/controller/v1/home.js
  8. 30 0
      app/controller/v1/setting.js
  9. 35 0
      app/extend/context.js
  10. 4 0
      app/lang/en.json
  11. 0 0
      app/lang/zh.json
  12. 8 0
      app/middleware/auth.js
  13. 1 0
      app/public/css/app.21d9577f.css
  14. 1 0
      app/public/css/app.29e10f6d.css
  15. 1 0
      app/public/css/app.741d5958.css
  16. 1 0
      app/public/css/app.7c9ffc83.css
  17. 1 0
      app/public/css/app.f6364533.css
  18. 1 0
      app/public/css/chunk-0f66403b.30fa847d.css
  19. 1 0
      app/public/css/chunk-3ab52c00.4313a3b7.css
  20. 1 0
      app/public/css/chunk-5fdd2c15.60185def.css
  21. 1 0
      app/public/css/chunk-cffe18f0.57244086.css
  22. 7 0
      app/public/css/chunk-vendors.a1538f74.css
  23. BIN
      app/public/favicon.ico
  24. BIN
      app/public/images/loding.gif
  25. BIN
      app/public/img/logo.17365383.png
  26. 1 0
      app/public/index.html
  27. 0 0
      app/public/js/app.1f094f31.js
  28. 0 0
      app/public/js/app.1f094f31.js.map
  29. 0 0
      app/public/js/app.7e10f66c.js
  30. 0 0
      app/public/js/app.7e10f66c.js.map
  31. 0 0
      app/public/js/app.93c4a41c.js
  32. 0 0
      app/public/js/app.93c4a41c.js.map
  33. 0 0
      app/public/js/app.974b7a41.js
  34. 0 0
      app/public/js/app.974b7a41.js.map
  35. 0 0
      app/public/js/app.bbb302cb.js
  36. 0 0
      app/public/js/app.bbb302cb.js.map
  37. 2 0
      app/public/js/chunk-0f66403b.bbb1f5cb.js
  38. 0 0
      app/public/js/chunk-0f66403b.bbb1f5cb.js.map
  39. 2 0
      app/public/js/chunk-2d208e4d.42b6aba6.js
  40. 0 0
      app/public/js/chunk-2d208e4d.42b6aba6.js.map
  41. 2 0
      app/public/js/chunk-3ab52c00.26a04398.js
  42. 0 0
      app/public/js/chunk-3ab52c00.26a04398.js.map
  43. 2 0
      app/public/js/chunk-5fdd2c15.c1bf50ef.js
  44. 0 0
      app/public/js/chunk-5fdd2c15.c1bf50ef.js.map
  45. 2 0
      app/public/js/chunk-cffe18f0.46e400b9.js
  46. 0 0
      app/public/js/chunk-cffe18f0.46e400b9.js.map
  47. 4 0
      app/public/js/chunk-vendors.9ef31ed0.js
  48. 0 0
      app/public/js/chunk-vendors.9ef31ed0.js.map
  49. 4 0
      app/public/js/chunk-vendors.e06e2b79.js
  50. 0 0
      app/public/js/chunk-vendors.e06e2b79.js.map
  51. 22 0
      app/public/loading.html
  52. 20 0
      app/router/index.js
  53. 12 0
      app/router/setting.js
  54. 22 0
      app/schedule/test.js
  55. 38 0
      app/service/base.js
  56. 10 0
      app/service/setting.js
  57. 7 0
      app/service/test.js
  58. 228 0
      app/utils/index.js
  59. 12 0
      app/utils/regRule.js
  60. 501 0
      app/utils/utils.js
  61. 42 0
      app/utils/validataRules.js
  62. 11 0
      app/view/hello.ejs
  63. 1 0
      app/view/index.ejs
  64. 3 0
      frontend/.env
  65. 3 0
      frontend/.env.development
  66. 3 0
      frontend/.env.preview
  67. 23 0
      frontend/.gitignore
  68. 24 0
      frontend/README.md
  69. 5 0
      frontend/babel.config.js
  70. 50 0
      frontend/package.json
  71. BIN
      frontend/public/favicon.ico
  72. 17 0
      frontend/public/index.html
  73. 47 0
      frontend/src/App.vue
  74. BIN
      frontend/src/assets/logo.png
  75. 58 0
      frontend/src/components/HelloWorld.vue
  76. 17 0
      frontend/src/main.js
  77. 17 0
      frontend/src/router/index.js
  78. 35 0
      frontend/src/utils/axios.js
  79. 61 0
      frontend/src/utils/request.js
  80. 68 0
      frontend/src/utils/util.js
  81. 32 0
      frontend/src/views/Contenta.vue
  82. 32 0
      frontend/src/views/Contentb.vue
  83. 5 0
      frontend/vue.config.js

+ 6 - 0
app/config/openAuthConfig.js

@@ -0,0 +1,6 @@
+'use strict';
+module.exports = {
+  authInfo: {
+    key: 'Tsld2o4elg',
+  },
+};

+ 0 - 0
app/const/common.js


+ 10 - 0
app/const/statusCode.js

@@ -0,0 +1,10 @@
+'use strict';
+
+let StatusCode;
+(function(StatusCode) {
+  // 系统
+  StatusCode[(StatusCode.SUCCESS = 0)] = 'SUCCESS';
+  StatusCode[(StatusCode.SYS_API_ERROR = 10001)] = 'SYS_API_ERROR' // api错误
+})(StatusCode || (StatusCode = {}));
+
+module.exports = StatusCode;

+ 6 - 0
app/const/storageKey.js

@@ -0,0 +1,6 @@
+'use strict';
+
+module.exports = {
+  EGG_CONFIG: 'egg_config',
+  ELECTRON_IPC: 'electron_ipc',
+};

+ 57 - 0
app/controller/base.js

@@ -0,0 +1,57 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class BaseController extends Controller {
+  constructor(ctx) {
+    super(ctx);
+  }
+
+  /*
+   * return success
+   * @params: object data
+   * @params: string msg
+   * @return: object { success, code, msg, data }
+   */
+  sendSuccess(data, msg) {
+    const { ctx } = this;
+    ctx.body = {
+      success: true,
+      code: 0,
+      msg,
+      data,
+    };
+    ctx.status = 200;
+  }
+
+  /*
+   * return fail
+   * @params: object data
+   * @params: string msg
+   * @return: object { success, code, msg, data }
+   */
+  sendFail(data, msg, code) {
+    const { ctx } = this;
+    ctx.body = {
+      success: false,
+      code,
+      msg,
+      data,
+    };
+    ctx.status = 200;
+  }
+
+  /*
+   * return sendData
+   * @params: object data
+   * @params: string msg
+   * @return: object { success, code, msg, data }
+   */
+  sendData(data) {
+    const { ctx } = this;
+    ctx.body = data;
+    ctx.status = 200;
+  }
+}
+
+module.exports = BaseController;

+ 22 - 0
app/controller/test.js

@@ -0,0 +1,22 @@
+'use strict';
+
+const BaseController = require('./base');
+
+class TestController extends BaseController {
+  async index() {
+    const { app, ctx, service } = this;
+    const query = ctx.request.query;
+    console.log('env:%j', app.config.env);
+    const res = 0;
+    const data = {
+      env: app.config.env,
+    };
+
+
+
+    console.log('res:%j', res);
+    this.sendSuccess(data, 'ok');
+  }
+}
+
+module.exports = TestController;

+ 28 - 0
app/controller/v1/home.js

@@ -0,0 +1,28 @@
+'use strict';
+
+const BaseController = require('../base');
+
+class HomeController extends BaseController {
+
+  async index() {
+    const { ctx } = this;
+
+    const data = {
+      title: 'hello electron-egg'
+    };
+
+    await ctx.render('index.ejs', data);
+  }
+  
+  async hello() {
+    const { ctx } = this;
+
+    const data = {
+      title: 'hello'
+    };
+
+    await ctx.render('hello.ejs', data);
+  }
+}
+
+module.exports = HomeController;

+ 30 - 0
app/controller/v1/setting.js

@@ -0,0 +1,30 @@
+'use strict';
+
+const BaseController = require('../base');
+
+class SettingController extends BaseController {
+
+  async autoLaunchEnable() {
+    const self = this;
+    const { ctx } = this;
+
+    const data = {
+      title: 'hello electron-egg'
+    };
+
+    self.sendSuccess(data);
+  }
+  
+  async autoLaunchDisable() {
+    const self = this;
+    const { ctx } = this;
+
+    const data = {
+      title: 'hello'
+    };
+
+    self.sendSuccess(data);
+  }
+}
+
+module.exports = SettingController;

+ 35 - 0
app/extend/context.js

@@ -0,0 +1,35 @@
+/**
+ *
+ * @type {{foo(*)}}
+ */
+'use strict';
+module.exports = {
+  isMobile() {
+    const deviceAgent = this.get('user-agent').toLowerCase();
+    const agentID = deviceAgent.match(/(iphone|ipod|ipad|android)/);
+    if (agentID) {
+      // 手机访问
+      return true;
+    }
+    // 电脑访问
+    return false;
+  },
+  success(msg, data, total) {
+    this.body = {
+      success: true,
+      msg,
+      result: data,
+      total,
+    };
+  },
+  failure(msg, data) {
+    this.body = {
+      success: false,
+      msg,
+      result: data,
+    };
+  },
+  async infoPage(msg) {
+    await this.render('500', { msg });
+  },
+};

+ 4 - 0
app/lang/en.json

@@ -0,0 +1,4 @@
+{
+  "SUCCESS": "",
+  "SYS_API_ERROR": ""
+}

+ 0 - 0
app/lang/zh.json


+ 8 - 0
app/middleware/auth.js

@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = () => {
+  return async function auth(ctx, next) {
+
+    await next();
+  };
+};

+ 1 - 0
app/public/css/app.21d9577f.css

@@ -0,0 +1 @@
+#components-layout-demo-responsive .logo[data-v-30499a1c]{border-bottom:1px solid #e8e8e8}#components-layout-demo-responsive .pic-logo[data-v-30499a1c]{height:32px;margin:10px}#components-layout-demo-responsive .layout-sider[data-v-30499a1c]{border-right:1px solid #e8e8e8}#components-layout-demo-responsive .menu-item .ant-menu-item[data-v-30499a1c]{background-color:#fff;margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-layout-sider[data-v-30499a1c]{background-color:#fafafa}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-30499a1c]{margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-30499a1c]:after{border-right:3px solid #f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected[data-v-30499a1c]{background-color:#f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected span[data-v-30499a1c]{color:#111}#components-layout-demo-responsive .sub-menu-item.ant-menu[data-v-30499a1c]{background:#fafafa}#components-layout-demo-responsive .sub-menu-item.ant-menu-inline[data-v-30499a1c]{border-right:0 solid #fafafa}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}

+ 1 - 0
app/public/css/app.29e10f6d.css

@@ -0,0 +1 @@
+#components-layout-demo-responsive .logo[data-v-30499a1c]{border-bottom:1px solid #e8e8e8}#components-layout-demo-responsive .pic-logo[data-v-30499a1c]{height:32px;margin:10px}#components-layout-demo-responsive .layout-sider[data-v-30499a1c]{border-right:1px solid #e8e8e8}#components-layout-demo-responsive .menu-item .ant-menu-item[data-v-30499a1c]{background-color:#fff;margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-layout-sider[data-v-30499a1c]{background-color:#fafafa}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-30499a1c]{margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-30499a1c]:after{border-right:3px solid #f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected[data-v-30499a1c]{background-color:#f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected span[data-v-30499a1c]{color:#111}#components-layout-demo-responsive .sub-menu-item.ant-menu[data-v-30499a1c]{background:#fafafa}#components-layout-demo-responsive .sub-menu-item.ant-menu-inline[data-v-30499a1c]{border-right:0 solid #fafafa}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}

+ 1 - 0
app/public/css/app.741d5958.css

@@ -0,0 +1 @@
+#components-layout-demo-responsive .logo[data-v-4356d2f9]{border-bottom:1px solid #e8e8e8}#components-layout-demo-responsive .pic-logo[data-v-4356d2f9]{height:32px;margin:10px}#components-layout-demo-responsive .layout-sider[data-v-4356d2f9]{border-right:1px solid #e8e8e8}#components-layout-demo-responsive .menu-item .ant-menu-item[data-v-4356d2f9]{background-color:#fff;margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-layout-sider[data-v-4356d2f9]{background-color:#fafafa}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-4356d2f9]{margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-4356d2f9]:after{border-right:3px solid #f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected[data-v-4356d2f9]{background-color:#f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected span[data-v-4356d2f9]{color:#111}#components-layout-demo-responsive .sub-menu-item.ant-menu[data-v-4356d2f9]{background:#fafafa}#components-layout-demo-responsive .sub-menu-item.ant-menu-inline[data-v-4356d2f9]{border-right:0 solid #fafafa}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}

+ 1 - 0
app/public/css/app.7c9ffc83.css

@@ -0,0 +1 @@
+#components-layout-demo-responsive .logo[data-v-40511e1a]{border-bottom:1px solid #e8e8e8}#components-layout-demo-responsive .pic-logo[data-v-40511e1a]{height:32px;margin:10px}#components-layout-demo-responsive .layout-sider[data-v-40511e1a]{border-right:1px solid #e8e8e8}#components-layout-demo-responsive .menu-item .ant-menu-item[data-v-40511e1a]{background-color:#fff;margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-layout-sider[data-v-40511e1a]{background-color:#fafafa}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-40511e1a]{margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-40511e1a]:after{border-right:3px solid #f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected[data-v-40511e1a]{background-color:#f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected span[data-v-40511e1a]{color:#111}#components-layout-demo-responsive .sub-menu-item.ant-menu[data-v-40511e1a]{background:#fafafa}#components-layout-demo-responsive .sub-menu-item.ant-menu-inline[data-v-40511e1a]{border-right:0 solid #fafafa}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}

+ 1 - 0
app/public/css/app.f6364533.css

@@ -0,0 +1 @@
+#components-layout-demo-responsive .logo[data-v-3570f8b8]{height:32px;background:rgba(139,137,137,.2);margin:16px}#components-layout-demo-responsive .menu-item .ant-menu-item[data-v-3570f8b8]{background-color:#001529;margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-3570f8b8]{margin-top:0;margin-bottom:0}#components-layout-demo-responsive .sub-menu-item .ant-menu-item[data-v-3570f8b8]:after{border-right:3px solid #f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected[data-v-3570f8b8]{background-color:#f2f2f2}#components-layout-demo-responsive .sub-menu-item .ant-menu-item-selected span[data-v-3570f8b8]{color:#111}#components-layout-demo-responsive .sub-menu-item.ant-menu[data-v-3570f8b8]{background:#fafafa}#components-layout-demo-responsive .sub-menu-item.ant-menu-inline[data-v-3570f8b8]{border-right:0 solid #fafafa}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50}

+ 1 - 0
app/public/css/chunk-0f66403b.30fa847d.css

@@ -0,0 +1 @@
+h3[data-v-57391c39]{margin:40px 0 0}ul[data-v-57391c39]{list-style-type:none;padding:0}li[data-v-57391c39]{display:inline-block;margin:0 10px}a[data-v-57391c39]{color:#42b983}

+ 1 - 0
app/public/css/chunk-3ab52c00.4313a3b7.css

@@ -0,0 +1 @@
+h3[data-v-7a6676ea]{margin:40px 0 0}ul[data-v-7a6676ea]{list-style-type:none;padding:0}li[data-v-7a6676ea]{display:inline-block;margin:0 10px}a[data-v-7a6676ea]{color:#42b983}

+ 1 - 0
app/public/css/chunk-5fdd2c15.60185def.css

@@ -0,0 +1 @@
+h3[data-v-5c8a24e8]{margin:40px 0 0}ul[data-v-5c8a24e8]{list-style-type:none;padding:0}li[data-v-5c8a24e8]{display:inline-block;margin:0 10px}a[data-v-5c8a24e8]{color:#42b983}

+ 1 - 0
app/public/css/chunk-cffe18f0.57244086.css

@@ -0,0 +1 @@
+h3[data-v-1965c50a]{margin:40px 0 0}ul[data-v-1965c50a]{list-style-type:none;padding:0}li[data-v-1965c50a]{display:inline-block;margin:0 10px}a[data-v-1965c50a]{color:#42b983}

File diff suppressed because it is too large
+ 7 - 0
app/public/css/chunk-vendors.a1538f74.css


BIN
app/public/favicon.ico


BIN
app/public/images/loding.gif


BIN
app/public/img/logo.17365383.png


+ 1 - 0
app/public/index.html

@@ -0,0 +1 @@
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>electron-egg</title><link href="/js/chunk-2d208e4d.42b6aba6.js" rel="prefetch"><link href="/css/app.741d5958.css" rel="preload" as="style"><link href="/css/chunk-vendors.a1538f74.css" rel="preload" as="style"><link href="/js/app.1f094f31.js" rel="preload" as="script"><link href="/js/chunk-vendors.9ef31ed0.js" rel="preload" as="script"><link href="/css/chunk-vendors.a1538f74.css" rel="stylesheet"><link href="/css/app.741d5958.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but electron-egg doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.9ef31ed0.js"></script><script src="/js/app.1f094f31.js"></script></body></html>

File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.1f094f31.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.1f094f31.js.map


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.7e10f66c.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.7e10f66c.js.map


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.93c4a41c.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.93c4a41c.js.map


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.974b7a41.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.974b7a41.js.map


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.bbb302cb.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/app.bbb302cb.js.map


+ 2 - 0
app/public/js/chunk-0f66403b.bbb1f5cb.js

@@ -0,0 +1,2 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-0f66403b"],{"462e":function(e,n,t){"use strict";t.r(n);var c=function(){var e=this,n=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("div",{staticClass:"hello"},[t("h1",[e._v("这是首页内一")])])}],r={name:"HelloWorld",props:{msg:String}},l=r,a=(t("e0db"),t("2877")),i=Object(a["a"])(l,c,s,!1,null,"57391c39",null);n["default"]=i.exports},"4fca":function(e,n,t){},e0db:function(e,n,t){"use strict";t("4fca")}}]);
+//# sourceMappingURL=chunk-0f66403b.bbb1f5cb.js.map

File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-0f66403b.bbb1f5cb.js.map


+ 2 - 0
app/public/js/chunk-2d208e4d.42b6aba6.js

@@ -0,0 +1,2 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d208e4d"],{a778:function(t,n,e){"use strict";e.r(n);var o=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",[e("h3",{style:{marginBottom:"16px"}},[t._v(" demo 打开文件夹实现 ")]),e("a-list",{attrs:{bordered:"","data-source":t.data},scopedSlots:t._u([{key:"renderItem",fn:function(n){return e("a-list-item",{on:{click:function(e){return t.openDirectry(n.id)}}},[t._v(" "+t._s(n.content)+" "),e("a-button",{attrs:{type:"link"}},[t._v(" 打开 ")])],1)}}])})],1)},r=[],c=e("b775"),i={outApi:"/v1/outApi",openDir:"/v1/example/openLocalDir"};function a(t){return Object(c["b"])({url:i.openDir,method:"post",data:t})}var u=[{content:"【下载】目录",id:"download"},{content:"【图片】目录",id:"picture"},{content:"【文档】目录",id:"doc"},{content:"【音乐】目录",id:"music"}],d={data:function(){return{data:u}},methods:{openDirectry:function(t){console.log("id:",t);var n={id:t};a(n).then((function(t){if(0!==t.code)return!1})).catch((function(t){console.log("err:",t)}))}}},l=d,s=e("2877"),p=Object(s["a"])(l,o,r,!1,null,null,null);n["default"]=p.exports}}]);
+//# sourceMappingURL=chunk-2d208e4d.42b6aba6.js.map

File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-2d208e4d.42b6aba6.js.map


+ 2 - 0
app/public/js/chunk-3ab52c00.26a04398.js

@@ -0,0 +1,2 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-3ab52c00"],{"38e5":function(e,n,t){},3957:function(e,n,t){"use strict";t("38e5")},"9c7c":function(e,n,t){"use strict";t.r(n);var c=function(){var e=this,n=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("div",{staticClass:"hello"},[t("h1",[e._v("bbbbb")])])}],r={name:"HelloWorld",props:{msg:String}},a=r,l=(t("3957"),t("2877")),i=Object(l["a"])(a,c,s,!1,null,"7a6676ea",null);n["default"]=i.exports}}]);
+//# sourceMappingURL=chunk-3ab52c00.26a04398.js.map

File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-3ab52c00.26a04398.js.map


+ 2 - 0
app/public/js/chunk-5fdd2c15.c1bf50ef.js

@@ -0,0 +1,2 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-5fdd2c15"],{"6e4a":function(e,n,t){},"9c7c":function(e,n,t){"use strict";t.r(n);var c=function(){var e=this,n=e.$createElement;e._self._c;return e._m(0)},s=[function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("div",{staticClass:"hello"},[t("h1",[e._v("这是首页内二")])])}],r={name:"HelloWorld",props:{msg:String}},a=r,l=(t("f28f"),t("2877")),i=Object(l["a"])(a,c,s,!1,null,"5c8a24e8",null);n["default"]=i.exports},f28f:function(e,n,t){"use strict";t("6e4a")}}]);
+//# sourceMappingURL=chunk-5fdd2c15.c1bf50ef.js.map

File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-5fdd2c15.c1bf50ef.js.map


+ 2 - 0
app/public/js/chunk-cffe18f0.46e400b9.js

@@ -0,0 +1,2 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-cffe18f0"],{"462e":function(e,n,t){"use strict";t.r(n);var a=function(){var e=this,n=e.$createElement;e._self._c;return e._m(0)},c=[function(){var e=this,n=e.$createElement,t=e._self._c||n;return t("div",{staticClass:"hello"},[t("h1",[e._v("aaaaa")])])}],s={name:"HelloWorld",props:{msg:String}},r=s,l=(t("7873"),t("2877")),i=Object(l["a"])(r,a,c,!1,null,"1965c50a",null);n["default"]=i.exports},"6ebd":function(e,n,t){},7873:function(e,n,t){"use strict";t("6ebd")}}]);
+//# sourceMappingURL=chunk-cffe18f0.46e400b9.js.map

File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-cffe18f0.46e400b9.js.map


File diff suppressed because it is too large
+ 4 - 0
app/public/js/chunk-vendors.9ef31ed0.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-vendors.9ef31ed0.js.map


File diff suppressed because it is too large
+ 4 - 0
app/public/js/chunk-vendors.e06e2b79.js


File diff suppressed because it is too large
+ 0 - 0
app/public/js/chunk-vendors.e06e2b79.js.map


+ 22 - 0
app/public/loading.html

@@ -0,0 +1,22 @@
+<html>
+ <head> 
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
+  <style type="text/css">
+    body{
+      margin:0px auto;
+    }
+    #picture1 {
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+    }
+  </style> 
+  <title></title> 
+ </head> 
+ <body> 
+  <div id="picture1">
+   <img src="./images/loding.gif" />
+  </div>  
+ </body>
+</html>

+ 20 - 0
app/router/index.js

@@ -0,0 +1,20 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  // home
+  router.get('/', controller.v1.home.index);
+
+  // hello
+  //router.get('/', controller.v1.home.hello);
+
+  // html
+  router.get('/home', controller.v1.home.index);
+
+  // 引入其他路由
+  require('./example')(app);
+  require('./setting')(app);
+};

+ 12 - 0
app/router/setting.js

@@ -0,0 +1,12 @@
+'use strict';
+
+/**
+ * @param {Egg.Application} app - egg application
+ */
+module.exports = app => {
+  const { router, controller } = app;
+  // open launch
+  router.get('/api/v1/setting/autoLaunchEnable', controller.v1.setting.autoLaunchEnable);
+  // close launch 
+  router.get('/api/v1/setting/autoLaunchDisable', controller.v1.setting.autoLaunchDisable);
+};

+ 22 - 0
app/schedule/test.js

@@ -0,0 +1,22 @@
+'use strict';
+
+const Subscription = require('egg').Subscription;
+
+/**
+ * test
+ */
+
+class Test extends Subscription {
+  static get schedule() {
+    return {
+      interval: '360m',
+      type: 'worker',
+      immediate: false,
+      disable: true,
+    };
+  }
+
+  async subscribe() {}
+}
+
+module.exports = Test;

+ 38 - 0
app/service/base.js

@@ -0,0 +1,38 @@
+'use strict';
+
+const request = require('superagent');
+const Service = require('egg').Service;
+
+class BaseService extends Service {
+  /*
+   * ipc call
+   */
+  async ipcCall(method = '', ...params) {
+    let result = {
+      err: null,
+      data: null
+    };
+    if (!method) {
+      result.err = 'Method does not exist';
+      return result;
+    }
+
+    const port = this.service.storage.getElectronIPCPort();
+    const url  = 'localhost:' + port + '/send';
+    try {
+      const response = await request.post(url)
+        .send({ cmd: method, params: params })
+        .set('accept', 'json');
+        
+        result = JSON.parse(response.text);  
+    } catch (err) {
+      this.app.logger.error('[base] [ipcCall] request error:', err);
+      result.err = 'request err';
+    }
+    this.app.logger.info('[base] [ipcCall] result:', result);
+
+    return result;
+  }
+}
+
+module.exports = BaseService;

+ 10 - 0
app/service/setting.js

@@ -0,0 +1,10 @@
+'use strict';
+
+const BaseService = require('./base');
+
+class SettingService extends BaseService {
+
+    
+}
+
+module.exports = SettingService;

+ 7 - 0
app/service/test.js

@@ -0,0 +1,7 @@
+'use strict';
+
+const BaseService = require('./base');
+
+class TestService extends BaseService {}
+
+module.exports = TestService;

+ 228 - 0
app/utils/index.js

@@ -0,0 +1,228 @@
+'use strict';
+
+// MD5加密工具
+const crypto = require('crypto');
+// 使用crypto进行MD5加密
+const md5 = crypto.createHash('md5');
+
+/* 通用函数集合 */
+// UTC时间格式化成本地时间
+exports.formatUTC = UTCDateString => {
+  if (!UTCDateString) {
+    return '-';
+  }
+  // 格式化显示
+  function formatFunc(str) {
+    return str > 9 ? str : '0' + str;
+  }
+  // 这步是关键
+  const date2 = new Date(UTCDateString);
+  const year = date2.getFullYear();
+  const mon = formatFunc(date2.getMonth() + 1);
+  const day = formatFunc(date2.getDate());
+  const hour = date2.getHours();
+  const min = date2.getMinutes();
+  const second = date2.getSeconds();
+
+  const dateStr =
+    year + '-' + mon + '-' + day + ' ' + hour + ':' + min + ':' + second;
+  return dateStr;
+};
+// 生成8位数的uid
+exports.createNewUid = () => {
+  /* 生成8位随机整数,不能有4位连续数字,不能有4位重复数字 */
+  // 4位重复数字
+  // let reg1 = /\d{4}/;
+  const reg1 = /([\d])\1{3}/;
+  // 4位连续数字
+  const reg2 = /(0(?=1)|1(?=2)|2(?=3)|3(?=4)|4(?=5)|5(?=6)|6(?=7)|7(?=8)|8(?=9)|9(?=0)){3}|(?:0(?=9)|9(?=8)|8(?=7)|7(?=6)|6(?=5)|5(?=4)|4(?=3)|3(?=2)|2(?=1)|1(?=0)){3}/;
+  // const numStr1 = '10122229';
+  // const numStr2 = '78902100';
+  // console.log(`reg1 is ${reg1.test(numStr1)}`);
+  // console.log(`reg2 is ${reg2.test(numStr2)}`);
+
+  // 生成uid(随机20次应该能有1次满足条件)
+  let uid = null;
+  for (let i = 0; i < 20; i++) {
+    // 生成随机整数(范围11111111到19878711)
+    uid = String(parseInt(Math.random() * 8767600) + 11111111);
+    // console.log(`uid is ${uid}`)
+    // const uid = "89016530";
+    // console.log(`reg1 is ${reg1.test(uid)}`);
+    // console.log(`reg2 is ${reg2.test(uid)}`);
+    if (!reg1.test(uid) && !reg2.test(uid)) {
+      // console.log(`uid is 1111`)
+      return uid;
+    }
+  }
+};
+
+// 生成密码加密的盐slat(8位字符串)
+exports.saltPwd = () => {
+  let str = '';
+  const arr = [
+    '0',
+    '1',
+    '2',
+    '3',
+    '4',
+    '5',
+    '6',
+    '7',
+    '8',
+    '9',
+    'a',
+    'b',
+    'c',
+    'd',
+    'e',
+    'f',
+    'g',
+    'h',
+    'i',
+    'j',
+    'k',
+    'l',
+    'm',
+    'n',
+    'o',
+    'p',
+    'q',
+    'r',
+    's',
+    't',
+    'u',
+    'v',
+    'w',
+    'x',
+    'y',
+    'z',
+  ];
+
+  let pos = null;
+  for (let i = 0; i < 8; i++) {
+    pos = Math.round(Math.random() * (arr.length - 1));
+    str += arr[pos];
+  }
+  return str;
+};
+// 生成随机字符串(数字(0-9),字母(a-z,A-Z))
+exports.randomWord = (randomFlag, min, max) => {
+  let str = '';
+  let range = min;
+  const arr = [
+    '0',
+    '1',
+    '2',
+    '3',
+    '4',
+    '5',
+    '6',
+    '7',
+    '8',
+    '9',
+    'a',
+    'b',
+    'c',
+    'd',
+    'e',
+    'f',
+    'g',
+    'h',
+    'i',
+    'j',
+    'k',
+    'l',
+    'm',
+    'n',
+    'o',
+    'p',
+    'q',
+    'r',
+    's',
+    't',
+    'u',
+    'v',
+    'w',
+    'x',
+    'y',
+    'z',
+    'A',
+    'B',
+    'C',
+    'D',
+    'E',
+    'F',
+    'G',
+    'H',
+    'I',
+    'J',
+    'K',
+    'L',
+    'M',
+    'N',
+    'O',
+    'P',
+    'Q',
+    'R',
+    'S',
+    'T',
+    'U',
+    'V',
+    'W',
+    'X',
+    'Y',
+    'Z',
+  ];
+
+  // 随机产生
+  if (randomFlag) {
+    range = Math.round(Math.random() * (max - min)) + min;
+  }
+  let pos = null;
+  for (let i = 0; i < range; i++) {
+    pos = Math.round(Math.random() * (arr.length - 1));
+    str += arr[pos];
+  }
+  return str;
+  // 使用方法
+  // 生成3-32位随机串:randomWord(true, 3, 32)
+  // 生成43位随机串:randomWord(false, 43)
+};
+// 生成两数之间随机数
+exports.randomNums = (min, max) => {
+  return Math.round(Math.random() * (max - min) + min);
+};
+// 客户端密码加密
+exports.saltPwdMd5 = (password, saltPwd) => {
+  const md5 = crypto.createHash('md5');
+  // 加了盐的客户端密码
+  const saltPassword = password + ':' + saltPwd;
+  // 加盐的密码再用MD5加密
+  const saltPasswordMd5 = md5.update(saltPassword).digest('hex');
+  return saltPasswordMd5;
+};
+exports.createToken = data => {
+  // console.log(`data is ${JSON.stringify(data)}`);
+  const { uid, app } = data;
+  // 当前时间戳
+  const created = Math.floor(Date.now() / 1000);
+
+  const token = app.jwt.sign({ uid, created }, app.config.jwt.secret, {
+    expiresIn: '30d',
+  });
+
+  return token;
+};
+exports.createAdminToken = data => {
+  // console.log(`data is ${JSON.stringify(data)}`);
+  const { id, role, app } = data;
+  // 当前时间戳
+  const created = Math.floor(Date.now() / 1000);
+
+  const token = app.jwt.sign({ id, role, created }, app.config.jwt.secret, {
+    expiresIn: '30d',
+  });
+
+  return token;
+};

+ 12 - 0
app/utils/regRule.js

@@ -0,0 +1,12 @@
+// // 密码校验规则(32位字符串,既Md5加密后的)
+// const passwordReg1 = /^.{32}$/
+// // 手机号码校验规则
+// const phoneReg = /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/
+'use strict';
+
+const regRule = {
+  paswwordReg1: /^.{32}$/,
+  phoneReg: /^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\d{8}$/,
+  emailReg: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/,
+};
+module.exports = regRule;

+ 501 - 0
app/utils/utils.js

@@ -0,0 +1,501 @@
+'use strict';
+const util = require('util');
+const crypto = require('crypto');
+const fs = require('fs');
+const path = require('path');
+const _ = require('lodash');
+const readline = require('readline');
+const net = require('net');
+
+exports = module.exports;
+
+// control variable of func "myPrint"
+const isPrintFlag = true;
+
+/**
+ * Check and invoke callback function
+ */
+exports.invokeCallback = function(cb) {
+  if (!!cb && typeof cb === 'function') {
+    cb.apply(null, Array.prototype.slice.call(arguments, 1));
+  }
+};
+
+exports.size = function(obj) {
+  if (!obj) {
+    return 0;
+  }
+
+  let size = 0;
+  for (const f in obj) {
+    if (obj.hasOwnProperty(f)) {
+      size++;
+    }
+  }
+
+  return size;
+};
+
+// print the file name and the line number ~ begin
+function getStack() {
+  const orig = Error.prepareStackTrace;
+  Error.prepareStackTrace = function(_, stack) {
+    return stack;
+  };
+  const err = new Error();
+  Error.captureStackTrace(err, arguments.callee);
+  const stack = err.stack;
+  Error.prepareStackTrace = orig;
+  return stack;
+}
+
+function getFileName(stack) {
+  return stack[1].getFileName();
+}
+
+function getLineNumber(stack) {
+  return stack[1].getLineNumber();
+}
+
+exports.myPrint = function() {
+  if (isPrintFlag) {
+    const len = arguments.length;
+    if (len <= 0) {
+      return;
+    }
+    const stack = getStack();
+    let aimStr =
+      "'" + getFileName(stack) + "' @" + getLineNumber(stack) + ' :\n';
+    for (let i = 0; i < len; ++i) {
+      aimStr +=
+        (typeof arguments[i] === 'object'
+          ? JSON.stringify(arguments[i])
+          : arguments[i]) + ' ';
+    }
+    console.log('\n' + aimStr);
+  }
+};
+
+exports.md5 = function(str) {
+  const hash = crypto.createHash('md5');
+  hash.update(str);
+  return hash.digest('hex');
+};
+
+/*
+ * 加密
+ */
+exports.cipher = function(algorithm, key, iv, data) {
+  key = new Buffer(key);
+  iv = new Buffer(iv ? iv : 0);
+  const cipher = crypto.createCipheriv(algorithm, key, iv);
+  cipher.setAutoPadding(true); // default true
+  let ciph = cipher.update(data, 'utf8', 'base64');
+  ciph += cipher.final('base64');
+
+  return ciph;
+};
+
+/*
+ * 解密
+ */
+exports.decipher = function(algorithm, key, iv, crypted) {
+  key = new Buffer(key);
+  iv = new Buffer(iv ? iv : '');
+  const decipher = crypto.createDecipheriv(algorithm, key, iv);
+  decipher.setAutoPadding(true);
+  let decoded = decipher.update(crypted, 'base64', 'utf8');
+  decoded += decipher.final('utf8');
+
+  return decoded;
+};
+
+exports.getDate = function(flag) {
+  if (!flag) {
+    flag = '';
+  }
+  const date = new Date();
+  const year = date.getFullYear();
+  const month = date.getMonth() + 1;
+  const day = date.getDate();
+  const mytimes = year + flag + month + flag + day;
+  return mytimes;
+};
+
+exports.dynamicSign = function(len) {
+  len = len || 5;
+  const chars = 'abcdefghijklmnopqrstuvwxyz';
+  const maxPos = chars.length;
+  let sign = '';
+  for (let i = 0; i < len; i++) {
+    sign += chars.charAt(Math.floor(Math.random() * maxPos));
+  }
+  return sign;
+};
+
+exports.toHump = function(str) {
+  let result = '';
+  const split = str.split('_');
+  result += split[0];
+  for (let i = 1; i < split.length; ++i) {
+    result += split[i][0].toUpperCase() + split[i].substr(1);
+  }
+  return result;
+};
+
+exports.tryJsonParse = function(jsonStr, cb) {
+  try {
+    cb(null, JSON.parse(jsonStr));
+  } catch (e) {
+    cb(e, null);
+  }
+};
+
+exports.mkdir = function(dirpath, dirname) {
+  // 判断是否是第一次调用
+  if (typeof dirname === 'undefined') {
+    if (fs.existsSync(dirpath)) {
+      return;
+    }
+    this.mkdir(dirpath, path.dirname(dirpath));
+  } else {
+    // 判断第二个参数是否正常,避免调用时传入错误参数
+    if (dirname !== path.dirname(dirpath)) {
+      this.mkdir(dirpath);
+      return;
+    }
+    if (fs.existsSync(dirname)) {
+      fs.mkdirSync(dirpath);
+    } else {
+      this.mkdir(dirname, path.dirname(dirname));
+      fs.mkdirSync(dirpath);
+    }
+  }
+
+  console.log('==> dir end', dirpath);
+};
+
+/*
+ * 获取目录下指定后缀的所有文件
+ * @param dir
+ * @param ext
+ * @return {Array}
+ */
+exports.getAllFiles = function(dir, ext) {
+  if (!dir) {
+    return [];
+  }
+
+  const self = this;
+  let extFiles = [];
+
+  const files = fs.readdirSync(dir);
+  files.forEach(function(file) {
+    const pathname = path.join(dir, file);
+    const stat = fs.lstatSync(pathname);
+
+    if (stat.isDirectory()) {
+      extFiles = extFiles.concat(self.getAllFiles(pathname, ext));
+    } else if (path.extname(pathname) === ext) {
+      extFiles.push(pathname.replace(cwd, '.'));
+    }
+  });
+
+  return extFiles;
+};
+
+/*
+ * 获取目录下所有文件夹
+ */
+exports.getDirs = function(dir) {
+  if (!dir) {
+    return [];
+  }
+
+  const components = [];
+  const files = fs.readdirSync(dir);
+  files.forEach(function(item, index) {
+    const stat = fs.lstatSync(dir + '/' + item);
+    if (stat.isDirectory() === true) {
+      components.push(item);
+    }
+  });
+
+  return components;
+};
+
+exports.fileExist = function(filePath) {
+  try {
+    return fs.statSync(filePath).isFile();
+  } catch (err) {
+    return false;
+  }
+};
+
+exports.delDir = function(path) {
+  let files = [];
+  if (fs.existsSync(path)) {
+    files = fs.readdirSync(path);
+    files.forEach((file, index) => {
+      const curPath = path + '/' + file;
+      if (fs.statSync(curPath).isDirectory()) {
+        this.delDir(curPath); // 递归删除文件夹
+      } else {
+        fs.unlinkSync(curPath); // 删除文件
+      }
+    });
+    fs.rmdirSync(path);
+  }
+};
+
+exports.chmodPath = function(path, mode) {
+  let files = [];
+  if (fs.existsSync(path)) {
+    files = fs.readdirSync(path);
+    files.forEach((file, index) => {
+      const curPath = path + '/' + file;
+      if (fs.statSync(curPath).isDirectory()) {
+        this.chmodPath(curPath, mode); // 递归删除文件夹
+      } else {
+        fs.chmodSync(curPath, mode);
+      }
+    });
+    fs.chmodSync(path, mode);
+  }
+};
+
+/**
+ * 判断是否是同一天
+ * @param d1
+ * @param d2
+ * @return {boolean}
+ */
+exports.isSameDay = function(d1, d2) {
+  return (
+    d1.getFullYear() === d2.getFullYear() &&
+    d1.getMonth() === d2.getMonth() &&
+    d1.getDate() === d2.getDate()
+  );
+};
+
+/*
+ * 判断是否在有效期
+ */
+exports.isInDate = function(createDate, days) {
+  const diffDays = this.diffDays(createDate) + 1;
+  return diffDays <= days;
+};
+
+/*
+ * differ days
+ * 返回两个日期相隔的天数
+ * 按0点算
+ * 1日0点与2日0点相隔为1天
+ */
+exports.diffDays = function(createDate) {
+  const tmp = new Date();
+  tmp.setHours(0, 0, 0, 0);
+  createDate.setHours(0, 0, 0, 0);
+  return (tmp - createDate) / 24 / 3600000;
+};
+
+/*
+ * differ weeks
+ * 判断两个日期是否在同一周
+ * add by mumu
+ */
+exports.isSameWeek = function(old, now) {
+  const oneDayTime = 1000 * 60 * 60 * 24;
+  const old_count = parseInt(old.getTime() / oneDayTime);
+  const now_other = parseInt(now.getTime() / oneDayTime);
+  return parseInt((old_count + 4) / 7) == parseInt((now_other + 4) / 7);
+};
+
+/**
+ * 读取json文件并解析
+ * @param path
+ * @return {any}
+ */
+exports.loadJson = function(path) {
+  return JSON.parse(fs.readFileSync(path).toString());
+};
+
+exports.getRandomArrayElements = function(arr, count) {
+  let shuffled = arr.slice(0),
+    i = arr.length,
+    min = i - count,
+    temp,
+    index;
+  while (i-- > min) {
+    index = Math.floor((i + 1) * Math.random());
+    temp = shuffled[index];
+    shuffled[index] = shuffled[i];
+    shuffled[i] = temp;
+  }
+  return shuffled.slice(min);
+};
+
+exports.getTodayExpireTime = function() {
+  const endTime = new Date(new Date().setHours(23, 59, 59, 0)) / 1000;
+  const expiresTime = endTime - Math.floor(new Date().getTime() / 1000);
+  return expiresTime;
+};
+
+exports.objKeySort = function(obj) {
+  const newkey = Object.keys(obj).sort();
+  const newObj = {};
+  for (let i = 0; i < newkey.length; i++) {
+    newObj[newkey[i]] = obj[newkey[i]];
+  }
+  return newObj;
+};
+
+exports.serialize = function(obj) {
+  const str = [];
+  for (const p in obj) {
+    if (obj.hasOwnProperty(p)) {
+      str.push(p + '=' + obj[p]);
+    }
+  }
+  return str.join('&');
+};
+
+exports.keepTwoDecimalFull = function(num) {
+  let result = parseFloat(num);
+  if (isNaN(result)) {
+    return false;
+  }
+  result = Math.round(num * 100) / 100;
+  let s_x = result.toString();
+  let pos_decimal = s_x.indexOf('.');
+  if (pos_decimal < 0) {
+    pos_decimal = s_x.length;
+    s_x += '.';
+  }
+  while (s_x.length <= pos_decimal + 2) {
+    s_x += '0';
+  }
+  return s_x;
+};
+
+exports.sleep = function(time = 0) {
+  return new Promise((resolve, reject) => {
+    setTimeout(() => {
+      resolve();
+    }, time);
+  });
+};
+
+/*
+ * 按行读取文件内容
+ * 返回:字符串数组
+ * 参数:fReadName:文件名路径
+ */
+exports.readFileToArr = async function(fReadName) {
+  const fRead = fs.createReadStream(fReadName);
+  const objReadline = readline.createInterface({
+    input: fRead,
+  });
+
+  return new Promise((resolve, reject) => {
+    const arr = [];
+    objReadline.on('line', function(line) {
+      arr.push(line);
+    });
+    objReadline.on('close', function() {
+      resolve(arr);
+    });
+  });
+};
+
+exports.compareVersion = function(version, bigVersion) {
+  version = version.split('.');
+  bigVersion = bigVersion.split('.');
+  for (let i = 0; i < version.length; i++) {
+    version[i] = +version[i];
+    bigVersion[i] = +bigVersion[i];
+    if (version[i] > bigVersion[i]) {
+      return false;
+    } else if (version[i] < bigVersion[i]) {
+      return true;
+    }
+  }
+  return false;
+};
+
+exports.handleVersion = function(version) {
+  if (!version) return version;
+  version = version + '';
+  if (version[0] === 'v') {
+    return version.substr(1);
+  }
+  return version;
+};
+
+/*
+ * 获取本机IP地址
+ */
+exports.getIPAddress = function() {
+  const interfaces = require('os').networkInterfaces();
+  for (const devName in interfaces) {
+    const iface = interfaces[devName];
+    for (let i = 0; i < iface.length; i++) {
+      const alias = iface[i];
+      if (
+        alias.family === 'IPv4' &&
+        alias.address !== '127.0.0.1' &&
+        !alias.internal
+      ) {
+        return alias.address;
+      }
+    }
+  }
+};
+
+/*
+ * 判断IP是否在同一网段
+ */
+exports.isEqualIPAddress = function (addr1, addr2, mask = '255.255.255.0'){
+  if(!addr1 || !addr2 || !mask){
+    console.log("各参数不能为空");
+    return false;
+  }
+  var 
+  res1 = [],
+  res2 = [];
+  addr1 = addr1.split(".");
+  addr2 = addr2.split(".");
+  mask  = mask.split(".");
+  for(var i = 0,ilen = addr1.length; i < ilen ; i += 1){
+    res1.push(parseInt(addr1[i]) & parseInt(mask[i]));
+    res2.push(parseInt(addr2[i]) & parseInt(mask[i]));
+  }
+  if(res1.join(".") == res2.join(".")){
+    return true;
+  }else{
+    return false;
+  }
+}
+
+/*
+ * 端口是否被占用
+ */
+exports.portIsOccupied = function portIsOccupied(port) {
+  const server = net.createServer().listen(port, '0.0.0.0');
+  return new Promise((resolve, reject) => {
+    server.on('listening', () => {
+      console.log(`the server is runnint on port ${port}`);
+      server.close();
+      resolve(false);
+    });
+
+    server.on('error', err => {
+      if (err.code === 'EADDRINUSE') {
+        resolve(true);
+        console.log(`this port ${port} is occupied.try another.`);
+      } else {
+        resolve(true);
+      }
+    });
+  });
+};

+ 42 - 0
app/utils/validataRules.js

@@ -0,0 +1,42 @@
+'use strict';
+// 正则校验规则集合
+const regRule = require('./regRule');
+// 校验规则
+const validateRules = {
+  // 账号校验1:手机号&&密码
+  accountType1: () => {
+    return {
+      email: {
+        type: 'string',
+        required: true,
+        allowEmpty: false,
+        format: regRule.emailReg,
+      },
+      password: {
+        type: 'string',
+        require: true,
+        allowEmpty: false,
+        format: regRule.passwordReg1,
+      },
+    };
+  },
+
+  // 账号校验2:手机号&&验证码登录
+  accountType2: () => {
+    return {
+      // phone: {
+      //   type: 'string',
+      //   required: true,
+      //   allowEmpty: false,
+      //   format: regRule.phoneReg,
+      // },
+      code: {
+        type: 'string',
+        required: true,
+        allowEmpty: false,
+      },
+    };
+  },
+};
+
+module.exports = validateRules;

+ 11 - 0
app/view/hello.ejs

@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title><%= title %></title>
+    <link rel='stylesheet' href='/stylesheets/style.css' />
+  </head>
+  <body>
+    <h1><%= title %></h1>
+    <p>Welcome to electron-egg</p>
+  </body>
+</html>

+ 1 - 0
app/view/index.ejs

@@ -0,0 +1 @@
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>electron-egg</title><link href="/js/chunk-2d208e4d.42b6aba6.js" rel="prefetch"><link href="/css/app.741d5958.css" rel="preload" as="style"><link href="/css/chunk-vendors.a1538f74.css" rel="preload" as="style"><link href="/js/app.1f094f31.js" rel="preload" as="script"><link href="/js/chunk-vendors.9ef31ed0.js" rel="preload" as="script"><link href="/css/chunk-vendors.a1538f74.css" rel="stylesheet"><link href="/css/app.741d5958.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but electron-egg doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.9ef31ed0.js"></script><script src="/js/app.1f094f31.js"></script></body></html>

+ 3 - 0
frontend/.env

@@ -0,0 +1,3 @@
+NODE_ENV=production
+VUE_APP_PREVIEW=false
+VUE_APP_API_BASE_URL=api

+ 3 - 0
frontend/.env.development

@@ -0,0 +1,3 @@
+NODE_ENV=development
+VUE_APP_PREVIEW=true
+VUE_APP_API_BASE_URL=http://localhost:7068/api

+ 3 - 0
frontend/.env.preview

@@ -0,0 +1,3 @@
+NODE_ENV=production
+VUE_APP_PREVIEW=true
+VUE_APP_API_BASE_URL=http://localhost:7068/api

+ 23 - 0
frontend/.gitignore

@@ -0,0 +1,23 @@
+.DS_Store
+node_modules
+/dist
+
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?

+ 24 - 0
frontend/README.md

@@ -0,0 +1,24 @@
+# antd-demo
+
+## Project setup
+```
+npm install
+```
+
+### Compiles and hot-reloads for development
+```
+npm run serve
+```
+
+### Compiles and minifies for production
+```
+npm run build
+```
+
+### Lints and fixes files
+```
+npm run lint
+```
+
+### Customize configuration
+See [Configuration Reference](https://cli.vuejs.org/config/).

+ 5 - 0
frontend/babel.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+  presets: [
+    '@vue/cli-plugin-babel/preset'
+  ]
+}

+ 50 - 0
frontend/package.json

@@ -0,0 +1,50 @@
+{
+  "name": "electron-egg",
+  "version": "0.1.0",
+  "private": true,
+  "scripts": {
+    "serve": "vue-cli-service serve",
+    "build": "vue-cli-service build",
+    "lint": "vue-cli-service lint"
+  },
+  "dependencies": {
+    "ant-design-vue": "^1.7.2",
+    "axios": "^0.21.1",
+    "core-js": "^3.6.5",
+    "store": "^2.0.12",
+    "vue": "^2.6.11",
+    "vue-quill-editor": "^3.0.6",
+    "vue-router": "^3.4.9",
+    "vuex": "^3.6.0"
+  },
+  "devDependencies": {
+    "@vue/cli-plugin-babel": "~4.5.0",
+    "@vue/cli-plugin-eslint": "~4.5.0",
+    "@vue/cli-service": "~4.5.0",
+    "babel-eslint": "^10.1.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
+    "less": "^3.0.4",
+    "less-loader": "^5.0.0",
+    "vue-template-compiler": "^2.6.11"
+  },
+  "eslintConfig": {
+    "root": true,
+    "env": {
+      "node": true
+    },
+    "extends": [
+      "plugin:vue/essential",
+      "eslint:recommended"
+    ],
+    "parserOptions": {
+      "parser": "babel-eslint"
+    },
+    "rules": {}
+  },
+  "browserslist": [
+    "> 1%",
+    "last 2 versions",
+    "not dead"
+  ]
+}

BIN
frontend/public/favicon.ico


+ 17 - 0
frontend/public/index.html

@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width,initial-scale=1.0">
+    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
+    <title><%= htmlWebpackPlugin.options.title %></title>
+  </head>
+  <body>
+    <noscript>
+      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
+    </noscript>
+    <div id="app"></div>
+    <!-- built files will be auto injected -->
+  </body>
+</html>

+ 47 - 0
frontend/src/App.vue

@@ -0,0 +1,47 @@
+<template>
+  <div id="app">
+    <Layout />
+  </div>
+</template>
+
+<script>
+// import HelloWorld from './components/HelloWorld.vue'
+// import { Button } from 'ant-design-vue'
+import Layout from './views/Layout'
+
+export default {
+  name: 'App',
+  components: {
+    Layout
+  },
+  data() {
+    return {
+      current: ['mail'],
+      openKeys: ['sub1']
+    };
+  },
+  watch: {
+    openKeys(val) {
+      console.log('openKeys', val);
+    },
+  },
+  methods: {
+    handleClick(e) {
+      console.log('click', e);
+    },
+    titleClick(e) {
+      console.log('titleClick', e);
+    },
+  }
+}
+</script>
+
+<style>
+#app {
+  font-family: Avenir, Helvetica, Arial, sans-serif;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+  text-align: center;
+  color: #2c3e50;
+}
+</style>

BIN
frontend/src/assets/logo.png


+ 58 - 0
frontend/src/components/HelloWorld.vue

@@ -0,0 +1,58 @@
+<template>
+  <div class="hello">
+    <h1>{{ msg }}</h1>
+    <p>
+      For a guide and recipes on how to configure / customize this project,<br>
+      check out the
+      <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
+    </p>
+    <h3>Installed CLI Plugins</h3>
+    <ul>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
+      <li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
+    </ul>
+    <h3>Essential Links</h3>
+    <ul>
+      <li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
+      <li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
+      <li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
+      <li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
+      <li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
+    </ul>
+    <h3>Ecosystem</h3>
+    <ul>
+      <li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
+      <li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
+      <li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
+      <li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
+      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
+    </ul>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    msg: String
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 17 - 0
frontend/src/main.js

@@ -0,0 +1,17 @@
+import Vue from 'vue';
+import antd from 'ant-design-vue';
+import 'ant-design-vue/dist/antd.css';
+import App from './App';
+import router from './router';
+import { VueAxios } from './utils/request'
+
+Vue.use(antd);
+// mount axios to `Vue.$http` and `this.$http`
+Vue.use(VueAxios)
+
+Vue.config.productionTip = false;
+
+new Vue({
+  router,
+  render: h => h(App),
+}).$mount('#app');

+ 17 - 0
frontend/src/router/index.js

@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import Router from 'vue-router'
+import { constantRouterMap } from '@/config/router.config'
+
+// hack router push callback
+const originalPush = Router.prototype.push
+Router.prototype.push = function push (location, onResolve, onReject) {
+  if (onResolve || onReject) return originalPush.call(this, location, onResolve, onReject)
+  return originalPush.call(this, location).catch(err => err)
+}
+
+Vue.use(Router)
+
+export default new Router({
+  mode: 'history',
+  routes: constantRouterMap
+})

+ 35 - 0
frontend/src/utils/axios.js

@@ -0,0 +1,35 @@
+const VueAxios = {
+  vm: {},
+  // eslint-disable-next-line no-unused-vars
+  install (Vue, instance) {
+    if (this.installed) {
+      return
+    }
+    this.installed = true
+
+    if (!instance) {
+      // eslint-disable-next-line no-console
+      console.error('You have to install axios')
+      return
+    }
+
+    Vue.axios = instance
+
+    Object.defineProperties(Vue.prototype, {
+      axios: {
+        get: function get () {
+          return instance
+        }
+      },
+      $http: {
+        get: function get () {
+          return instance
+        }
+      }
+    })
+  }
+}
+
+export {
+  VueAxios
+}

+ 61 - 0
frontend/src/utils/request.js

@@ -0,0 +1,61 @@
+import axios from 'axios'
+import storage from 'store'
+import notification from 'ant-design-vue/es/notification'
+import { VueAxios } from './axios'
+
+// 创建 axios 实例
+const request = axios.create({
+  // API 请求的默认前缀
+  baseURL: process.env.VUE_APP_API_BASE_URL,
+  timeout: 6000 // 请求超时时间
+})
+
+// 异常拦截处理器
+const errorHandler = (error) => {
+  if (error.response) {
+    const data = error.response.data
+    if (error.response.status === 403) {
+      notification.error({
+        message: 'Forbidden',
+        description: data.message
+      })
+    }
+    if (error.response.status === 401 && !(data.result && data.result.isLogin)) {
+      notification.error({
+        message: 'Unauthorized',
+        description: 'Authorization verification failed'
+      })
+    }
+  }
+  return Promise.reject(error)
+}
+
+// request interceptor
+request.interceptors.request.use(config => {
+  const token = storage.get('token')
+  // 如果 token 存在
+  // 让每个请求携带自定义 token 请根据实际情况自行修改
+  if (token) {
+    config.headers['Access-Token'] = token
+  }
+  return config
+}, errorHandler)
+
+// response interceptor
+request.interceptors.response.use((response) => {
+  return response.data
+}, errorHandler)
+
+const installer = {
+  vm: {},
+  install (Vue) {
+    Vue.use(VueAxios, request)
+  }
+}
+
+export default request
+
+export {
+  installer as VueAxios,
+  request as axios
+}

+ 68 - 0
frontend/src/utils/util.js

@@ -0,0 +1,68 @@
+export function timeFix () {
+  const time = new Date()
+  const hour = time.getHours()
+  return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
+}
+
+export function welcome () {
+  const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
+  const index = Math.floor(Math.random() * arr.length)
+  return arr[index]
+}
+
+/**
+ * 触发 window.resize
+ */
+export function triggerWindowResizeEvent () {
+  const event = document.createEvent('HTMLEvents')
+  event.initEvent('resize', true, true)
+  event.eventType = 'message'
+  window.dispatchEvent(event)
+}
+
+export function handleScrollHeader (callback) {
+  let timer = 0
+
+  let beforeScrollTop = window.pageYOffset
+  callback = callback || function () {}
+  window.addEventListener(
+    'scroll',
+    event => {
+      clearTimeout(timer)
+      timer = setTimeout(() => {
+        let direction = 'up'
+        const afterScrollTop = window.pageYOffset
+        const delta = afterScrollTop - beforeScrollTop
+        if (delta === 0) {
+          return false
+        }
+        direction = delta > 0 ? 'down' : 'up'
+        callback(direction)
+        beforeScrollTop = afterScrollTop
+      }, 50)
+    },
+    false
+  )
+}
+
+export function isIE () {
+  const bw = window.navigator.userAgent
+  const compare = (s) => bw.indexOf(s) >= 0
+  const ie11 = (() => 'ActiveXObject' in window)()
+  return compare('MSIE') || ie11
+}
+
+/**
+ * Remove loading animate
+ * @param id parent element id or class
+ * @param timeout
+ */
+export function removeLoadingAnimate (id = '', timeout = 1500) {
+  if (id === '') {
+    return
+  }
+  setTimeout(() => {
+    document.body.removeChild(document.getElementById(id))
+  }, timeout)
+}
+  

+ 32 - 0
frontend/src/views/Contenta.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="hello">
+    <h1>这是首页内一</h1>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    msg: String
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 32 - 0
frontend/src/views/Contentb.vue

@@ -0,0 +1,32 @@
+<template>
+  <div class="hello">
+    <h1>这是首页内二</h1>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'HelloWorld',
+  props: {
+    msg: String
+  }
+}
+</script>
+
+<!-- Add "scoped" attribute to limit CSS to this component only -->
+<style scoped>
+h3 {
+  margin: 40px 0 0;
+}
+ul {
+  list-style-type: none;
+  padding: 0;
+}
+li {
+  display: inline-block;
+  margin: 0 10px;
+}
+a {
+  color: #42b983;
+}
+</style>

+ 5 - 0
frontend/vue.config.js

@@ -0,0 +1,5 @@
+module.exports = {
+    //Solution For Issue:You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
+    //zhengkai.blog.csdn.net
+    runtimeCompiler: true
+  }

Some files were not shown because too many files changed in this diff