@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
@@ -0,0 +1,129 @@
1
+ <template>
2
+ <el-form
3
+ v-if="schema && schema.properties"
4
+ :inline="true"
5
+ class="schema-search-bar"
6
+ >
7
+ <!-- 动态组件 -->
8
+ <el-form-item
9
+ v-for="(schemaItem, key) in schema.properties"
10
+ :key="key"
11
+ :label="schemaItem.label"
12
+ >
13
+ <component
14
+ :ref="searchComList"
15
+ :is="SearchItemConfig[schemaItem.option?.comType]?.component"
16
+ :schemaKey="key"
17
+ :schema="schemaItem"
18
+ @loaded="handleChildLoaded"
19
+ />
20
+ </el-form-item>
21
+
22
+ <!-- 操作区域 -->
23
+ <el-form-item>
24
+ <el-button type="primary" plain class="search-btn" @click="search">
25
+ 搜索
26
+ </el-button>
27
+ <el-button plain class="reset-btn" @click="reset"> 重置 </el-button>
28
+ </el-form-item>
29
+ </el-form>
30
+ </template>
31
+
32
+ <script setup>
33
+ import { ref, toRefs } from 'vue'
34
+ import SearchItemConfig from './search-item-config'
35
+
36
+ const props = defineProps({
37
+ /**
38
+ * schema 配置,结构如下:
39
+ * {
40
+ * type: "object",
41
+ * properties: {
42
+ * key: {
43
+ * ...schema, // 标准 schema 配置
44
+ * type: "", // 字段类型
45
+ * label: "", // 字段中文名
46
+ * // 字段在 search-bar 中的相关配置
47
+ * option: {
48
+ * ...eleComponentConfig, // 标准 el-component-column 配置
49
+ * comType: "", // 配置组件类型 input/select…
50
+ * default: "", // 默认值
51
+ * }
52
+ * }
53
+ * // ...
54
+ * }
55
+ * }
56
+ */
57
+ schema: Object,
58
+ })
59
+
60
+ const { schema } = toRefs(props)
61
+
62
+ const emits = defineEmits(['load', 'search', 'reset'])
63
+
64
+ const search = () => {
65
+ emits('search', getValue())
66
+ }
67
+
68
+ const reset = () => {
69
+ searchComList.value.forEach((component) => component?.reset())
70
+ emits('reset')
71
+ }
72
+
73
+ const searchComList = ref([])
74
+
75
+ const getValue = () => {
76
+ let dtoObj = {}
77
+
78
+ searchComList.value.forEach((component) => {
79
+ dtoObj = {
80
+ ...dtoObj,
81
+ ...component?.getValue(),
82
+ }
83
+ })
84
+
85
+ return dtoObj
86
+ }
87
+
88
+ let childComLoadedCount = 0
89
+ const handleChildLoaded = () => {
90
+ childComLoadedCount++
91
+ if (childComLoadedCount >= Object.keys(schema.value?.properties).length) {
92
+ emits('load', getValue())
93
+ }
94
+ }
95
+
96
+ defineExpose({
97
+ reset,
98
+ })
99
+ </script>
100
+
101
+ <style lang="less">
102
+ .schema-search-bar {
103
+ min-width: 500px;
104
+
105
+ .input {
106
+ width: 180px;
107
+ }
108
+
109
+ .select {
110
+ width: 180px;
111
+ }
112
+
113
+ .dynamic-select {
114
+ width: 180px;
115
+ }
116
+
117
+ // .date-range {
118
+ // width: 300px;
119
+ // }
120
+
121
+ .search-btn {
122
+ width: 100px;
123
+ }
124
+
125
+ .reset-btn {
126
+ width: 100px;
127
+ }
128
+ }
129
+ </style>
@@ -0,0 +1,24 @@
1
+ import Input from "./complex-view/input/input.vue";
2
+ import Select from "./complex-view/select/select.vue";
3
+ import DynamicSelect from "./complex-view/dynamic-select/dynamic-select.vue";
4
+ import DateRange from "./complex-view/date-range/date-range.vue";
5
+
6
+ // 业务拓展 form-item 配置
7
+ import BusinessSearchItemConfig from "$businessSearchItemConfig";
8
+
9
+ const SearchItemConfig = {
10
+ input: {
11
+ component: Input,
12
+ },
13
+ select: {
14
+ component: Select,
15
+ },
16
+ dynamicSelect: {
17
+ component: DynamicSelect,
18
+ },
19
+ dateRange: {
20
+ component: DateRange,
21
+ },
22
+ };
23
+
24
+ export default { ...SearchItemConfig, ...BusinessSearchItemConfig };
@@ -0,0 +1,212 @@
1
+ <template>
2
+ <div class="schema-table">
3
+ <el-table
4
+ v-if="schema && schema?.properties"
5
+ v-loading="loading"
6
+ :data="tableData"
7
+ class="table"
8
+ >
9
+ <template v-for="(schemaItem, key) in schema.properties">
10
+ <el-table-column
11
+ v-if="schemaItem.option.visible !== false"
12
+ :key="key"
13
+ :prop="key"
14
+ :label="schemaItem.label"
15
+ v-bind="schemaItem.option"
16
+ ></el-table-column>
17
+ </template>
18
+ <el-table-column
19
+ v-if="buttons?.length > 0"
20
+ label="操作"
21
+ fixed="right"
22
+ :width="operationWidth"
23
+ >
24
+ <template #default="scoped">
25
+ <el-button
26
+ v-for="item in buttons"
27
+ link
28
+ v-bind="item"
29
+ @click="operationHander({ btnConfig: item, rowData: scoped.row })"
30
+ >
31
+ {{ item.label }}
32
+ </el-button>
33
+ </template>
34
+ </el-table-column>
35
+ </el-table>
36
+
37
+ <el-row justify="end" class="pagination">
38
+ <el-pagination
39
+ :current-page="currentPage"
40
+ :page-size="pageSize"
41
+ :page-sizes="[10, 20, 30, 40, 50, 100]"
42
+ :total="total"
43
+ layout="prev, pager, next, jumper, ->, total"
44
+ @size-change="onPageSizeChange"
45
+ @current-change="onCurrentPageChange"
46
+ ></el-pagination>
47
+ </el-row>
48
+ </div>
49
+ </template>
50
+
51
+ <script setup>
52
+ import { ref, onMounted, toRefs, nextTick, watch, computed } from "vue";
53
+ import $curl from "$elpisCommon/curl.js";
54
+
55
+ const props = defineProps({
56
+ schema: Object, // schema 配置
57
+ api: String, // 表格数据源 API
58
+ apiParams: Object, // 列表接口参数
59
+ buttons: Array, // 操作按钮相关配置
60
+ });
61
+
62
+ const emits = defineEmits(["operate"]);
63
+
64
+ const { schema, api, apiParams, buttons } = toRefs(props);
65
+
66
+ const loading = ref(false);
67
+ const tableData = ref([]);
68
+ const currentPage = ref(1);
69
+ const pageSize = ref(50);
70
+ const total = ref(0);
71
+
72
+ watch(
73
+ [schema, api, apiParams],
74
+ () => {
75
+ initData();
76
+ },
77
+ { deep: true },
78
+ );
79
+
80
+ /**
81
+ * 计算 table 操作列宽度
82
+ */
83
+ const operationWidth = computed(() => {
84
+ return buttons?.value?.length > 0
85
+ ? buttons.value.reduce((pre, cur) => {
86
+ return pre + cur.label.length * 18;
87
+ }, 50)
88
+ : 50;
89
+ });
90
+
91
+ onMounted(() => {
92
+ initData();
93
+ });
94
+
95
+ /**
96
+ * 初始化数据
97
+ */
98
+ const initData = () => {
99
+ currentPage.value = 1;
100
+ pageSize.value = 50;
101
+ nextTick(async () => {
102
+ await loadTableData();
103
+ });
104
+ };
105
+
106
+ let timerId = null;
107
+
108
+ /**
109
+ * 防抖处理
110
+ */
111
+ const loadTableData = async () => {
112
+ clearTimeout(timerId);
113
+ timerId = setTimeout(async () => {
114
+ await fetchTableData();
115
+ timerId = null;
116
+ }, 100);
117
+ };
118
+
119
+ /**
120
+ * 加载表格数据
121
+ */
122
+ const fetchTableData = async () => {
123
+ if (!api.value) {
124
+ return;
125
+ }
126
+
127
+ showLoading();
128
+
129
+ const res = await $curl({
130
+ method: "get",
131
+ url: `${api.value}/list`,
132
+ query: {
133
+ ...apiParams.value,
134
+ page: currentPage.value,
135
+ size: pageSize.value,
136
+ },
137
+ });
138
+
139
+ hideLoading();
140
+
141
+ if (!res || !res.success || !Array.isArray(res.data)) {
142
+ tableData.value = [];
143
+ total.value = 0;
144
+ return;
145
+ }
146
+
147
+ tableData.value = buildTableData(res.data);
148
+ total.value = res.metadata.total;
149
+ };
150
+
151
+ /**
152
+ * 处理元数据
153
+ * @param listData
154
+ */
155
+ const buildTableData = (listData) => {
156
+ if (!schema.value?.properties) {
157
+ return listData;
158
+ }
159
+
160
+ return listData.map((rowData) => {
161
+ for (const rKey in rowData) {
162
+ const schemaItem = schema.value.properties[rKey];
163
+
164
+ if (schemaItem?.option?.toFixed) {
165
+ rowData[rKey] =
166
+ rowData[rKey].toFixed &&
167
+ rowData[rKey].toFixed(schemaItem.option.toFixed);
168
+ }
169
+ }
170
+ return rowData;
171
+ });
172
+ };
173
+
174
+ const showLoading = () => (loading.value = true);
175
+ const hideLoading = () => (loading.value = false);
176
+
177
+ const operationHander = ({ btnConfig, rowData }) => {
178
+ emits("operate", { btnConfig, rowData });
179
+ };
180
+
181
+ const onPageSizeChange = async (value) => {
182
+ pageSize.value = value;
183
+ await loadTableData();
184
+ };
185
+
186
+ const onCurrentPageChange = async (value) => {
187
+ currentPage.value = value;
188
+ await loadTableData();
189
+ };
190
+
191
+ defineExpose({
192
+ initData,
193
+ loadTableData,
194
+ showLoading,
195
+ hideLoading,
196
+ });
197
+ </script>
198
+
199
+ <style scoped lang="less">
200
+ .schema-table {
201
+ flex: 1;
202
+ display: flex;
203
+ flex-direction: column;
204
+ overflow: auto;
205
+ .table {
206
+ flex: 1;
207
+ }
208
+ .pagination {
209
+ margin: 10px 0;
210
+ }
211
+ }
212
+ </style>
@@ -0,0 +1,26 @@
1
+ <template>
2
+ <el-container class="sider-container">
3
+ <el-aside width="200px" class="aside">
4
+ <slot name="menu-content"></slot>
5
+ </el-aside>
6
+ <el-main class="main">
7
+ <slot name="main-content"></slot>
8
+ </el-main>
9
+ </el-container>
10
+ </template>
11
+
12
+ <script setup></script>
13
+
14
+ <style scoped lang="less">
15
+ .sider-container {
16
+ height: 100%;
17
+
18
+ .aside {
19
+ border: 1px solid #e8e8e8;
20
+ }
21
+
22
+ .main {
23
+ overflow: scroll;
24
+ }
25
+ }
26
+ </style>
@@ -0,0 +1,55 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <title>{{ name }}</title>
6
+ <link href="/static/normalize.css" rel="stylesheet" />
7
+ <link href="/static/favicon.ico" rel="icon" type="image/x-icon" />
8
+ </head>
9
+ <body>
10
+ <h1 style="color: red">
11
+ entry.page1
12
+ <span id="env">{{ env }}</span>
13
+ <button onclick="handleClick()">发送请求</button>
14
+ </h1>
15
+ </body>
16
+ <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
17
+ <script src="https://cdn.jsdelivr.net/npm/js-md5@0.8.3/src/md5.min.js"></script>
18
+ <script>
19
+ try {
20
+ window.env = document.getElementById("env").textContent;
21
+ } catch (e) {
22
+ console.log(e);
23
+ }
24
+
25
+ function handleClick() {
26
+ const signKey = "ajflskjflaskdjfqoiwefjlaskdjflka";
27
+ const s_t = Date.now();
28
+ const s_sign = md5(`${signKey}_${s_t}`);
29
+
30
+ // axios.request({
31
+ // method:"post",
32
+ // url:'/api/project/list',
33
+ // headers:{
34
+ // s_t,
35
+ // s_sign
36
+ // },
37
+ // data:{a:1,b:2,c:3}
38
+ // })
39
+
40
+ axios.request({
41
+ method: "get",
42
+ url: "/api/project/list",
43
+ params: { proj_key: "123" },
44
+ headers: {
45
+ s_t,
46
+ s_sign,
47
+ },
48
+ });
49
+
50
+ // axios.get('/api/project/list').then(res=>{
51
+ // console.log(res,'res')
52
+ // })
53
+ }
54
+ </script>
55
+ </html>
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link href="/static/favicon.ico" rel="icon" type="image/x-icon" />
6
+ <title>entry.page1</title>
7
+ </head>
8
+ <body>
9
+ <h1 style="color: darkgreen">entry.page2</h1>
10
+ </body>
11
+ </html>
Binary file