@infly/libs 2.0.36 → 2.0.38

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.
@@ -188,61 +188,78 @@ const userModule = {
188
188
  };
189
189
 
190
190
  // 递归更新路由权限
191
- const updateRoutesPermission = (
192
- routes = [],
193
- userPermissions = [],
194
- redirectRoute = {
195
- level0: "",
196
- level1: "",
197
- level2: ""
198
- },
199
- lastNoVerPMRoute = {
200
- level0: "",
201
- level1: "",
202
- level2: ""
203
- },
204
- level = 0
205
- ) => {
206
- const curLevelKey = `level${level}`;
207
-
191
+ // 递归应用路由权限(设置 hidden)
192
+ const applyRoutesPermission = (routes = []) => {
208
193
  routes.forEach((route) => {
209
- const { path } = route;
210
- if (route.meta && route.meta.permission && !route.hidden) {
194
+ if (route.meta?.permission && !route.hidden) {
211
195
  route.hidden = !Uts.getPM(route.meta.permission);
212
-
213
- // 记录第一级有权限控制的路由,用于重定向
214
- if (!route.hidden && !redirectRoute[curLevelKey]) {
215
- redirectRoute[curLevelKey] = route.path;
216
- }
217
196
  }
197
+ if (route.children?.length) {
198
+ applyRoutesPermission(route.children);
199
+ }
200
+ });
201
+ };
202
+
203
+ // 深度优先查找第一个可访问的叶子路由完整路径
204
+ const getFirstAccessiblePath = (routes = [], parentPath = "") => {
205
+ for (const route of routes) {
206
+ if (route.hidden || !route.path) continue;
207
+
208
+ // 绝对路径直接用,相对路径拼接父路径
209
+ const fullPath = route.path.startsWith("/")
210
+ ? route.path
211
+ : parentPath
212
+ ? `${parentPath}/${route.path}`
213
+ : route.path;
218
214
 
219
- // 记录最后一级没有权限控制的路由,用于重定向
220
- if ((!route.meta || !route.meta.permission) && !route.hidden && path) {
221
- lastNoVerPMRoute[`level${level}`] = path;
215
+ if (route.children?.length) {
216
+ const childPath = getFirstAccessiblePath(route.children, fullPath);
217
+ if (childPath) return childPath;
218
+ } else {
219
+ return fullPath;
222
220
  }
221
+ }
222
+ return "";
223
+ };
223
224
 
224
- if (route.children) {
225
- updateRoutesPermission(route.children, userPermissions, redirectRoute, lastNoVerPMRoute, level + 1);
225
+ // 更新路由权限并设置重定向
226
+ const findAccessibleRouteByPath = (routes = [], targetPath, parentPath = "") => {
227
+ if (!targetPath) return null;
228
+
229
+ for (const route of routes) {
230
+ if (route.hidden || !route.path) continue;
231
+
232
+ const fullPath = route.path.startsWith("/")
233
+ ? route.path
234
+ : parentPath
235
+ ? `${parentPath}/${route.path}`
236
+ : route.path;
237
+
238
+ if (fullPath === targetPath) {
239
+ return route;
226
240
  }
227
241
 
228
- // 处理重定向
229
- if (path === "") {
230
- let tempRoute = redirectRoute;
231
- if (!redirectRoute.level0 && !redirectRoute.level1 && !redirectRoute.level2 && lastNoVerPMRoute.level0) {
232
- tempRoute = lastNoVerPMRoute;
233
- }
234
- route.redirect = `${tempRoute.level1}/${tempRoute.level2}`;
235
- if (!tempRoute.level2) {
236
- route.redirect = `${tempRoute.level0}/${tempRoute.level1}`;
237
- }
238
-
239
- if (route.redirect === "/") {
240
- route.redirect = "*";
241
- }
242
-
243
- CONFIG.redirectRoute = route || {};
242
+ if (route.children?.length) {
243
+ const matched = findAccessibleRouteByPath(route.children, targetPath, fullPath);
244
+ if (matched) return matched;
244
245
  }
245
- });
246
+ }
247
+
248
+ return null;
249
+ };
250
+
251
+ const updateRoutesPermission = (routes = []) => {
252
+ applyRoutesPermission(routes);
253
+
254
+ const redirectRoute = routes.find((r) => r.path === "");
255
+ if (redirectRoute) {
256
+ const availableRoutes = routes.filter((r) => r.path !== "");
257
+ const initRoutePath = CONFIG.settings?.projectConfig?.initRoutePath;
258
+ const initRoute = findAccessibleRouteByPath(availableRoutes, initRoutePath);
259
+ const firstPath = getFirstAccessiblePath(availableRoutes);
260
+ redirectRoute.redirect = initRoute ? initRoutePath : firstPath || "*";
261
+ CONFIG.redirectRoute = redirectRoute;
262
+ }
246
263
  };
247
264
 
248
265
  export default {
@@ -0,0 +1,56 @@
1
+ /**
2
+ * 自动导出目录下所有文件
3
+ * @param {Function} requireContext - require.context 返回的函数
4
+ * @param {RegExp} [filePattern=/\.vue$/] - 文件匹配正则
5
+ * @returns {Object} 导出对象,key 为文件名(不含扩展名),value 为模块内容
6
+ *
7
+ * @example
8
+ * // 在 components/Dialog/index.js 中使用
9
+ * import { autoExportFiles } from '@infly/libs/tools/auto-export.js';
10
+ * const components = autoExportFiles(require.context('./', false, /\.vue$/));
11
+ * Object.keys(components).forEach(name => {
12
+ * module.exports[name] = components[name];
13
+ * });
14
+ *
15
+ * // 或者直接一行
16
+ * Object.assign(module.exports, autoExportFiles(require.context('./', false, /\.vue$/)));
17
+ */
18
+ function autoExportFiles(requireContext, filePattern = /\.vue$/) {
19
+ if (!requireContext || typeof requireContext !== 'function') {
20
+ console.error('autoExportFiles: requireContext 必须是 require.context 返回的函数');
21
+ return {};
22
+ }
23
+
24
+ const exports = {};
25
+
26
+ requireContext.keys().forEach(fileName => {
27
+ // 跳过 index 文件自身
28
+ if (fileName.includes('index')) return;
29
+
30
+ const componentConfig = requireContext(fileName);
31
+ const componentName = fileName
32
+ .replace(/^\.\//, '') // 移除 './'
33
+ .replace(/\.\w+$/, ''); // 移除扩展名
34
+
35
+ exports[componentName] = componentConfig.default || componentConfig;
36
+ });
37
+
38
+ return exports;
39
+ }
40
+
41
+ /**
42
+ * 简化版:直接挂载到 module.exports
43
+ * @param {Function} requireContext - require.context 返回的函数
44
+ * @param {Object} targetExports - 目标导出对象(通常是 module.exports)
45
+ *
46
+ * @example
47
+ * // 在 components/Dialog/index.js 中使用
48
+ * import { autoExportToModule } from '@infly/libs/tools/auto-export.js';
49
+ * autoExportToModule(require.context('./', false, /\.vue$/), module.exports);
50
+ */
51
+ function autoExportToModule(requireContext, targetExports) {
52
+ const files = autoExportFiles(requireContext);
53
+ Object.assign(targetExports, files);
54
+ }
55
+
56
+ export { autoExportFiles, autoExportToModule };
@@ -22,7 +22,9 @@ async function exportFile(config) {
22
22
  reqMethod = "get",
23
23
  Message = {},
24
24
  MessageBox = {},
25
- Loading = {}
25
+ Loading = {},
26
+ hideConfirm = false,
27
+ confirmConfig = { message: "导出筛选后的所有文件, 是否继续?" }
26
28
  } = config || {};
27
29
 
28
30
  if (!url || !request) {
@@ -76,8 +78,8 @@ async function exportFile(config) {
76
78
 
77
79
  try {
78
80
  // 2. 确认框
79
- if (MessageBox && Uts.isFunction(MessageBox.confirm)) {
80
- await MessageBox.confirm("导出筛选后的所有文件, 是否继续?", "提示", {
81
+ if (MessageBox && Uts.isFunction(MessageBox.confirm) && !hideConfirm) {
82
+ await MessageBox.confirm(confirmConfig?.message, "提示", {
81
83
  confirmButtonText: "确定",
82
84
  cancelButtonText: "取消",
83
85
  type: "warning"
@@ -103,6 +105,11 @@ async function exportFile(config) {
103
105
  showMessage("error", "导出失败:不支持的请求方法!");
104
106
  return;
105
107
  }
108
+ const { code, message } = res || {};
109
+ if (code && (code != 0 || code != 200)) {
110
+ showMessage("error", message || "导出失败!");
111
+ return;
112
+ }
106
113
 
107
114
  const blob = new Blob([res], { type: "application/octet-stream" });
108
115
  const fullFileName = `${fileName}_${new Date().toISOString().slice(0, 10)}${suffix}`;
@@ -111,17 +118,17 @@ async function exportFile(config) {
111
118
  showMessage("success", "文件导出成功!");
112
119
  } catch (err) {
113
120
  console.error("导出错误:", err);
114
- const { response } = err || {};
115
- const { status, statusText } = response || {};
121
+ const { response, message: errMsg } = err || {};
122
+ const { status, statusText, message = errMsg } = response || {};
116
123
 
117
124
  if (status === 403 || statusText === "Forbidden") {
118
125
  showMessage("error", "无操作权限!");
119
126
  } else if (status === 404) {
120
127
  showMessage("error", "导出地址未找到!");
121
- } else if (err.message && err.message.includes("timeout")) {
128
+ } else if (message && message.includes("timeout")) {
122
129
  showMessage("error", "导出超时,请稍后再试!");
123
130
  } else {
124
- showMessage("error", "导出异常,请稍后再试!");
131
+ showMessage("error", message || "导出异常,请稍后再试!");
125
132
  }
126
133
  } finally {
127
134
  hideLoading(); // 隐藏加载
@@ -149,13 +156,10 @@ const fileExportMixin = {
149
156
  Loading: this.$loading || Loading,
150
157
  request: config.request || this.$axios
151
158
  };
152
-
159
+
153
160
  return await exportFile(enhancedConfig);
154
161
  }
155
162
  }
156
163
  };
157
164
 
158
- export {
159
- exportFile,
160
- fileExportMixin
161
- };
165
+ export { exportFile, fileExportMixin };
@@ -10,126 +10,139 @@ const projectRoot = process.cwd().replace(/\\node_modules.*$/g, "");
10
10
  const projectPkgPath = path.resolve(projectRoot, "package.json");
11
11
  const projectVueConfigPath = path.resolve(projectRoot, "vue.config.js");
12
12
  const projectConfig = fs.existsSync(projectVueConfigPath) ? require(projectVueConfigPath) : {};
13
+ const projectPackage = fs.existsSync(projectPkgPath) ? require(projectPkgPath) : {};
13
14
  const rawArgv = process.argv.slice(2);
14
15
  const args = rawArgv.join(" ");
15
16
 
17
+ function getBuildContext() {
18
+ try {
19
+ return JSON.parse(process.env.INFLY_BUILD_CONTEXT || "{}");
20
+ } catch {
21
+ return {};
22
+ }
23
+ }
24
+
25
+ const buildContext = getBuildContext();
26
+
27
+ global.logColor = global.logColor || {
28
+ success: "\n\x1b[32m%s\x1b[0m",
29
+ error: "\n\x1b[31m%s\x1b[0m",
30
+ warning: "\n\x1b[33m%s\x1b[0m",
31
+ link: "\x1b[34m%s\x1b[0m",
32
+ info: "\n\x1b[36m%s\x1b[0m"
33
+ };
34
+
16
35
  const DEFAULT_CONFIG = {
17
- port: 9001,
18
- publicPath: "/",
19
- outputDir: "dist"
36
+ port: 9001,
37
+ publicPath: "/",
38
+ outputDir: "dist"
20
39
  };
21
40
 
22
41
  function scriptInit() {
23
- if (fs.existsSync(projectVueConfigPath)) {
24
- return;
25
- }
26
- scriptWrite(projectPkgPath, previewList);
42
+ if (fs.existsSync(projectVueConfigPath)) {
43
+ return;
44
+ }
45
+ scriptWrite(projectPkgPath, previewList);
27
46
  }
28
47
 
29
- /**
30
- * 检查端口是否可用
31
- * @param {number} port - 端口号
32
- * @returns {Promise<boolean>} - 端口是否可用
33
- */
34
48
  function isPortAvailable(port) {
35
- return new Promise((resolve) => {
36
- const server = net.createServer();
37
-
38
- server.listen(port, () => {
39
- server.once('close', () => {
40
- resolve(true);
41
- });
42
- server.close();
43
- });
44
-
45
- server.on('error', () => {
46
- resolve(false);
47
- });
49
+ return new Promise((resolve) => {
50
+ const server = net.createServer();
51
+
52
+ server.listen(port, () => {
53
+ server.once("close", () => {
54
+ resolve(true);
55
+ });
56
+ server.close();
57
+ });
58
+
59
+ server.on("error", () => {
60
+ resolve(false);
48
61
  });
62
+ });
49
63
  }
50
64
 
51
- /**
52
- * 查找可用端口
53
- * @param {number} startPort - 起始端口
54
- * @param {number} maxTries - 最大尝试次数
55
- * @returns {Promise<number>} - 可用端口
56
- */
57
65
  async function findAvailablePort(startPort, maxTries = 10) {
58
- for (let i = 0; i < maxTries; i++) {
59
- const port = startPort + i;
60
- const available = await isPortAvailable(port);
61
-
62
- if (available) {
63
- if (i > 0) {
64
- console.log(global.logColor.warning, `⚠️ 端口 ${startPort} 被占用,使用端口 ${port}`);
65
- }
66
- return port;
67
- }
66
+ for (let i = 0; i < maxTries; i++) {
67
+ const port = startPort + i;
68
+ const available = await isPortAvailable(port);
69
+
70
+ if (available) {
71
+ if (i > 0) {
72
+ console.log(global.logColor.warning, `⚠️ 端口 ${startPort} 被占用,使用端口 ${port}`);
73
+ }
74
+ return port;
68
75
  }
69
-
70
- throw new Error(`无法找到可用端口,已尝试从 ${startPort} 到 ${startPort + maxTries - 1}`);
76
+ }
77
+
78
+ throw new Error(`无法找到可用端口,已尝试从 ${startPort} 到 ${startPort + maxTries - 1}`);
71
79
  }
72
80
 
73
81
  async function init(skipBuild = false) {
74
- try {
75
- const { connect } = require("../lib/server/connect");
76
- const { serveStatic } = require("../lib/server/serve-static");
77
- const app = connect();
78
- const noBuild = skipBuild || rawArgv.includes("--no-build");
79
- const { devServer } = projectConfig || {};
80
- const { port: devServerPort } = devServer || {};
81
- projectConfig.port = devServerPort || DEFAULT_CONFIG.port;
82
- const { publicPath, outputDir, port } = {
83
- ...DEFAULT_CONFIG,
84
- ...projectConfig
85
- };
86
- const baseListenPort = port - 1000;
87
-
88
- if (!noBuild) {
89
- buildProject();
90
- }
91
-
92
- // ✅ 查找可用端口
93
- const listenPort = await findAvailablePort(baseListenPort);
94
-
95
- app.use(
96
- publicPath,
97
- serveStatic(outputDir, {
98
- index: ["index.html", "/"]
99
- })
100
- );
101
-
102
- const server = app.listen(listenPort, function () {
103
- console.log(global.logColor.success, `\x1b[42m\x1b[30m DONE \x1b[0m\x1b[32m 项目构建预览,CTRL + C结束:`);
104
- console.log(global.logColor.link, `http://localhost:${listenPort}${publicPath}`);
105
- });
106
-
107
- // ✅ 处理服务器启动错误
108
- server.on('error', (error) => {
109
- if (error.code === 'EADDRINUSE') {
110
- console.log(global.logColor.error, `❌ 端口 ${listenPort} 仍然被占用`);
111
- } else {
112
- console.log(global.logColor.error, `❌ 服务器启动失败:${error.message}`);
113
- }
114
- });
115
-
116
- return server;
117
- } catch (error) {
118
- console.log(global.logColor.error, `❌ 预览项目失败:${error.message}`);
119
- throw error;
82
+ try {
83
+ const { connect } = require("../lib/server/connect");
84
+ const { serveStatic } = require("../lib/server/serve-static");
85
+ const app = connect();
86
+ const noBuild = skipBuild || rawArgv.includes("--no-build");
87
+ const { devServer } = projectConfig || {};
88
+ const { port: devServerPort } = devServer || {};
89
+ projectConfig.port = devServerPort || DEFAULT_CONFIG.port;
90
+ const { publicPath, outputDir, port } = {
91
+ ...DEFAULT_CONFIG,
92
+ ...projectConfig
93
+ };
94
+ const baseListenPort = port - 1000;
95
+
96
+ if (!noBuild) {
97
+ buildProject();
120
98
  }
99
+
100
+ const listenPort = await findAvailablePort(baseListenPort);
101
+
102
+ app.use(
103
+ publicPath,
104
+ serveStatic(outputDir, {
105
+ index: ["index.html", "/"]
106
+ })
107
+ );
108
+
109
+ const server = app.listen(listenPort, function () {
110
+ const previewUrl = `http://localhost:${listenPort}${publicPath}`;
111
+
112
+ if (buildContext.batchPreview === true || process.env.INFLY_BATCH_PREVIEW === "1") {
113
+ console.log(global.logColor.link, `${projectPackage.name || path.basename(projectRoot)}: ${previewUrl}`);
114
+ return;
115
+ }
116
+
117
+ console.log(global.logColor.success, `\x1b[42m\x1b[30m DONE \x1b[0m\x1b[32m 项目构建预览,CTRL + C结束:`);
118
+ console.log(global.logColor.link, previewUrl);
119
+ });
120
+
121
+ server.on("error", (error) => {
122
+ if (error.code === "EADDRINUSE") {
123
+ console.log(global.logColor.error, `❌ 端口 ${listenPort} 仍然被占用`);
124
+ } else {
125
+ console.log(global.logColor.error, `❌ 服务器启动失败:${error.message}`);
126
+ }
127
+ });
128
+
129
+ return server;
130
+ } catch (error) {
131
+ console.log(global.logColor.error, `❌ 预览项目失败:${error.message}`);
132
+ throw error;
133
+ }
121
134
  }
122
135
 
123
136
  function buildProject() {
124
- try {
125
- execSync(`vue-cli-service build ${args}`, { stdio: "inherit" });
126
- } catch (err) {
127
- console.error(global.logColor.error, "❌ 构建失败:", err.message);
128
- process.exit(1);
129
- }
137
+ try {
138
+ execSync(`vue-cli-service build ${args}`, { stdio: "inherit" });
139
+ } catch (err) {
140
+ console.error(global.logColor.error, "❌ 构建失败:", err.message);
141
+ process.exit(1);
142
+ }
130
143
  }
131
144
 
132
145
  module.exports = {
133
- init,
134
- scriptInit
146
+ init,
147
+ scriptInit
135
148
  };
@@ -1,71 +0,0 @@
1
- // 去掉方便开发直接进入引用文件
2
- declare module "@infly/libs/module/Uts" {
3
- const Uts: any;
4
- export default Uts;
5
- }
6
-
7
- declare module "@infly/libs/module/Uts.js" {
8
- const Uts: any;
9
- export default Uts;
10
- }
11
-
12
- declare module "@infly/libs/dataInit/marketingActivitiesMap" {
13
- const marketingActivitiesMap: any;
14
- export default marketingActivitiesMap;
15
- }
16
-
17
- declare module "@infly/libs/dataInit/marketingActivitiesMap.js" {
18
- const marketingActivitiesMap: any;
19
- export default marketingActivitiesMap;
20
- }
21
-
22
- declare module "@infly/libs/dataInit/settlementMap" {
23
- const settlementMap: any;
24
- export default settlementMap;
25
- }
26
-
27
- declare module "@infly/libs/dataInit/settlementMap.js" {
28
- const settlementMap: any;
29
- export default settlementMap;
30
- }
31
-
32
- declare module "@infly/libs/dataInit/commonTypeMap" {
33
- const commonTypeMap: any;
34
- export default commonTypeMap;
35
- }
36
-
37
- declare module "@infly/libs/dataInit/commonTypeMap.js" {
38
- const commonTypeMap: any;
39
- export default commonTypeMap;
40
- }
41
- declare module "@infly/libs/tools/format" {
42
- const FormatTools: any;
43
- export default FormatTools;
44
- }
45
-
46
- declare module "@infly/libs/tools/format.js" {
47
- const FormatTools: any;
48
- export default FormatTools;
49
- }
50
-
51
- declare module "@infly/libs/module/REST" {
52
- const REST: any;
53
- export default REST;
54
- }
55
-
56
- declare module "@infly/libs/module/REST.js" {
57
- const REST: any;
58
- export default REST;
59
- }
60
-
61
- declare module "@infly/libs/module/Permission" {
62
- // 根据实际导出内容细化类型,这里先用 any
63
- const Permission: any;
64
- export default Permission;
65
- }
66
-
67
- declare module "@infly/libs/module/Permission.js" {
68
- // 根据实际导出内容细化类型,这里先用 any
69
- const Permission: any;
70
- export default Permission;
71
- }