@hr-components-dev/cli 1.1.4 → 1.1.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hr-components-dev/cli",
3
- "version": "1.1.4",
3
+ "version": "1.1.5",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -32,6 +32,8 @@
32
32
  "vite.config.ts",
33
33
  "index.html",
34
34
  "tsconfig.build.json",
35
+ "!**/*.ts",
36
+ "!**/*.tsx",
35
37
  "!scripts/**/*.ts",
36
38
  "!**/*.test.js",
37
39
  "!**/*.spec.js"
@@ -1,10 +1,49 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { fileURLToPath } from 'node:url';
4
- import { dirname, join } from 'node:path';
4
+ import { dirname, join, resolve } from 'node:path';
5
+ import { existsSync, symlinkSync, unlinkSync } from 'node:fs';
5
6
  import { spawn } from 'node:child_process';
6
- import path from 'node:path';
7
7
  import consola from 'consola';
8
+
9
+ /**
10
+ * 创建软链接
11
+ */
12
+ function BuildSoftLink() {
13
+ consola.info('=== 开始构建软链接... ===');
14
+
15
+ try {
16
+ // 组件源目录 (项目根目录下的 src/components)
17
+ const source = resolve(process.cwd(), 'src/components');
18
+ // 目标链接位置 (cli 子包根目录下的 src/components)
19
+ const target = resolve(targetPackageDir, 'src/components');
20
+
21
+ consola.info(`源目录: ${source}`);
22
+ consola.info(`目标链接: ${target}`);
23
+
24
+ // 检查源目录是否存在
25
+ if (!existsSync(source)) {
26
+ consola.error('源目录不存在:', source);
27
+ process.exit(1);
28
+ }
29
+
30
+ // 如果目标链接已存在,则删除它
31
+ if (existsSync(target)) {
32
+ unlinkSync(target);
33
+ consola.info('已删除现有链接');
34
+ }
35
+
36
+ // 创建软链接
37
+ symlinkSync(source, target, 'junction'); // 使用 junction 在 Windows 上更兼容
38
+
39
+ consola.success('软链接创建成功!');
40
+ consola.info(`${target} -> ${source}`);
41
+
42
+ } catch (error) {
43
+ consola.error('创建软链接失败:', error);
44
+ process.exit(1);
45
+ }
46
+ }
8
47
  // 在文件顶部添加辅助函数
9
48
  function handleProcess(childProcess, name) {
10
49
  childProcess.on('error', (err) => {
@@ -28,10 +67,12 @@ const command = args[0];
28
67
  /**
29
68
  * cli 子包根目录
30
69
  */
31
- const targetPackageDir = path.resolve(__dirname, '../../');
70
+ const targetPackageDir = resolve(__dirname, '../../');
32
71
 
33
72
  switch (command) {
34
73
  case 'dev':
74
+ BuildSoftLink();
75
+
35
76
  // 启动开发服务器
36
77
  const viteProcess = spawn('npx', ['vite'], {
37
78
  cwd: targetPackageDir,
@@ -5,8 +5,8 @@ import consola from "consola";
5
5
  async function getAllComponents() {
6
6
  // 使用 import.meta.glob 动态导入 src/components 下的所有组件
7
7
  debugger;
8
- const modules = import.meta.glob('../../../src/components/*/index.ts');
9
- consola.info(`找到[${Object.keys(modules).length}]个组件`, '../../../src/components/*/index.ts');
8
+ const modules = import.meta.glob('/src/components/*/index.ts');
9
+ consola.info(`找到[${Object.keys(modules).length}]个组件`, '/src/components/*/index.ts');
10
10
  const components = [];
11
11
  for (const path in modules) {
12
12
  try {
@@ -1,126 +0,0 @@
1
- import type { FormControlProps } from 'amis';
2
- import _ from 'lodash';
3
-
4
- /**
5
- * 表单校验 组件 FormItem
6
- * @param props
7
- * @returns
8
- // */
9
- const EditorComponent = (_p: amis.AmisComponentPropsType) => {
10
- const throttledSuccessMessage = _.throttle(() =>
11
- _p.amisUI.toast.success('hr-editor 代码校验完成!')
12
- , 3000);
13
- // 修改节流函数,接受错误对象作为参数
14
- const throttledFailedMessage = _.throttle((o: any, title: string) => {
15
- _p.amisUI.toast.error(
16
- `${o.startLineNumber}行${o.startColumn}列,【${o.owner}】错误`,
17
- {
18
- body: `错误: ${o.message}\n\n${title}\n${o.label}`,
19
- timeout: 5000,
20
- position: "top-right"
21
- });
22
- }, 1000);
23
- const $EditorList: any = {};
24
- const $MonacoList: any = {};
25
-
26
- return (p: FormControlProps) => {
27
- const [errors, setError] = _p.react.useState<any>([]);
28
- const [name, setName] = _p.react.useState<any>(p.name);
29
- const [label, setLabel] = _p.react.useState<any>(p.label);
30
- const [editorOncahnge, setEditorOnchange] = _p.react.useState<any>(false);
31
-
32
- const get_peditor = () => $EditorList[name];
33
- const get_pmonaco = () => $MonacoList[name];
34
-
35
- _p.amislib.addRule(
36
- `Validat-${p.name}`, // 校验名
37
- (_values: any, _value: string) => {
38
- // 查找value对应的key
39
-
40
- // 校验函数,values 是表单里所有表单项的值,可用于做联合校验;value 是当前表单项的值
41
- const markers: Array<any> = get_pmonaco()?.editor?.getModelMarkers({ resource: get_peditor().getModel().uri })
42
- .filter((marker: { severity: any }) => marker.severity === get_pmonaco().MarkerSeverity.Error);
43
- setError(markers);
44
- return markers?.length === 0;
45
- },
46
- `语法共有${errors?.length}处错误,例: ${errors?.at(0)?.message ?? ''} ,请检查` // 出错时的报错信息
47
- );
48
-
49
- _p.react.useEffect(() => {
50
- if (errors?.length > 0) {
51
- errors?.forEach((o: any, _i: number) => {
52
- // 调用节流函数时传递错误对象参数
53
- throttledFailedMessage({ ...o, label }, `共:${errors.length}处`);
54
- });
55
- } else {
56
- throttledSuccessMessage();
57
- }
58
- }, [errors]);
59
-
60
- return p.render(
61
- 'body',
62
- {
63
- required: true,
64
- allowFullscreen: true,
65
- disabled: false,
66
- language: 'json',
67
- autoParseJSON: true,
68
- options: {
69
- automaticLayout: true,
70
- disableLayerHinting: true,
71
- formatOnPaste: true,
72
- minimap: {
73
- enabled: true
74
- },
75
- renderFinalNewline: true,
76
- lineNumbersMinChars: 1, // 行号最小宽度
77
- glyphMargin: true, // 显示glyph margin
78
- renderLineHighlight: 'all',
79
- renderSideBySide: true,
80
- scrollBeyondLastLine: false,
81
- selectOnLineNumbers: true,
82
- theme: 'vs',
83
- wordWrapBreakAfterCharacters: ',',
84
- wordWrapBreakBeforeCharacters: ',',
85
- // 新增配置项
86
- fontSize: 19,
87
- fontFamily: '微软雅黑',
88
- cursorStyle: 'line', // 光标样式: 'line', 'block', 'underline'
89
- cursorBlinking: 'smooth', // 光标闪烁: 'blink', 'smooth', 'phase', 'expand', 'solid'
90
- cursorSmoothCaretAnimation: true // 平滑插入动画
91
- },
92
- ...p.$schema,
93
- editorDidMount: (editor: any, monaco: any) => {
94
- setEditorOnchange(true);
95
- const changeListener = editor.onDidChangeModelContent(() => {
96
- setLabel(`字段: ${p.label.split(' ').slice(0, 2).join(' ')}`);
97
- setName(p.name);
98
- });
99
- $EditorList[p.name!] = editor;
100
- $MonacoList[p.name!] = monaco;
101
-
102
- // eslint-disable-next-line no-bitwise
103
- editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS, () => {
104
- editor.trigger('keyboard', 'editor.action.formatDocument');
105
- });
106
-
107
- return () => {
108
- changeListener.dispose();
109
- // 清除残留的节流调用
110
- throttledSuccessMessage.cancel();
111
- throttledFailedMessage.cancel();
112
- };
113
- },
114
- validateOnChange: editorOncahnge,
115
- validations: {
116
- [`Validat-${p.name}`]: true
117
- },
118
- type: 'editor'
119
- },
120
- {
121
- // props: p
122
- }
123
- );
124
- };
125
- };
126
- export default EditorComponent;
@@ -1,53 +0,0 @@
1
- import type { FormControlProps } from 'amis';
2
-
3
-
4
-
5
- /**
6
- * 表单校验 组件 FormItem
7
- * @param props
8
- * @returns
9
- // */
10
- const EditorFormItemComponent = (_p: amis.AmisComponentPropsType) => {
11
- const { useRef } = _p.react;
12
- return (p: FormControlProps) => {
13
- const _dom: any = useRef(null);
14
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
15
- const { name, type, label, ...other } = p.$schema;
16
- return p.render(
17
- 'body',
18
- {
19
- type: 'button',
20
- label,
21
- actionType: 'dialog',
22
- dialog: {
23
- onEvent: {
24
- // confirm: {
25
- // actions: [
26
- // {
27
- // actionType: 'custom',
28
- // script: (_ctx: any, _act: any, e: { parentDefault: () => void }) => {
29
- // e.parentDefault();
30
- // }
31
- // }
32
- // ]
33
- // }
34
- },
35
- title: "编辑器",
36
- size: 'full',
37
- body: {
38
- type: 'hr-editor',
39
- onChange: p.onChange,
40
- onBulkChange: p.onBulkChange,
41
- name: p.name,
42
- ...other
43
- }
44
- }
45
- },
46
- {
47
- // props: p
48
- }
49
- );
50
- };
51
- };
52
-
53
- export default EditorFormItemComponent;
@@ -1,141 +0,0 @@
1
- import type { AxiosResponse } from 'axios';
2
- import dayjs from 'dayjs';
3
- import _ from 'lodash';
4
- import consola from 'consola';
5
- import { disAutoConnect, autoConnect, hiprint } from '@sv-print/hiprint';
6
- import type { IScopedContext } from 'amis';
7
- import { loadAmisSDK } from '@maita/amis-tools';
8
- import axios from 'axios';
9
- disAutoConnect();
10
-
11
-
12
-
13
-
14
-
15
- /**
16
- * 动态执行给定的作用域表达式,并返回处理后的上下文和数据。
17
- *
18
- * @param scope - 要执行的动态表达式字符串。
19
- * @returns 包含 `context` 和 `data` 的对象。如果 `scope` 为空,则返回空对象。
20
- */
21
- export const evalFc = async (
22
- scopeStr: string,
23
- instance?: IScopedContext & amis.TypeEmbed
24
- ): Promise<{
25
- data?: Record<string, string | number | boolean | null | undefined>;
26
- context?: Record<string, any>;
27
- }> => {
28
- const getAmis = async () => {
29
- if (!window.amisRequire) await loadAmisSDK();
30
- return new Promise((res, rej) => {
31
- try {
32
- window.amisRequire(['amis-ui', 'amis', 'amis-formula', 'react', 'amis-core'], (...args: any[]) => {
33
- const [ui, lib, formula, react, core] = args;
34
- res({ ui, lib, formula, react, core });
35
- });
36
- } catch (error) {
37
- consola.error('amisRequire 加载失败,部分功能可能无法使用', error);
38
- rej(error);
39
- }
40
- });
41
- };
42
-
43
- const eval2 = (express: string) => {
44
- // eslint-disable-next-line no-new-func
45
- return new Function('instance', '_', 'axios', 'hiprint', 'hiprintConnect', 'dayjs', 'amis', `return ${express}`);
46
- };
47
- const dynamicCode = eval2(`(${scopeStr})`)(
48
- instance,
49
- _,
50
- axios,
51
- hiprint.PrintTemplate,
52
- autoConnect,
53
- dayjs,
54
- await getAmis()
55
- );
56
-
57
- const Scope: {
58
- data?: Record<string, string | number | boolean | null | undefined>;
59
- context?: Record<string, any>;
60
- } = {
61
- context: dynamicCode.context,
62
- data: dynamicCode.data
63
- };
64
-
65
- return Scope;
66
- };
67
-
68
- /**
69
- * 递归转换数组Schema类型的$字符串表达式
70
- * @param orgobj 含$字符串的Schema表达式的对象
71
- * @param args Title ,entity,user 参数
72
- * @returns 计算后的对象
73
- */
74
- export function ConvertSchemaMarkToJSON<T>(orgobj: Record<string, any>, scope: any): T {
75
- const eval2 = (express: string) => {
76
- // eslint-disable-next-line no-new-func
77
- return new Function('scope', `return ${express.replace('{{', '').replace('}}', '')}`);
78
- };
79
-
80
- /**
81
- * 递归处理对象
82
- * @param obj 当前处理的对象
83
- * @returns 处理后的对象
84
- */
85
- const getObject = (obj: Record<string, any> | string): any => {
86
- // 处理对象
87
- const targetObj: Record<string, any> = {};
88
- if (typeof obj === 'number') {
89
- return obj;
90
- } else if (typeof obj === 'string') {
91
- if (/{{.*}}/.test(obj)) obj = eval2(obj)(scope);
92
- return obj;
93
- }
94
-
95
- for (const key in obj) {
96
- if (Object.hasOwn(obj, key)) {
97
- const value = obj[key];
98
- // 递归处理对象或数组
99
- if (Array.isArray(value)) {
100
- targetObj[key] = value.map(item => getObject(item));
101
- } else if (typeof value === 'object') {
102
- targetObj[key] = getObject(value);
103
- }
104
- // 处理包含 {{}} 的字符串
105
- else if (typeof value === 'string' && /{{.*}}/.test(value)) {
106
- targetObj[key] = eval2(value)(scope);
107
- } else targetObj[key] = value;
108
- }
109
- }
110
- return targetObj;
111
- };
112
- return getObject(orgobj);
113
- }
114
-
115
- /**
116
- * 封装response数据为一个文件下载
117
- * @param response - Axios 响应对象
118
- * @returns 如果服务端返回的是一个blob 则返回一个文件下载
119
- */
120
- export const responeToDownLoad = (response: AxiosResponse<any>) => {
121
- let filename = '文件打包.zip';
122
- const contentDisposition = response.headers['content-disposition'] || response.headers['Content-Disposition'];
123
- // 解析 Content-Disposition 头以获取文件名
124
- if (contentDisposition) {
125
- const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
126
- if (filenameMatch && filenameMatch[1]) {
127
- filename = decodeURIComponent(filenameMatch[1].replace(/['"]/g, ''));
128
- }
129
- }
130
-
131
- const downloadUrl = window.URL.createObjectURL(new Blob([response.data as unknown as BlobPart]));
132
- const link = document.createElement('a');
133
- link.style.display = 'none';
134
- link.href = downloadUrl;
135
- link.setAttribute('download', filename); // 设置下载的文件名
136
- document.body.appendChild(link);
137
- link.click();
138
- document.body.removeChild(link);
139
- window.URL.revokeObjectURL(downloadUrl);
140
- return { msg: '下载成功', status: 0, data: {} }; // 不进行 Amis 渲染
141
- };
@@ -1,4 +0,0 @@
1
- export * from './registerAmisComponent';
2
- export * from './setupAmisConfig';
3
- export * from './evalScope';
4
-
@@ -1,27 +0,0 @@
1
- import type React from 'react';
2
-
3
- /**
4
- * 注册amis 自定义组件
5
- * @param amislib amisReauire amis库
6
- * @param react amisReauire react库
7
- */
8
- export const registerAmisComponent = (p: amis.AmisComponentPropsType) => {
9
- const registerComponent = (
10
- name: string,
11
- hook: (props: amis.AmisComponentPropsType) => React.ComponentType<any>,
12
- isFormItem: boolean = false
13
- ) => {
14
- if (!p.amislib.getFormItemByName(name.toLocaleLowerCase())) {
15
- const state = isFormItem
16
- ? p.amislib.FormItem({ type: name.toLocaleLowerCase() })(hook(p)) // 注册 formitem 组件
17
- : p.amislib.Renderer({ type: name.toLocaleLowerCase() })(hook(p)); // 注册 renderer 组件
18
- return state;
19
- }
20
- return p.amislib.getRendererByName(name.toLocaleLowerCase());
21
- };
22
-
23
- return registerComponent;
24
- };
25
-
26
- export default registerAmisComponent;
27
-
@@ -1,25 +0,0 @@
1
- import { MaitaGlobalConfig, loadAmisSDK } from '@maita/amis-tools';
2
-
3
- /** 设置Amis配置 */
4
- export const setupAmisConfig = () => {
5
- const _cf = new MaitaGlobalConfig();
6
- (async () => {
7
- // 定义的通用window方法,供amis设计器使用
8
- const newJsFunc = {
9
- /**
10
- * 浏览器动态列缓存
11
- *
12
- * @param ctx amis context上下文
13
- * @param event amis event事件
14
- * @param clear 是否清除 默认false
15
- */
16
- // dynimicColumnCache: (_ctx: any, _event: any, _clear: boolean = false) => {},
17
- // dynimicColumnSave: (_ctx: any, _event: any, _clear: boolean = false) => {}
18
- };
19
- // if (!window.amisRequire) {
20
- // await loadAmisSDK();
21
- // }
22
-
23
- Object.assign((window as any).__JSFunc, newJsFunc);
24
- })();
25
- };
package/src/main.ts DELETED
@@ -1,6 +0,0 @@
1
- import { createApp } from 'vue'
2
- import './style.css'
3
- // import '../src/assets/@fortawesome/fontawesome-free/css/all.min.css';
4
- import App from './App.vue'
5
-
6
- createApp(App).mount('#app')
@@ -1,183 +0,0 @@
1
- #!/usr/bin/env node
2
- import { build } from "vite";
3
- import vue from "@vitejs/plugin-vue";
4
- import vueJsx from "@vitejs/plugin-vue-jsx";
5
- import { dirname, resolve } from "path";
6
- import { existsSync, readdirSync, readFileSync, statSync } from "fs";
7
- import cssInjectedByJsPlugin from "vite-plugin-css-injected-by-js";
8
- import consola from "consola";
9
-
10
- // 查找项目根目录
11
- export const findProjectRoot = (startDir: string): string => {
12
- let currentDir = startDir;
13
-
14
- // 向上搜索直到找到标识性的文件或达到系统根目录
15
- while (currentDir !== dirname(currentDir)) {
16
- const pkgPath = resolve(currentDir, 'package.json');
17
- if (existsSync(pkgPath)) {
18
- try {
19
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
20
-
21
- // 检查是否为根目录的更可靠方法:
22
- // 1. 是否包含 workspaces 字段
23
- // 2. 是否包含 src 目录
24
- // 3. 是否包含特定的根项目标识
25
- if (pkg.workspaces || existsSync(resolve(currentDir, 'src'))) {
26
- // 验证是否存在 src/components 目录
27
- if (existsSync(resolve(currentDir, 'src', 'components'))) {
28
- return currentDir;
29
- }
30
- }
31
- } catch (e) {
32
- // 忽略解析错误,继续向上搜索
33
- }
34
- }
35
- currentDir = dirname(currentDir);
36
- }
37
-
38
- // 如果没找到根目录,则尝试使用命令行参数或者环境变量
39
- const argv = require('yargs').argv;
40
- if (argv.root) {
41
- return resolve(argv.root);
42
- }
43
-
44
- if (process.env.PROJECT_ROOT) {
45
- return resolve(process.env.PROJECT_ROOT);
46
- }
47
-
48
- // 最后的备选方案:返回初始目录
49
- return startDir;
50
- }
51
-
52
-
53
- // 获取项目根目录
54
- const projectRoot = findProjectRoot(process.cwd());
55
-
56
-
57
- // 将连字符命名转换为大驼峰命名(PascalCase)
58
- function toPascalCase(str: string) {
59
- // 将连字符命名转换为驼峰命名
60
- function toCamelCase(str: string) {
61
- return str.replace(/-([a-z])/g, (g) => g[1].toUpperCase());
62
- }
63
- const camelCase = toCamelCase(str);
64
- return camelCase.charAt(0).toUpperCase() + camelCase.slice(1);
65
- }
66
-
67
- // 获取所有组件名称
68
- function getAllComponents() {
69
- consola.info('projectRoot:', projectRoot);
70
- const srcDir = resolve(projectRoot, "src/components");
71
-
72
- if (!existsSync(srcDir)) {
73
- console.error(`源目录不存在: ${srcDir}`);
74
- process.exit(1);
75
- }
76
-
77
- const components = [];
78
- const items = readdirSync(srcDir);
79
-
80
- for (const item of items) {
81
- const itemPath = resolve(srcDir, item);
82
- if (statSync(itemPath).isDirectory()) {
83
- const entryFile = resolve(itemPath, "index.ts");
84
- if (existsSync(entryFile)) {
85
- components.push(item);
86
- }
87
- }
88
- }
89
-
90
- return components;
91
- }
92
-
93
- async function buildComponent(componentName: string) {
94
- const srcDir = resolve(projectRoot, "src/components");
95
- const componentDir = resolve(srcDir, componentName);
96
- const entryFile = resolve(componentDir, "index.ts");
97
-
98
- // 转换为合法的 JS 标识符
99
- const legalName = toPascalCase(componentName);
100
-
101
- // 检查组件目录和入口文件是否存在
102
- if (!existsSync(componentDir)) {
103
- console.error(`组件目录不存在: ${componentDir}`);
104
- process.exit(1);
105
- }
106
-
107
- if (!existsSync(entryFile)) {
108
- console.error(`入口文件不存在: ${entryFile}`);
109
- process.exit(1);
110
- }
111
-
112
- try {
113
- await build({
114
- root: process.cwd(),
115
- configFile: false,
116
- plugins: [vue(), vueJsx(), cssInjectedByJsPlugin()],
117
- build: {
118
- lib: {
119
- entry: entryFile,
120
- name: legalName,
121
- fileName: (format) => {
122
- // 为不同格式生成不同的文件名
123
- const name = format == "iife" ? "index.js" : `index.${format}.js`;
124
- return name;
125
- },
126
- formats: ["es", "umd", "iife", "system", "cjs"], // 使用 ES 格式
127
- },
128
- outDir: resolve(process.cwd(), "dist", componentName),
129
- emptyOutDir: true,
130
- rollupOptions: {
131
- external: ["vue"],
132
- output: {
133
- globals: {
134
- vue: "Vue",
135
- },
136
- paths: {
137
- // vue: "https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.prod.js", // 可选:指定vue的CDN路径
138
- },
139
- },
140
- },
141
- cssCodeSplit: false, // 禁用 CSS 代码分割,将所有 CSS 合并
142
- cssMinify: true, // 压缩 CSS
143
- },
144
- define: {
145
- "process.env.NODE_ENV": JSON.stringify("production"),
146
- },
147
- });
148
-
149
- console.log(`✅ 组件 ${componentName} 构建完成`);
150
- } catch (error) {
151
- console.error(`❌ 组件 ${componentName} 构建失败:`, error);
152
- process.exit(1);
153
- }
154
- }
155
-
156
- // 获取命令行参数
157
- const args = process.argv.slice(2);
158
-
159
- // 处理不同的参数情况
160
- if (args.length === 0 || (args.length === 1 && args[0] === "--all")) {
161
- // 批量构建所有组件
162
- const components = getAllComponents();
163
-
164
- if (components.length === 0) {
165
- console.warn("未找到任何组件");
166
- process.exit(0);
167
- }
168
-
169
- console.log(`发现 ${components.length} 个组件,开始批量构建...`);
170
-
171
- for (const component of components) {
172
- await buildComponent(component);
173
- }
174
-
175
- console.log("✅ 所有组件构建完成");
176
- } else if (args.length === 1) {
177
- // 构建单个组件
178
- const componentName = args[0];
179
- await buildComponent(componentName);
180
- } else {
181
- console.error("参数错误:请提供组件名称或使用 --all 参数构建所有组件");
182
- process.exit(1);
183
- }
@@ -1,57 +0,0 @@
1
- // component-preview.js
2
- import { createServer } from "vite";
3
- import { writeFileSync, existsSync } from "fs";
4
- import path, { resolve } from "path";
5
-
6
- const componentPath = process.argv[2];
7
-
8
- if (!componentPath) {
9
- console.error(
10
- "请提供组件路径,例如: node script/component-preview.js /hr-test/HelloWorld.vue"
11
- );
12
- process.exit(1);
13
- }
14
-
15
- if (!existsSync("./src/components/" + componentPath)) {
16
- console.error(`组件文件不存在: ${"./src/components/" + componentPath}`);
17
- process.exit(1);
18
- }
19
-
20
- // 生成临时预览文件
21
- const previewHtml = `
22
- <!DOCTYPE html>
23
- <html lang="en">
24
- <head>
25
- <meta charset="UTF-8">
26
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
27
- <title>Component Preview</title>
28
- </head>
29
- <body>
30
- <div id="app"></div>
31
- <script type="module">
32
- import { createApp } from 'vue'
33
- import Component from '${"./src/components/" + componentPath.replace(/\\/g, "/")
34
- }'
35
-
36
- createApp(Component, {
37
- msg: 'Component Preview'
38
- }).mount('#app')
39
- </script>
40
- </body>
41
- </html>`;
42
-
43
- writeFileSync("./temp-preview.html", previewHtml);
44
-
45
- // 启动 Vite 服务器
46
- const v = import.meta;
47
- const configFile = path.resolve(v.dirname, '../../') + "/vite.config.ts";
48
- const server = await createServer({
49
- configFile,
50
- root: process.cwd(),
51
- server: {
52
- open: "./temp-preview.html",
53
- },
54
- });
55
-
56
- await server.listen(5167);
57
- server.printUrls();
@@ -1,90 +0,0 @@
1
- import path from 'node:path';
2
- import fs from 'node:fs';
3
- import { viteStaticCopy } from 'vite-plugin-static-copy';
4
-
5
- const copyDirectory = (source: string, destination: string) => {
6
- // 确保目标目录存在
7
- fs.mkdirSync(destination, { recursive: true });
8
-
9
- // 读取源目录内容
10
- const entries = fs.readdirSync(source, { withFileTypes: true });
11
-
12
- for (const entry of entries) {
13
- const srcPath = path.join(source, entry.name);
14
- const destPath = path.join(destination, entry.name);
15
-
16
- if (entry.isDirectory()) {
17
- // 递归复制目录
18
- copyDirectory(srcPath, destPath);
19
- } else {
20
- // 复制文件(使用 COPYFILE_FICLONE_FORCE 标志避免符号链接)
21
- try {
22
- fs.copyFileSync(srcPath, destPath, fs.constants.COPYFILE_FICLONE_FORCE);
23
- } catch (error) {
24
- // 如果强制复制失败,使用普通复制
25
- fs.copyFileSync(srcPath, destPath);
26
- }
27
- }
28
- }
29
- };
30
-
31
- const copyNodeModulesSdk = (targetPath: string) => {
32
- // 定义路径
33
- const assetsSdkPath = path.resolve(__dirname, `../../assets/${targetPath}`).replace(/\\/g, '/');
34
- const nodeModulesSdkPath = path.resolve(__dirname, `../../../node_modules/${targetPath}`).replace(/\\/g, '/');
35
-
36
- // 检查 assets 目录是否存在 SDK 文件
37
- if (fs.existsSync(assetsSdkPath)) {
38
- // 如果 assets 目录存在 SDK,则使用它
39
- return assetsSdkPath;
40
- } else if (fs.existsSync(nodeModulesSdkPath)) {
41
- // 如果 assets 目录不存在,但 node_modules 中有,则使用 node_modules 的
42
- // 同时将文件复制到 assets 目录以便下次使用
43
- const destAssetsSdkPath = path.resolve(__dirname, `../../assets/${targetPath}`);
44
-
45
- // 确保目标目录存在
46
- fs.mkdirSync(path.dirname(destAssetsSdkPath), { recursive: true });
47
-
48
- // 如果目标目录已存在,先删除
49
- if (fs.existsSync(destAssetsSdkPath)) {
50
- fs.rmSync(destAssetsSdkPath, { recursive: true });
51
- }
52
-
53
- // 使用自定义复制函数进行递归复制(避免符号链接问题)
54
- try {
55
- copyDirectory(nodeModulesSdkPath, destAssetsSdkPath);
56
- } catch (error) {
57
- console.error('Failed to copy directory:', error);
58
- // 如果复制失败,直接返回 node_modules 路径
59
- return nodeModulesSdkPath;
60
- }
61
-
62
- return destAssetsSdkPath;
63
- } else {
64
- throw new Error(`${targetPath} not found in either assets or node_modules`);
65
- }
66
- };
67
-
68
-
69
-
70
- export default function setupAmisPlugin() {
71
-
72
-
73
- const amisPath = copyNodeModulesSdk('/amis/sdk');
74
- // const fontawesome = copyNodeModulesSdk('/@fortawesome/fontawesome-free')
75
-
76
- // console.log(fontawesome);
77
-
78
- return viteStaticCopy({
79
- targets: [
80
- {
81
- src: `${amisPath}/[!.]*`,
82
- dest: 'amis/sdk'
83
- },
84
- // {
85
- // src: `${fontawesome}/[!.]*`,
86
- // dest: '@fortawesome'
87
- // }
88
- ]
89
- });
90
- }
@@ -1,88 +0,0 @@
1
- import consola from "consola";
2
- import type { ComponentType } from 'react'; // 引入 React 类型
3
-
4
- // 定义组件项的接口
5
- interface ComponentItem {
6
- 组件名: string;
7
- 组件包: {
8
- default: (props: amis.AmisComponentPropsType) => ComponentType<any>;
9
- isFormItem: boolean;
10
- };
11
- 组件类型: string;
12
- 注册状态: string;
13
- }
14
-
15
- /**
16
- * 获取所有组件名称列表
17
- */
18
- async function getAllComponents(): Promise<ComponentItem[]> {
19
- // 使用 import.meta.glob 动态导入 src/components 下的所有组件
20
- debugger
21
- const modules = import.meta.glob<{
22
- default: (props: amis.AmisComponentPropsType) => ComponentType<any>,
23
- isFormItem: boolean
24
- }>('../../../src/components/*/index.ts');
25
-
26
- consola.info(`找到[${Object.keys(modules).length}]个组件`, '../../../src/components/*/index.ts');
27
-
28
- const components: ComponentItem[] = [];
29
- for (const path in modules) {
30
- try {
31
- const loader = modules[path];
32
- if (!loader) continue; // 防止 undefined 调用
33
- const module = await loader();
34
- // 从路径中提取组件名称
35
- const componentName = path.match(/\/components\/(.+?)\//)?.[1];
36
- if (componentName) {
37
- components.push({
38
- 组件名: componentName,
39
- 组件包: module,
40
- 组件类型: module.isFormItem ? '@FormItem' : '@Renderer',
41
- 注册状态: '未注册'
42
- });
43
- }
44
- } catch (error) {
45
- consola.error(`加载组件失败: ${path}`, error);
46
- }
47
- }
48
- consola.info(`找到[${components.length}]个待注册组件`);
49
- return components;
50
- }
51
-
52
- /**
53
- * 自动注册组件函数 *
54
- * @param register - 组件注册函数,用于将组件注册到系统中
55
- * @returns 无返回值的异步函数
56
- */
57
- export const autoRegisterComponent = async (
58
- register: (
59
- name: string,
60
- hook: (props: amis.AmisComponentPropsType) => ComponentType<any>,
61
- isFormItem?: boolean
62
- ) => any
63
- ) => {
64
- consola.start('开始自动注册组件....');
65
- const components = await getAllComponents();
66
-
67
- // 注册每个组件
68
- for (let i = 0; i < components.length; i++) {
69
- const component = components[i];
70
- if (!component) continue;
71
-
72
- try {
73
- const componentModule = component.组件包;
74
-
75
- if (componentModule.default) {
76
- register(component.组件名, componentModule.default, componentModule.isFormItem);
77
- consola.success(`组件注册 【${component.组件名}】 成功`);
78
- component.注册状态 = '成功'; // 直接使用已存在的 component 对象
79
- }
80
- } catch (error) {
81
- consola.error(`注册组件失败: ${component.组件名}`, error);
82
- component.注册状态 = '失败'; // 同样直接赋值
83
- }
84
- }
85
- console.table(components);
86
- };
87
-
88
- export default autoRegisterComponent;
@@ -1,66 +0,0 @@
1
- import type { RootRenderProps } from 'amis-core/lib/Root';
2
- import type { FormControlProps, IScopedContext, Schema } from 'amis';
3
- import type * as vue from 'vue';
4
- import React, { JSX } from 'react';
5
-
6
- type PathModule = 'amis' | 'amis/embed' | 'amis-core' | 'react' | 'amis-ui' | 'amis-formula';
7
- type AmisRequireCallback<T extends string | string[]> = T extends string
8
- ? (arg1: any) => void
9
- : T extends Array<infer U>
10
- ? U extends string
11
- ? ((...args: any[]) => void) & { length: T['length'] }
12
- : never
13
- : never;
14
-
15
-
16
- declare global {
17
- export interface Window {
18
- amisRequire: <T extends PathModule | PathModule[]>(path: T, callback?: AmisRequireCallback<T>) => any;
19
- }
20
- namespace amis {
21
- type TypeEmbed = {
22
- updateProps: (props: Partial<RootRenderProps>, callback?: (p: Partial<RootRenderProps>, s: Schema) => void) => void;
23
- updateSchema: (
24
- newSchema: Schema,
25
- props?: Partial<RootRenderProps>,
26
- callback?: (p: Partial<RootRenderProps>, s: Schema) => void
27
- ) => void;
28
- unmount: () => void;
29
- };
30
-
31
- type AmisComponentPropsType = {
32
- /**
33
- * Vue.es 模块
34
- */
35
- vue: typeof vue;
36
- /**
37
- * React.es 模块
38
- */
39
- react: typeof React;
40
- /**
41
- * amis 模块
42
- */
43
- amislib: any;
44
- /**
45
- * amis-ui 模块
46
- */
47
- amisUI: any;
48
- /**
49
- * 当前amis 实例
50
- */
51
- scoped: IScopedContext & TypeEmbed;
52
- /**
53
- * 当前语言
54
- */
55
- locale: string;
56
- /**
57
- * 当前主题
58
- */
59
- theme: "dark" | "antd" | "cxd" | "ang";
60
- };
61
-
62
- type ComponentsFc<T = amis.AmisComponentPropsType> = (_p: T) => (_sp: FormControlProps) => React.ReactElement<React.DOMAttributes<Element>, any> | JSX.Element;
63
-
64
-
65
- }
66
- }