@wanglindoc/elpis 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/.eslintignore +2 -0
  2. package/.eslintrc +52 -0
  3. package/.idea/codeStyles/Project.xml +14 -0
  4. package/.idea/codeStyles/codeStyleConfig.xml +5 -0
  5. package/.idea/elpis.iml +12 -0
  6. package/.idea/inspectionProfiles/Project_Default.xml +6 -0
  7. package/.idea/modules.xml +8 -0
  8. package/.idea/prettier.xml +7 -0
  9. package/.idea/vcs.xml +6 -0
  10. package/README.md +232 -0
  11. package/app/controller/base.js +42 -0
  12. package/app/controller/project.js +76 -0
  13. package/app/controller/view.js +19 -0
  14. package/app/extend/logger.js +42 -0
  15. package/app/middleware/api-params-verify.js +81 -0
  16. package/app/middleware/api-sign-verify.js +45 -0
  17. package/app/middleware/error-handler.js +41 -0
  18. package/app/middleware/project-handler.js +30 -0
  19. package/app/middleware.js +42 -0
  20. package/app/pages/assets/custom.css +14 -0
  21. package/app/pages/boot.js +51 -0
  22. package/app/pages/common/curl.js +91 -0
  23. package/app/pages/common/utils.js +7 -0
  24. package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +18 -0
  25. package/app/pages/dashboard/complex-view/header-view/header-view.vue +154 -0
  26. package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +46 -0
  27. package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +40 -0
  28. package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +127 -0
  29. package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +22 -0
  30. package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +95 -0
  31. package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +104 -0
  32. package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +129 -0
  33. package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +137 -0
  34. package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +102 -0
  35. package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu.vue +21 -0
  36. package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +141 -0
  37. package/app/pages/dashboard/dashboard.vue +96 -0
  38. package/app/pages/dashboard/entry.dashboard.js +53 -0
  39. package/app/pages/dashboard/todo/todo.vue +6 -0
  40. package/app/pages/store/index.js +5 -0
  41. package/app/pages/store/menu.js +73 -0
  42. package/app/pages/store/project.js +15 -0
  43. package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
  44. package/app/pages/widgets/header-container/asserts/logo.png +0 -0
  45. package/app/pages/widgets/header-container/header-container.vue +106 -0
  46. package/app/pages/widgets/schema-form/complex-view/input/input.vue +137 -0
  47. package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +135 -0
  48. package/app/pages/widgets/schema-form/complex-view/select/select.vue +119 -0
  49. package/app/pages/widgets/schema-form/form-item-config.js +20 -0
  50. package/app/pages/widgets/schema-form/schema-form.vue +145 -0
  51. package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +52 -0
  52. package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +65 -0
  53. package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +42 -0
  54. package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +49 -0
  55. package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +129 -0
  56. package/app/pages/widgets/schema-search-bar/search-item-config.js +24 -0
  57. package/app/pages/widgets/schema-table/schema-table.vue +212 -0
  58. package/app/pages/widgets/sider-container/sider-container.vue +26 -0
  59. package/app/public/output/entry.page1.tpl +55 -0
  60. package/app/public/output/entry.page2.tpl +11 -0
  61. package/app/public/static/favicon.ico +0 -0
  62. package/app/public/static/normalize.css +267 -0
  63. package/app/router/project.js +14 -0
  64. package/app/router/view.js +9 -0
  65. package/app/router-schema/project.js +32 -0
  66. package/app/service/base.js +15 -0
  67. package/app/service/project.js +48 -0
  68. package/app/view/entry.tpl +22 -0
  69. package/app/webpack/build-dev.js +64 -0
  70. package/app/webpack/build-prod.js +29 -0
  71. package/app/webpack/config/webpack.base.js +352 -0
  72. package/app/webpack/config/webpack.dev.js +59 -0
  73. package/app/webpack/config/webpack.prod.js +145 -0
  74. package/app/webpack/libs/blank.js +1 -0
  75. package/config/config.default.js +4 -0
  76. package/elpis-core/env.js +20 -0
  77. package/elpis-core/index.js +106 -0
  78. package/elpis-core/loader/config.js +62 -0
  79. package/elpis-core/loader/controller.js +79 -0
  80. package/elpis-core/loader/extend.js +67 -0
  81. package/elpis-core/loader/middleware.js +77 -0
  82. package/elpis-core/loader/router-schema.js +57 -0
  83. package/elpis-core/loader/router.js +57 -0
  84. package/elpis-core/loader/service.js +76 -0
  85. package/index.js +39 -0
  86. package/model/index.js +128 -0
  87. package/package.json +90 -0
  88. package/test/controller/project.test.js +243 -0
package/package.json ADDED
@@ -0,0 +1,90 @@
1
+ {
2
+ "name": "@wanglindoc/elpis",
3
+ "version": "1.0.0",
4
+ "description": "简易版egg.js",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "lint": "eslint --quiet --ext js,vue .",
8
+ "test": "_ENV='local' mocha 'test/**/*.js'"
9
+ },
10
+ "repository": {
11
+ "type": "git"
12
+ },
13
+ "author": "wanglin",
14
+ "license": "ISC",
15
+ "dependencies": {
16
+ "@babel/core": "^7.24.0",
17
+ "@babel/runtime": "^7.29.2",
18
+ "ajv": "^6.10.2",
19
+ "axios": "^0.19.2",
20
+ "echarts": "^5.5.0",
21
+ "element-plus": "^2.3.7",
22
+ "generate-password": "^1.7.1",
23
+ "glob": "^7.1.4",
24
+ "jsonwebtoken": "^9.0.2",
25
+ "knex": "^0.19.0",
26
+ "koa": "2.7.0",
27
+ "koa-bodyparser": "^4.2.1",
28
+ "koa-nunjucks-2": "^3.0.2",
29
+ "koa-router": "^7.4.0",
30
+ "koa-static": "^5.0.0",
31
+ "koa-useragent": "2.0.0",
32
+ "koa2-cors": "^2.0.6",
33
+ "less": "^3.8.1",
34
+ "lodash": "^4.17.21",
35
+ "log4js": "^6.9.1",
36
+ "md5": "^2.2.1",
37
+ "moment": "^2.29.4",
38
+ "mysql": "^2.18.1",
39
+ "node-schedule": "^2.1.1",
40
+ "nodemon": "^1.19.2",
41
+ "path": "^0.12.7",
42
+ "pinia": "^2.1.6",
43
+ "superagent": "^8.1.2",
44
+ "vue": "^3.3.4",
45
+ "vue-json-viewer": "^3.0.4",
46
+ "vue-router": "^4.2.4",
47
+ "vuex": "^4.1.0",
48
+ "@babel/plugin-transform-runtime": "^7.1.0",
49
+ "@babel/preset-env": "^7.4.5",
50
+ "babel-loader": "^8.0.4",
51
+ "clean-webpack-plugin": "^0.1.19",
52
+ "consoler": "^0.2.0",
53
+ "css-loader": "^0.23.1",
54
+ "css-minimizer-webpack-plugin": "^5.0.1",
55
+ "directory-named-webpack-plugin": "^4.0.1",
56
+ "express": "^4.18.2",
57
+ "file-loader": "^6.2.0",
58
+ "happypack": "^5.0.1",
59
+ "html-webpack-inject-attributes-plugin": "^1.0.1",
60
+ "html-webpack-plugin": "^5.5.3",
61
+ "less-loader": "^11.1.3",
62
+ "mini-css-extract-plugin": "^2.7.6",
63
+ "style-loader": "^0.14.1",
64
+ "terser-webpack-plugin": "^2.3.5",
65
+ "url-loader": "^4.1.1",
66
+ "vue-loader": "^17.2.2",
67
+ "vue-style-loader": "^4.1.2",
68
+ "webpack": "^5.88.1",
69
+ "webpack-dev-middleware": "^6.1.1",
70
+ "webpack-hot-middleware": "^2.25.4",
71
+ "webpack-merge": "^4.2.1"
72
+ },
73
+ "devDependencies": {
74
+ "assert": "^2.0.0",
75
+ "babel-eslint": "^10.0.2",
76
+ "eslint": "^7.32.0",
77
+ "eslint-plugin-import": "^2.28.1",
78
+ "eslint-plugin-vue": "^9.17.0",
79
+ "ghooks": "~1.0.3",
80
+ "mocha": "^6.1.4",
81
+ "supertest": "^4.0.2",
82
+ "validate-commit-msg": "~2.14.0"
83
+ },
84
+ "config": {
85
+ "ghooks": {
86
+ "commit-msg": "validate-commit-msg",
87
+ "pre-commit": "npm run lint"
88
+ }
89
+ }
90
+ }
@@ -0,0 +1,243 @@
1
+ const assert = require("assert");
2
+ const supertest = require("supertest");
3
+ const md5 = require("md5");
4
+ const elpisCore = require("../../elpis-core");
5
+
6
+ const signKey = "ajflskjflaskdjfqoiwefjlaskdjflka";
7
+ const st = Date.now();
8
+
9
+ // describe是一个场景的描述,里面可以有很多 it
10
+ describe("测试project相关接口", function () {
11
+ this.timeout(60000);
12
+
13
+ let request;
14
+
15
+ // 标准数据与接口做对比
16
+ let modelList;
17
+ const projectList = [];
18
+
19
+ // 一个 it 可以看作是一个用例或者一个步骤
20
+ it("启动服务", async () => {
21
+ const app = await elpisCore.start();
22
+
23
+ modelList = require("../../model/index")(app);
24
+
25
+ modelList.forEach((modelItem) => {
26
+ const { project } = modelItem;
27
+
28
+ for (const pKey in project) {
29
+ projectList.push(project[pKey]);
30
+ }
31
+ });
32
+
33
+ request = supertest(app.listen());
34
+ });
35
+
36
+ /**
37
+ * 获取所有模型与项目的结构化数据
38
+ */
39
+ it("GET /api/project/model_list", async () => {
40
+ let temRequest = request.get("/api/project/model_list");
41
+ temRequest = temRequest.set("s_t", st);
42
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
43
+ const res = await temRequest;
44
+
45
+ // 断言语句
46
+ assert(res.body.success === true);
47
+
48
+ const resData = res.body.data;
49
+ assert(resData.length > 0);
50
+
51
+ for (let i = 0; i < resData.length; ++i) {
52
+ const item = resData[i];
53
+ assert(item.model);
54
+ assert(item.model.key);
55
+ assert(item.model.name);
56
+ assert(item.project);
57
+ for (const projKey in item.project) {
58
+ assert(item.project[projKey].key);
59
+ assert(item.project[projKey].name);
60
+ }
61
+ }
62
+ });
63
+
64
+ /**
65
+ * 获取统一模型下的项目列表(没有 proj_key)
66
+ */
67
+ it("GET /api/project/list without proj_key", async () => {
68
+ let temRequest = request.get("/api/project/list");
69
+ temRequest = temRequest.set("s_t", st);
70
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
71
+ const res = await temRequest;
72
+
73
+ assert(res.body.success === true);
74
+
75
+ const resData = res.body.data;
76
+ assert(resData.length === projectList.length);
77
+
78
+ for (let i = 0; i < resData.length; ++i) {
79
+ const item = resData[i];
80
+ assert(item.modelKey);
81
+ assert(item.key);
82
+ assert(item.name);
83
+ assert(item.desc !== undefined);
84
+ assert(item.homePage !== undefined);
85
+ }
86
+ });
87
+
88
+ /**
89
+ * 获取统一模型下的项目列表(有 proj_key)
90
+ */
91
+ it("GET /api/project/list with proj_key", async () => {
92
+ const { key: projKey } =
93
+ projectList[Math.floor(Math.random() * projectList.length)];
94
+ const { modelKey } = projectList.find((item) => item.key === projKey);
95
+
96
+ let temRequest = request.get("/api/project/list");
97
+ temRequest = temRequest.set("s_t", st);
98
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
99
+ temRequest = temRequest.query({ proj_key: projKey });
100
+ const res = await temRequest;
101
+
102
+ assert(res.body.success === true);
103
+
104
+ const resData = res.body.data;
105
+ assert(
106
+ resData.length ===
107
+ projectList.filter((item) => item.modelKey === modelKey).length,
108
+ );
109
+
110
+ for (let i = 0; i < resData.length; ++i) {
111
+ const item = resData[i];
112
+ assert(item.modelKey);
113
+ assert(item.key);
114
+ assert(item.name);
115
+ assert(item.desc !== undefined);
116
+ assert(item.homePage !== undefined);
117
+ }
118
+ });
119
+
120
+ /**
121
+ * 根据 proj_key 获取项目配置 没有 proj_key
122
+ */
123
+ it("GET /api/project without proj_key", async () => {
124
+ let temRequest = request.get("/api/project");
125
+ temRequest = temRequest.set("s_t", st);
126
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
127
+
128
+ const res = await temRequest;
129
+
130
+ assert(res.body.success === false);
131
+
132
+ const resBody = res.body;
133
+
134
+ assert(resBody.code === 442);
135
+ assert(
136
+ resBody.message.indexOf(
137
+ "request validate fial: data should have required property 'proj_key'",
138
+ ) > -1,
139
+ );
140
+ });
141
+
142
+ /**
143
+ * 根据 proj_key 获取项目配置 fail
144
+ */
145
+ it("GET /api/project with fail", async () => {
146
+ let temRequest = request.get("/api/project");
147
+ temRequest = temRequest.set("s_t", st);
148
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
149
+ temRequest = temRequest.query({ proj_key: "xxx" });
150
+ const res = await temRequest;
151
+
152
+ assert(res.body.success === false);
153
+
154
+ const resBody = res.body;
155
+ assert(resBody.code === 50000);
156
+ assert(resBody.message === "获取项目异常");
157
+ });
158
+
159
+ /**
160
+ * 根据 proj_key 获取项目配置 有 proj_key
161
+ */
162
+ it("GET /api/project with proj_key", async () => {
163
+ for (let i = 0; i < projectList.length; ++i) {
164
+ const projKey = projectList[i].key;
165
+ console.log(`GET /api/project with proj_key:${projKey}`);
166
+
167
+ let temRequest = request.get("/api/project");
168
+ temRequest = temRequest.set("s_t", st);
169
+ temRequest = temRequest.set("s_sign", md5(`${signKey}_${st}`));
170
+ temRequest = temRequest.query({ proj_key: projKey });
171
+ const res = await temRequest;
172
+
173
+ assert(res.body.success === true);
174
+ const resData = res.body.data;
175
+
176
+ assert(resData.key === projKey);
177
+ assert(resData.modelKey);
178
+ assert(resData.name);
179
+ assert(resData.desc !== undefined);
180
+ assert(resData.homePage !== undefined);
181
+
182
+ const { menu } = resData;
183
+ menu.forEach((menuItem) => {
184
+ checkMenuItem(menuItem);
185
+ });
186
+ }
187
+
188
+ // 检查 menu 菜单
189
+ function checkMenuItem(menuItem) {
190
+ console.log("---------", menuItem.key);
191
+
192
+ assert(menuItem.key);
193
+ assert(menuItem.name);
194
+ assert(menuItem.menuType);
195
+
196
+ if (menuItem.menuType === "group") {
197
+ assert(menuItem.subMenu !== undefined);
198
+ menuItem.subMenu.forEach((subMenuItem) => {
199
+ checkMenuItem(subMenuItem);
200
+ });
201
+ }
202
+
203
+ if (menuItem.menuType === "module") {
204
+ checkModule(menuItem);
205
+ }
206
+ }
207
+
208
+ // 检查 module 菜单配置
209
+ function checkModule(menuItem) {
210
+ const { moduleType } = menuItem;
211
+
212
+ assert(moduleType);
213
+
214
+ if (moduleType === "sider") {
215
+ const { siderConfig } = menuItem;
216
+ assert(siderConfig);
217
+ assert(siderConfig.menu);
218
+ siderConfig.menu.forEach((siderMenuItem) => {
219
+ checkMenuItem(siderMenuItem);
220
+ });
221
+ }
222
+
223
+ if (moduleType === "iframe") {
224
+ const { iframeConfig } = menuItem;
225
+ assert(iframeConfig);
226
+ assert(iframeConfig.path !== undefined);
227
+ }
228
+
229
+ if (moduleType === "custom") {
230
+ const { customConfig } = menuItem;
231
+ assert(customConfig);
232
+ assert(customConfig.path !== undefined);
233
+ }
234
+
235
+ if (moduleType === "schema") {
236
+ const { schemaConfig } = menuItem;
237
+ assert(schemaConfig);
238
+ assert(schemaConfig.api !== undefined);
239
+ assert(schemaConfig.schema);
240
+ }
241
+ }
242
+ });
243
+ });