@jiangliffey/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.
- package/.eslintignore +3 -0
- package/.eslintrc +55 -0
- package/CLAUDE.md +81 -0
- package/README.md +200 -0
- package/app/controller/base.js +38 -0
- package/app/controller/project.js +74 -0
- package/app/controller/view.js +22 -0
- package/app/extend/logger.js +35 -0
- package/app/middleware/api-params-verify.js +81 -0
- package/app/middleware/api-sign-verify.js +35 -0
- package/app/middleware/error-handler.js +33 -0
- package/app/middleware/project-handler.js +27 -0
- package/app/middleware.js +37 -0
- package/app/pages/asserts/custom.css +12 -0
- package/app/pages/boot.js +50 -0
- package/app/pages/common/curl.js +89 -0
- package/app/pages/common/utils.js +2 -0
- package/app/pages/dashboard/complex-view/header-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/header-view/header-view.vue +123 -0
- package/app/pages/dashboard/complex-view/iframe-view/iframe-view.vue +43 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/search-panel/search-panel.vue +40 -0
- package/app/pages/dashboard/complex-view/schema-view/complex-view/table-panel/table-panel.vue +124 -0
- package/app/pages/dashboard/complex-view/schema-view/components/component-config.js +23 -0
- package/app/pages/dashboard/complex-view/schema-view/components/create-form/create-form.vue +87 -0
- package/app/pages/dashboard/complex-view/schema-view/components/detail-panel/detail-panel.vue +100 -0
- package/app/pages/dashboard/complex-view/schema-view/components/edit-form/edit-form.vue +118 -0
- package/app/pages/dashboard/complex-view/schema-view/hook/schema.js +124 -0
- package/app/pages/dashboard/complex-view/schema-view/schema-view.vue +80 -0
- package/app/pages/dashboard/complex-view/sider-view/complex-view/sub-menu/sub-menu.vue +21 -0
- package/app/pages/dashboard/complex-view/sider-view/sider-view.vue +135 -0
- package/app/pages/dashboard/dashboard.vue +96 -0
- package/app/pages/dashboard/entry.dashboard.js +45 -0
- package/app/pages/dashboard/todo/todo.vue +11 -0
- package/app/pages/store/index.js +4 -0
- package/app/pages/store/menu.js +58 -0
- package/app/pages/store/project.js +14 -0
- package/app/pages/widgets/header-container/asserts/avatar.png +0 -0
- package/app/pages/widgets/header-container/asserts/logo.png +0 -0
- package/app/pages/widgets/header-container/header-container.vue +106 -0
- package/app/pages/widgets/schema-form/complex-view/input/input.vue +134 -0
- package/app/pages/widgets/schema-form/complex-view/input-number/input-number.vue +136 -0
- package/app/pages/widgets/schema-form/complex-view/select/select.vue +116 -0
- package/app/pages/widgets/schema-form/form-item-config.js +23 -0
- package/app/pages/widgets/schema-form/schema-form.vue +135 -0
- package/app/pages/widgets/schema-search-bar/complex-view/date-range/date-range.vue +50 -0
- package/app/pages/widgets/schema-search-bar/complex-view/dynamic-select/dynamic-select.vue +67 -0
- package/app/pages/widgets/schema-search-bar/complex-view/input/input.vue +44 -0
- package/app/pages/widgets/schema-search-bar/complex-view/select/select.vue +51 -0
- package/app/pages/widgets/schema-search-bar/schema-search-bar.vue +129 -0
- package/app/pages/widgets/schema-search-bar/search-item-config.js +27 -0
- package/app/pages/widgets/schema-table/schema-table.vue +235 -0
- package/app/pages/widgets/sider-container/sider-container.vue +31 -0
- package/app/public/static/logo.png +0 -0
- package/app/public/static/normalize.css +239 -0
- package/app/router/project.js +6 -0
- package/app/router/view.js +8 -0
- package/app/router-schema/project.js +30 -0
- package/app/service/base.js +11 -0
- package/app/service/project.js +56 -0
- package/app/view/entry.tpl +26 -0
- package/app/webpack/config/webpack.base.js +203 -0
- package/app/webpack/config/webpack.dev.js +59 -0
- package/app/webpack/config/webpack.prod.js +107 -0
- package/app/webpack/dev.js +53 -0
- package/app/webpack/libs/blank.js +3 -0
- package/app/webpack/prod.js +17 -0
- package/config/config.default.js +3 -0
- package/docs/dashboard-model.js +153 -0
- package/elpis-core/env.js +23 -0
- package/elpis-core/index.js +96 -0
- package/elpis-core/loader/config.js +50 -0
- package/elpis-core/loader/controller.js +54 -0
- package/elpis-core/loader/extend.js +49 -0
- package/elpis-core/loader/middleware.js +53 -0
- package/elpis-core/loader/router-schema.js +41 -0
- package/elpis-core/loader/router.js +45 -0
- package/elpis-core/loader/service.js +54 -0
- package/index.js +40 -0
- package/model/index.js +99 -0
- package/package.json +92 -0
- package/test/controller/project.test.js +225 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
const glob = require('glob');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const webpack = require('webpack');
|
|
5
|
+
const { merge } = require('webpack-merge');
|
|
6
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
|
7
|
+
const { VueLoaderPlugin } = require('vue-loader');
|
|
8
|
+
|
|
9
|
+
// 动态构造 elpisPageEntries elpisHtmlWebpackPluginList
|
|
10
|
+
const elpisPageEntries = {};
|
|
11
|
+
const elpisHtmlWebpackPluginList = [];
|
|
12
|
+
// 获取 elpis/app/pages 目录下所有入口文件 (entry.xx.js)
|
|
13
|
+
const elpisEntryList = path.resolve(__dirname, '../../pages/**/entry.*.js')
|
|
14
|
+
glob.sync(elpisEntryList).forEach(file => {
|
|
15
|
+
handleFile(file, elpisPageEntries, elpisHtmlWebpackPluginList);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// 动态构造 businessPageEntries businessHtmlWebpackPluginList
|
|
19
|
+
const businessPageEntries = {};
|
|
20
|
+
const businessHtmlWebpackPluginList = [];
|
|
21
|
+
// 获取 业务/app/pages 目录下所有入口文件 (entry.xx.js)
|
|
22
|
+
const businessEntryList = path.resolve(process.cwd(), './app/pages/**/entry.*.js')
|
|
23
|
+
glob.sync(businessEntryList).forEach(file => {
|
|
24
|
+
handleFile(file, businessPageEntries, businessHtmlWebpackPluginList);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// 构造相关 webpack 处理的数据结构
|
|
28
|
+
function handleFile(file, entries = {}, htmlWebpackPluginList = []) {
|
|
29
|
+
const entryName = path.basename(file, '.js');
|
|
30
|
+
// 构造entry
|
|
31
|
+
entries[entryName] = path.resolve(process.cwd(), file);
|
|
32
|
+
// 构造最终渲染的页面文件
|
|
33
|
+
htmlWebpackPluginList.push(
|
|
34
|
+
// html-webpack-plugin 辅助注入打包后的 bundle 文件到 tpl 文件中
|
|
35
|
+
new HtmlWebpackPlugin({
|
|
36
|
+
// 产物(最终模板)输出路径
|
|
37
|
+
filename: path.resolve(process.cwd(), './app/public/dist/', `${entryName}.tpl`),
|
|
38
|
+
// 指定要使用的模板文件
|
|
39
|
+
template: path.resolve(__dirname, '../../view/entry.tpl'),
|
|
40
|
+
// 要注入的代码块
|
|
41
|
+
chunks: [ entryName ]
|
|
42
|
+
})
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 加载 业务 webpack 配置
|
|
48
|
+
*/
|
|
49
|
+
let businessWebpackConfig = {};
|
|
50
|
+
try {
|
|
51
|
+
businessWebpackConfig = require(path.resolve(process.cwd(), './app/webpack.config.js'));
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.warn('未找到业务 webpack 配置,使用默认配置');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* webpack 基础配置
|
|
58
|
+
*/
|
|
59
|
+
module.exports = merge({
|
|
60
|
+
// 入口配置
|
|
61
|
+
entry: Object.assign({}, elpisPageEntries, businessPageEntries),
|
|
62
|
+
// 模块解析配置(决定了需要加载解析哪些模块,以及用什么方式去解析)
|
|
63
|
+
module: {
|
|
64
|
+
rules: [
|
|
65
|
+
{
|
|
66
|
+
test: /\.vue$/,
|
|
67
|
+
use: { loader: require.resolve('vue-loader') }
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
test: /\.js$/,
|
|
71
|
+
// 对elpis目录代码进行Babel,加快webpack打包速度
|
|
72
|
+
include: [ path.resolve(__dirname, '../../pages') ],
|
|
73
|
+
// 对业务目录代码进行Babel,加快webpack打包速度
|
|
74
|
+
include: [ path.resolve(process.cwd(), './app/pages') ],
|
|
75
|
+
use: { loader: require.resolve('babel-loader') }
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
test: /\.(png|jpe?g|gif)(\?.+)?$/,
|
|
79
|
+
use: {
|
|
80
|
+
loader: require.resolve('url-loader'),
|
|
81
|
+
options: {
|
|
82
|
+
limit: 300,
|
|
83
|
+
esModule: false
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
test: /\.css$/,
|
|
89
|
+
use: [require.resolve('style-loader'), require.resolve('css-loader')],
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
test: /\.less$/,
|
|
93
|
+
use: [require.resolve('style-loader'), require.resolve('css-loader'), require.resolve('less-loader')],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
|
|
97
|
+
use: require.resolve('file-loader'),
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
// 产物输出路径,因为开发和生产环境输出不一致,所以在各自环境中自行配置
|
|
102
|
+
output: {},
|
|
103
|
+
// 配置模块解析的具体行为(定义webpack在打包时,如何找到并解析具体模块路径)
|
|
104
|
+
resolve: {
|
|
105
|
+
extensions: ['.js', '.vue', '.less', '.css'],
|
|
106
|
+
alias: (() => {
|
|
107
|
+
const aliasMap = {};
|
|
108
|
+
const blankModulePath = path.resolve(__dirname, '../libs/blank.js');
|
|
109
|
+
|
|
110
|
+
// dashboard 路由拓展配置
|
|
111
|
+
const businessDashboardRouterConfig = path.resolve(process.cwd(), './app/pages/dashboard/router.js');
|
|
112
|
+
aliasMap['$businessDashboardRouterConfig'] = fs.existsSync(businessDashboardRouterConfig) ? businessDashboardRouterConfig : blankModulePath;
|
|
113
|
+
|
|
114
|
+
// schema-view component 扩展配置
|
|
115
|
+
const businessComponentConfig = path.resolve(process.cwd(), './app/pages/dashboard/complex-view/schema-view/components/component-config.js');
|
|
116
|
+
aliasMap['$businessComponentConfig'] = fs.existsSync(businessComponentConfig) ? businessComponentConfig : blankModulePath;
|
|
117
|
+
|
|
118
|
+
// schema-form 扩展配置
|
|
119
|
+
const businessFormItemConfig = path.resolve(process.cwd(), './app/pages/widgets/schema-form/form-item-config.js');
|
|
120
|
+
aliasMap['$businessFormItemConfig'] = fs.existsSync(businessFormItemConfig) ? businessFormItemConfig : blankModulePath;
|
|
121
|
+
|
|
122
|
+
// schema-search-bar 扩展配置
|
|
123
|
+
const businessSearchItemConfig = path.resolve(process.cwd(), './app/pages/widgets/schema-search-bar/search-item-config.js');
|
|
124
|
+
aliasMap['$businessSearchItemConfig'] = fs.existsSync(businessSearchItemConfig) ? businessSearchItemConfig : blankModulePath;
|
|
125
|
+
|
|
126
|
+
return {
|
|
127
|
+
'vue': require.resolve('vue'),
|
|
128
|
+
'@babel/runtime/helpers/toConsumableArray': require.resolve('@babel/runtime/helpers/toConsumableArray'),
|
|
129
|
+
'@babel/runtime/helpers/asyncToGenerator': require.resolve('@babel/runtime/helpers/asyncToGenerator'),
|
|
130
|
+
'@babel/runtime/regenerator': require.resolve('@babel/runtime/regenerator'),
|
|
131
|
+
$elpisPages: path.resolve(__dirname, '../../pages'),
|
|
132
|
+
$elpisCommon: path.resolve(__dirname, '../../pages/common'),
|
|
133
|
+
$elpisCurl: path.resolve(__dirname, '../../pages/common/curl.js'),
|
|
134
|
+
$elpisUtils: path.resolve(__dirname, '../../pages/common/utils.js'),
|
|
135
|
+
$elpisWidgets: path.resolve(__dirname, '../../pages/widgets'),
|
|
136
|
+
$elpisHeaderContainer: path.resolve(__dirname, '../../pages/widgets/header-container/header-container.vue'),
|
|
137
|
+
$elpisSiderContainer: path.resolve(__dirname, '../../pages/widgets/sider-container/sider-container.vue'),
|
|
138
|
+
$elpisSchemaTable: path.resolve(__dirname, '../../pages/widgets/schema-table/schema-table.vue'),
|
|
139
|
+
$elpisSchemaForm: path.resolve(__dirname, '../../pages/widgets/schema-form/schema-form.vue'),
|
|
140
|
+
$elpisSchemaSearchBar: path.resolve(__dirname, '../../pages/widgets/schema-search-bar/schema-search-bar.vue'),
|
|
141
|
+
$elpisStore: path.resolve(__dirname, '../../pages/store'),
|
|
142
|
+
$elpisBoot: path.resolve(__dirname, '../../pages/boot.js'),
|
|
143
|
+
...aliasMap
|
|
144
|
+
};
|
|
145
|
+
})()
|
|
146
|
+
},
|
|
147
|
+
// 配置webpack插件
|
|
148
|
+
plugins: [
|
|
149
|
+
// 处理 .vue 文件,该插件是必需的
|
|
150
|
+
// 它的职能是将你定义过的其他规则复制并应用到 .vue 文件里
|
|
151
|
+
// 例如:如果有一条匹配规则 /\.js$/ 的规则,那么它会应用到 .vue 文件中 <script>板块中
|
|
152
|
+
new VueLoaderPlugin(),
|
|
153
|
+
// 把第三方库暴露到window context下
|
|
154
|
+
new webpack.ProvidePlugin({
|
|
155
|
+
Vue: 'vue',
|
|
156
|
+
axios: 'axios',
|
|
157
|
+
_: 'lodash'
|
|
158
|
+
}),
|
|
159
|
+
// 定义全局常量
|
|
160
|
+
new webpack.DefinePlugin({
|
|
161
|
+
__VUE_OPTIONS_API__: 'true', // 支持 vue 解析 optionsApi
|
|
162
|
+
__VUE_PROD_DEVTOOLS__: 'false', // 禁用 vue 调试工具
|
|
163
|
+
__VUE_PROD_HYDRATION_MISMATCH_DETAILS: 'false' //禁用生产环境显示“水合”信息
|
|
164
|
+
}),
|
|
165
|
+
// 构造最终渲染的页面模板
|
|
166
|
+
...elpisHtmlWebpackPluginList,
|
|
167
|
+
...businessHtmlWebpackPluginList,
|
|
168
|
+
],
|
|
169
|
+
// 配置打包输出优化(配置代码分割,模块合并,缓存,TreeShaing,压缩等优化策略)
|
|
170
|
+
optimization: {
|
|
171
|
+
/**
|
|
172
|
+
* 把js文件打包成3种类型、
|
|
173
|
+
* 1、vendor:第三方lib库,基本不会改动,除非依赖版本升级
|
|
174
|
+
* 2、common:业务组件代码的公共部分抽取出来,改动较少
|
|
175
|
+
* 3、entry.{page}:不用页面entry里的业务组件代码的差异部分,会经常改动
|
|
176
|
+
* 目的:把改动和引用频率不一样的js区分出来,以达到更好利用浏览器缓存的效果
|
|
177
|
+
*/
|
|
178
|
+
splitChunks: {
|
|
179
|
+
chunks: 'all',// 对同步和异步模块都进行分割
|
|
180
|
+
maxAsyncRequests: 10,// 每次异步加载的最大并行请求数
|
|
181
|
+
maxInitialRequests: 10,// 入口点的最大并行请求数
|
|
182
|
+
cacheGroups: {
|
|
183
|
+
vendor: { // 第三方依赖库
|
|
184
|
+
test: /[\\/]node_modules[\\/]/, // 打包node_modules文件
|
|
185
|
+
name: 'vendor', // 模块名称
|
|
186
|
+
priority: 20,// 优先级:数字越大,优先级越高
|
|
187
|
+
enforce: true, // 强制执行
|
|
188
|
+
reuseExistingChunk: true, // 复用已有的公共chunk
|
|
189
|
+
},
|
|
190
|
+
common: { // 公共模块
|
|
191
|
+
test: /[\\/]common|widgets[\\/]/, // 打包node_modules文件
|
|
192
|
+
name: 'common', // 模块名称
|
|
193
|
+
minChunks: 2, // 最少被2处引用即被归为公共模块
|
|
194
|
+
minSize: 1, // 最小分割文件大小(1 byte)
|
|
195
|
+
priority: 10,
|
|
196
|
+
reuseExistingChunk: true,
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
},
|
|
200
|
+
// 将webpack运行时生成的代码打包到runtime.js
|
|
201
|
+
runtimeChunk: true,
|
|
202
|
+
},
|
|
203
|
+
}, businessWebpackConfig);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const { merge } = require('webpack-merge');
|
|
3
|
+
const webpack = require("webpack");
|
|
4
|
+
|
|
5
|
+
// 基类配置
|
|
6
|
+
const baseConfig = require('./webpack.base.js');
|
|
7
|
+
|
|
8
|
+
// dev-server 配置
|
|
9
|
+
const DEV_SERVER_CONFIG = {
|
|
10
|
+
HOST: '127.0.0.1',
|
|
11
|
+
PORT: 9002,
|
|
12
|
+
HMR_PATH: '__webpack_hmr',// 官方规定
|
|
13
|
+
TIMEOUT: 20000
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// 开发阶段的 entry 配置需要加入 hmr
|
|
17
|
+
Object.keys(baseConfig.entry).forEach(v => {
|
|
18
|
+
// 第三方包不作为 hmr 入口
|
|
19
|
+
if(v !== 'vendor') {
|
|
20
|
+
baseConfig.entry[v] = [
|
|
21
|
+
// 主入口文件
|
|
22
|
+
baseConfig.entry[v],
|
|
23
|
+
// hmr 更新入口,官方指定的hmr路径
|
|
24
|
+
`${require.resolve('webpack-hot-middleware/client')}?path=http://${DEV_SERVER_CONFIG.HOST}:${DEV_SERVER_CONFIG.PORT}/${DEV_SERVER_CONFIG.HMR_PATH}&timeout=${DEV_SERVER_CONFIG.TIMEOUT}&reload=true`
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// 生产环境webpack配置
|
|
30
|
+
const webpackConfig = merge(baseConfig, {
|
|
31
|
+
// 指定开发环境
|
|
32
|
+
mode: 'development',
|
|
33
|
+
// source-map开发工具,呈现代码的映射关系,便于在开发过程中调试代码
|
|
34
|
+
devtool: 'eval-cheap-module-source-map',
|
|
35
|
+
// 开发环境output配置
|
|
36
|
+
output: {
|
|
37
|
+
filename: 'js/[name]_[chunkhash:8].bundle.js',
|
|
38
|
+
path: path.join(process.cwd(), './app/public/dist/dev/'),// 输出文件存储路径
|
|
39
|
+
publicPath: `http://${DEV_SERVER_CONFIG.HOST}:${DEV_SERVER_CONFIG.PORT}/public/dist/dev/`,// 外部资源公共路径
|
|
40
|
+
globalObject: 'this',
|
|
41
|
+
crossOriginLoading: 'anonymous',
|
|
42
|
+
},
|
|
43
|
+
// 开发阶段插件
|
|
44
|
+
plugins: [
|
|
45
|
+
// HotModuleReplacementPlugin 用于实现热模块替换 (Hot Module Replacement 简称 HMR)
|
|
46
|
+
// 模块热替换允许在应用程序运行时替换模块
|
|
47
|
+
// 极大的提升开发效率,因为能让应用程序一直保持运行状态
|
|
48
|
+
new webpack.HotModuleReplacementPlugin({
|
|
49
|
+
multiStep: false,
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
// webpack配置
|
|
56
|
+
webpackConfig,
|
|
57
|
+
// devServer 配置,暴露给 dev.js 使用
|
|
58
|
+
DEV_SERVER_CONFIG
|
|
59
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { mergeWithRules } = require('webpack-merge');
|
|
3
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
4
|
+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
|
5
|
+
const TerserPlugin = require('terser-webpack-plugin');
|
|
6
|
+
|
|
7
|
+
// 基类配置
|
|
8
|
+
const baseConfig = require('./webpack.base.js');
|
|
9
|
+
|
|
10
|
+
// 让 prod 中相同 test 的 rules 覆盖 webpack.base.js 中的 rules,避免重复命中
|
|
11
|
+
const merge = mergeWithRules({
|
|
12
|
+
module: {
|
|
13
|
+
rules: {
|
|
14
|
+
test: 'match',
|
|
15
|
+
include: 'match',
|
|
16
|
+
use: 'replace',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// 生产环境 webpack 配置
|
|
22
|
+
const webpackConfig = merge(baseConfig, {
|
|
23
|
+
// 指定生产环境
|
|
24
|
+
mode: 'production',
|
|
25
|
+
// webpack文件系统缓存
|
|
26
|
+
cache: {
|
|
27
|
+
type: 'filesystem',
|
|
28
|
+
},
|
|
29
|
+
// 生产构建通常关闭 source map
|
|
30
|
+
devtool: false,
|
|
31
|
+
// 生产环境output配置
|
|
32
|
+
output: {
|
|
33
|
+
filename: 'js/[name]_[chunkhash:8].bundle.js',
|
|
34
|
+
path: path.join(process.cwd(), './app/public/dist/prod/'),
|
|
35
|
+
publicPath: '/dist/prod/',
|
|
36
|
+
crossOriginLoading: 'anonymous',
|
|
37
|
+
clean: true, // 清空build输出目录
|
|
38
|
+
},
|
|
39
|
+
module: {
|
|
40
|
+
rules: [
|
|
41
|
+
{
|
|
42
|
+
test: /\.css$/,
|
|
43
|
+
use: [ MiniCssExtractPlugin.loader, require.resolve('css-loader') ],
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
test: /\.js$/,
|
|
47
|
+
// 对elpis目录代码进行Babel,加快webpack打包速度
|
|
48
|
+
include: [path.resolve(__dirname, '../../pages')],
|
|
49
|
+
// 对业务目录代码进行Babel,加快webpack打包速度
|
|
50
|
+
include: [path.resolve(process.cwd(), './app/pages')],
|
|
51
|
+
use: {
|
|
52
|
+
loader: require.resolve('babel-loader'),
|
|
53
|
+
options: {
|
|
54
|
+
cacheDirectory: true,
|
|
55
|
+
cacheCompression: false,
|
|
56
|
+
presets: [
|
|
57
|
+
[require.resolve('@babel/preset-env'), { modules: false }],
|
|
58
|
+
],
|
|
59
|
+
plugins: [require.resolve('@babel/plugin-transform-runtime')],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
test: /\.less$/,
|
|
65
|
+
use: [
|
|
66
|
+
MiniCssExtractPlugin.loader,
|
|
67
|
+
require.resolve('css-loader'),
|
|
68
|
+
require.resolve('less-loader'),
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
// webpack 不会有大量hints信息,默认为warning
|
|
74
|
+
performance: {
|
|
75
|
+
hints: false,
|
|
76
|
+
},
|
|
77
|
+
plugins: [
|
|
78
|
+
// 提取 css 的公共部分,有效利用缓存,(非公共部分使用inline)
|
|
79
|
+
new MiniCssExtractPlugin({
|
|
80
|
+
filename: 'css/[name]_[contenthash:8].bundle.css',
|
|
81
|
+
chunkFilename: 'css/[name]_[contenthash:8].bundle.css',
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
optimization: {
|
|
85
|
+
// 使用TerserPlugin 的并发和缓存,提升压缩阶段的性能
|
|
86
|
+
// 清除 console.log
|
|
87
|
+
minimize: true,
|
|
88
|
+
minimizer: [
|
|
89
|
+
new TerserPlugin({
|
|
90
|
+
parallel: true, // 利用多核CPU的优势来加快压缩速度
|
|
91
|
+
extractComments: false,
|
|
92
|
+
terserOptions: {
|
|
93
|
+
compress: {
|
|
94
|
+
drop_console: true,// 去掉console.log 内容
|
|
95
|
+
},
|
|
96
|
+
format: {
|
|
97
|
+
comments: false,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
}),
|
|
101
|
+
// 优化并压缩 css 资源
|
|
102
|
+
new CssMinimizerPlugin(),
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
module.exports = webpackConfig;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// 本地开发启动 devServer
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const consoler = require('consoler');
|
|
5
|
+
const webpack = require('webpack');
|
|
6
|
+
const devMiddleware = require('webpack-dev-middleware')
|
|
7
|
+
const hotMiddleware = require('webpack-hot-middleware')
|
|
8
|
+
|
|
9
|
+
module.exports = () => {
|
|
10
|
+
// 从webpack.dev.js 获取webpack配置和devServer配置
|
|
11
|
+
const {
|
|
12
|
+
webpackConfig,
|
|
13
|
+
DEV_SERVER_CONFIG
|
|
14
|
+
} = require('./config/webpack.dev.js');
|
|
15
|
+
|
|
16
|
+
const app = express();
|
|
17
|
+
|
|
18
|
+
const compiler = webpack(webpackConfig);
|
|
19
|
+
|
|
20
|
+
// 指定静态文件目录
|
|
21
|
+
app.use(express.static(path.join(__dirname, '../public/dist')));
|
|
22
|
+
|
|
23
|
+
// 引入devMiddleware中间件(监控文件改动,产物放在内存中)
|
|
24
|
+
app.use(devMiddleware(compiler, {
|
|
25
|
+
// 落地文件
|
|
26
|
+
writeToDisk: (filePath) => filePath.endsWith('.tpl'),
|
|
27
|
+
// 资源路径
|
|
28
|
+
publicPath: webpackConfig.output.publicPath,
|
|
29
|
+
headers: {
|
|
30
|
+
'Access-Control-Allow-Origin': '*',
|
|
31
|
+
'Access-Control-Allow-Methods': 'GET,POST,PUT,PATCH,DELETE,OPTIONS',
|
|
32
|
+
'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type, Authorization, Origin, Accept',
|
|
33
|
+
},
|
|
34
|
+
stats: {
|
|
35
|
+
colors: true
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
// 引入hotMiddleware中间件(实现热更新通讯)
|
|
40
|
+
app.use(hotMiddleware(compiler, {
|
|
41
|
+
path: `/${DEV_SERVER_CONFIG.HMR_PATH}`,
|
|
42
|
+
log: () => {}
|
|
43
|
+
}));
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
consoler.info('请等待webpack初次构建完成提示...')
|
|
47
|
+
|
|
48
|
+
// 启动devServer
|
|
49
|
+
const port = DEV_SERVER_CONFIG.PORT;
|
|
50
|
+
app.listen(port, () => {
|
|
51
|
+
console.log(`app listening on port: ${port}`)
|
|
52
|
+
})
|
|
53
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const webpack = require('webpack');
|
|
2
|
+
const webpackProdConfig = require('./config/webpack.prod.js');
|
|
3
|
+
|
|
4
|
+
module.exports = () => {
|
|
5
|
+
console.log('\nbuilding... \n');
|
|
6
|
+
|
|
7
|
+
webpack(webpackProdConfig, (err, stats) => {
|
|
8
|
+
if(err) { console.log(err); return; }
|
|
9
|
+
process.stdout.write(`${stats.toString({
|
|
10
|
+
colors: true, // 在控制台输出色彩信息
|
|
11
|
+
modules: false, // 不显示每个模块的打包信息
|
|
12
|
+
children: false, // 不显示子编译任务的信息
|
|
13
|
+
chunks: false, // 不显示每个代码块的信息
|
|
14
|
+
chunkModules: true, // 显示代码块中模块的信息
|
|
15
|
+
})}\n`)
|
|
16
|
+
})
|
|
17
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
{
|
|
2
|
+
model: 'dashboard'; // 模板类型,不同模板类型对应不一样的模板数据结构
|
|
3
|
+
name: ''; // 名称
|
|
4
|
+
desc: ''; // 描述
|
|
5
|
+
icon: ''; // 图标
|
|
6
|
+
homePage: ''; // 首页(项目配置)
|
|
7
|
+
// 头部菜单
|
|
8
|
+
menu: [{
|
|
9
|
+
key: '', // 菜单唯一描述
|
|
10
|
+
name: '', // 菜单名称
|
|
11
|
+
menuType: '', // 枚举值:group/module
|
|
12
|
+
|
|
13
|
+
// 当 menuType == group 时,可填
|
|
14
|
+
subMenu: [{
|
|
15
|
+
// 可递归 menuItem
|
|
16
|
+
},],
|
|
17
|
+
|
|
18
|
+
// 当 menuType == module 时,可填
|
|
19
|
+
moduleType: '', // 枚举值:sider/iframe/custom/schema
|
|
20
|
+
|
|
21
|
+
// 当 moduleType == sider 时
|
|
22
|
+
siderConfig: {
|
|
23
|
+
menu: [{
|
|
24
|
+
// 可递归 menuItem(除了menuType == sider外)
|
|
25
|
+
}]
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// 当 moduleType == iframe 时
|
|
29
|
+
iframeConfig: {
|
|
30
|
+
path: '', // iframe路径
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
// 当 moduleType == custom 时
|
|
34
|
+
customConfig: {
|
|
35
|
+
path: '', // 自定义路由路径
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// 当 moduleType == schema 时
|
|
39
|
+
schemaConfig: {
|
|
40
|
+
api: '', // 数据源API(遵循 RESTFUL 规范)
|
|
41
|
+
schema: { // 板块数据结构
|
|
42
|
+
type: 'object',
|
|
43
|
+
properties: {
|
|
44
|
+
key: {
|
|
45
|
+
...schema, // 标准 schema 配置
|
|
46
|
+
type: '', // 字段类型
|
|
47
|
+
label: '', // 字段中文名
|
|
48
|
+
// 字段在 table 中的相关配置
|
|
49
|
+
tableOption: {
|
|
50
|
+
...elTableColumnConfig, // 标准 el-table-column 配置
|
|
51
|
+
toFixed: 0, // 保留小数点后几位
|
|
52
|
+
visible: true, // 默认为 true (false时,表示不在表单中显示)
|
|
53
|
+
},
|
|
54
|
+
// 字段在 search-bar 中的相关配置
|
|
55
|
+
searchOption: {
|
|
56
|
+
...elComponentConfig, // 标准 el-table-column 配置
|
|
57
|
+
comType: '', // 配置组件类型 input/select/...
|
|
58
|
+
default: '', // 默认值
|
|
59
|
+
|
|
60
|
+
// comType === 'select' 时的相关配置
|
|
61
|
+
enumList: [], // 下拉框可选项
|
|
62
|
+
|
|
63
|
+
// comType === 'dynamicSelect' 时的相关配置
|
|
64
|
+
api: ''
|
|
65
|
+
},
|
|
66
|
+
// 字段在不同动态 component 中的相关配置,前缀对应 componentConfig 中的键值
|
|
67
|
+
// 如:componentConfig.createForm,这里对应 createFormOption
|
|
68
|
+
// 字段在 createForm 中的相关配置
|
|
69
|
+
createFormOption: {
|
|
70
|
+
...elComponentConfig, // 标准 el-component 配置
|
|
71
|
+
comType: '', // 控件类型 input/select/...
|
|
72
|
+
visible: true, // 默认为 true
|
|
73
|
+
disable: false, // 是否禁用,默认false
|
|
74
|
+
default: '', // 默认值
|
|
75
|
+
|
|
76
|
+
// comType === 'select' 时生效
|
|
77
|
+
enumList: [], // 枚举列表
|
|
78
|
+
},
|
|
79
|
+
// 字段在 editForm 表单中的相关配置
|
|
80
|
+
editFormOption: {
|
|
81
|
+
...elComponentConfig, // 标准 el-component 配置
|
|
82
|
+
comType: '', // 控件类型 input/select/...
|
|
83
|
+
visible: true, // 默认为 true
|
|
84
|
+
disable: false, // 是否禁用,默认false
|
|
85
|
+
default: '', // 默认值
|
|
86
|
+
|
|
87
|
+
// comType === 'select' 时生效
|
|
88
|
+
enumList: [], // 枚举列表
|
|
89
|
+
},
|
|
90
|
+
// 字段在 detail-panel 中的相关配置
|
|
91
|
+
detailPanelOption: {
|
|
92
|
+
...elComponentConfig, // 标准 el-component 配置
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
...
|
|
96
|
+
},
|
|
97
|
+
required: [], // 标记哪些字段是必填项
|
|
98
|
+
},
|
|
99
|
+
// table 相关配置
|
|
100
|
+
tableConfig: {
|
|
101
|
+
headerButtons: [{
|
|
102
|
+
label: '', // 按钮中文名
|
|
103
|
+
eventKey: '', // 按钮事件名
|
|
104
|
+
// 按钮事件具体配置
|
|
105
|
+
eventOption: {
|
|
106
|
+
// 当 eventKey === 'showComponent'
|
|
107
|
+
comName: '', // 组件名称
|
|
108
|
+
},
|
|
109
|
+
...elButtonConfig // 标准el-button 配置
|
|
110
|
+
},...],
|
|
111
|
+
rowButtons: [{
|
|
112
|
+
label: '', // 按钮中文名
|
|
113
|
+
eventKey: '', // 按钮事件名
|
|
114
|
+
eventOption: {
|
|
115
|
+
// 当 eventKey === 'showComponent'
|
|
116
|
+
comName: '', // 组件名称
|
|
117
|
+
|
|
118
|
+
// 当 eventKey === 'remove'
|
|
119
|
+
params: {
|
|
120
|
+
// paramsKey = 参数的键值
|
|
121
|
+
// rowValueKey = 参数值,格式为 schema::tableKey 的时候,到table中找相应的字段
|
|
122
|
+
paramsKey: rowValueKey
|
|
123
|
+
}
|
|
124
|
+
}, // 按钮事件具体配置
|
|
125
|
+
...elButtonConfig // 标准el-button 配置
|
|
126
|
+
},...],
|
|
127
|
+
},
|
|
128
|
+
// search-bar 相关配置
|
|
129
|
+
searchConfig: {},
|
|
130
|
+
// 动态组件 相关配置
|
|
131
|
+
componentConfig: {
|
|
132
|
+
// create-form 表单相关配置
|
|
133
|
+
createForm: {
|
|
134
|
+
title: '', // 表单标题
|
|
135
|
+
saveBtnText: '', // 保存按钮文案
|
|
136
|
+
},
|
|
137
|
+
// edit-form 表单相关配置
|
|
138
|
+
editForm: {
|
|
139
|
+
mainKey: '', // 表单主键,用于唯一标识要修改的数据对象
|
|
140
|
+
title: '', // 表单标题
|
|
141
|
+
saveBtnText: '', // 保存按钮文案
|
|
142
|
+
},
|
|
143
|
+
detailPanel: {
|
|
144
|
+
mainKey: '', // 表单主键,用于唯一标识要修改的数据对象
|
|
145
|
+
title: '', // 表单标题
|
|
146
|
+
}
|
|
147
|
+
// detail-panel 相关配置
|
|
148
|
+
// ...支持用户动态拓展
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
},]
|
|
153
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module.exports = (app) => {
|
|
2
|
+
return {
|
|
3
|
+
// 判断是否本地环境
|
|
4
|
+
isLocal() {
|
|
5
|
+
return process.env._ENV === 'local';
|
|
6
|
+
},
|
|
7
|
+
|
|
8
|
+
// 判断是否测试环境
|
|
9
|
+
isBeta() {
|
|
10
|
+
return process.env._ENV === 'beta';
|
|
11
|
+
},
|
|
12
|
+
|
|
13
|
+
// 判断是否生产环境
|
|
14
|
+
isProduction() {
|
|
15
|
+
return process.env._ENV === 'production';
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
// 获取当前环境
|
|
19
|
+
getEnv() {
|
|
20
|
+
return process.env._ENV ?? 'local';
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|