@ticatec/uniface-flexi-module 0.0.2
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/FLEXICRITERIASET_GUIDE.md +1559 -0
- package/FLEXICRITERIASET_GUIDE_CN.md +1133 -0
- package/FLEXIDATATABLE_GUIDE.md +1650 -0
- package/FLEXIDATATABLE_GUIDE_CN.md +1650 -0
- package/FLEXIFORM_GUIDE.md +1068 -0
- package/FLEXIFORM_GUIDE_CN.md +1068 -0
- package/FLEXI_CONTEXT_GUIDE_CN.md +172 -0
- package/MODULE_LOADER_CN.md +228 -0
- package/README.md +307 -0
- package/README_CN.md +51 -0
- package/SANDBOX_CN.md +201 -0
- package/dist/FlexiContext.d.ts +28 -0
- package/dist/FlexiContext.js +45 -0
- package/dist/ModuleLoader.d.ts +41 -0
- package/dist/ModuleLoader.js +55 -0
- package/dist/Sandbox.d.ts +33 -0
- package/dist/Sandbox.js +101 -0
- package/dist/criteria-panel/CriteriaFieldsPanel.svelte +26 -0
- package/dist/criteria-panel/CriteriaFieldsPanel.svelte.d.ts +22 -0
- package/dist/criteria-panel/components/CascadeSelectSearchField.svelte +10 -0
- package/dist/criteria-panel/components/CascadeSelectSearchField.svelte.d.ts +25 -0
- package/dist/criteria-panel/components/DateRangeField.svelte +11 -0
- package/dist/criteria-panel/components/DateRangeField.svelte.d.ts +25 -0
- package/dist/criteria-panel/components/DateSearchField.svelte +10 -0
- package/dist/criteria-panel/components/DateSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/DateTimeSearchField.svelte +10 -0
- package/dist/criteria-panel/components/DateTimeSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/InputOptionSelectSearchField.svelte +9 -0
- package/dist/criteria-panel/components/InputOptionSelectSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/NumberRangeField.svelte +11 -0
- package/dist/criteria-panel/components/NumberRangeField.svelte.d.ts +25 -0
- package/dist/criteria-panel/components/NumberSearchField.svelte +9 -0
- package/dist/criteria-panel/components/NumberSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/OptionMultiSelectSearchField.svelte +9 -0
- package/dist/criteria-panel/components/OptionMultiSelectSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/OptionSelectSearchField.svelte +9 -0
- package/dist/criteria-panel/components/OptionSelectSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/SearchField.svelte +14 -0
- package/dist/criteria-panel/components/SearchField.svelte.d.ts +33 -0
- package/dist/criteria-panel/components/TextSearchField.svelte +9 -0
- package/dist/criteria-panel/components/TextSearchField.svelte.d.ts +24 -0
- package/dist/criteria-panel/components/UnknownCriteriaField.svelte +9 -0
- package/dist/criteria-panel/components/UnknownCriteriaField.svelte.d.ts +24 -0
- package/dist/criteria-panel/index.d.ts +6 -0
- package/dist/criteria-panel/index.js +6 -0
- package/dist/criteria-panel/lib/CriteriaComponentBuilder.d.ts +19 -0
- package/dist/criteria-panel/lib/CriteriaComponentBuilder.js +31 -0
- package/dist/criteria-panel/lib/CriteriaFieldBuilder.d.ts +1 -0
- package/dist/criteria-panel/lib/CriteriaFieldBuilder.js +127 -0
- package/dist/criteria-panel/lib/FlexiCriteriaField.d.ts +38 -0
- package/dist/criteria-panel/lib/FlexiCriteriaField.js +31 -0
- package/dist/criteria-panel/lib/FlexiCriteriaSet.d.ts +24 -0
- package/dist/criteria-panel/lib/FlexiCriteriaSet.js +48 -0
- package/dist/flexi-datatable/FlexiDataTable.d.ts +111 -0
- package/dist/flexi-datatable/FlexiDataTable.js +90 -0
- package/dist/flexi-datatable/index.d.ts +2 -0
- package/dist/flexi-datatable/index.js +2 -0
- package/dist/flexi-form/FlexiCompound.d.ts +34 -0
- package/dist/flexi-form/FlexiCompound.js +84 -0
- package/dist/flexi-form/FlexiFormDialog.svelte +24 -0
- package/dist/flexi-form/FlexiFormDialog.svelte.d.ts +21 -0
- package/dist/flexi-form/FlexiFormPage.svelte +26 -0
- package/dist/flexi-form/FlexiFormPage.svelte.d.ts +25 -0
- package/dist/flexi-form/Schema.d.ts +6 -0
- package/dist/flexi-form/Schema.js +1 -0
- package/dist/flexi-form/components/BreakLine.svelte +1 -0
- package/dist/flexi-form/components/BreakLine.svelte.d.ts +26 -0
- package/dist/flexi-form/components/CardTitleBar.svelte +18 -0
- package/dist/flexi-form/components/CardTitleBar.svelte.d.ts +22 -0
- package/dist/flexi-form/components/CascadeOptionSelectField.svelte +13 -0
- package/dist/flexi-form/components/CascadeOptionSelectField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/CellFieldBuilder.d.ts +1 -0
- package/dist/flexi-form/components/CellFieldBuilder.js +178 -0
- package/dist/flexi-form/components/DateField.svelte +12 -0
- package/dist/flexi-form/components/DateField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/DateTimeField.svelte +13 -0
- package/dist/flexi-form/components/DateTimeField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/InputOptionSelectField.svelte +13 -0
- package/dist/flexi-form/components/InputOptionSelectField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/MemoField.svelte +12 -0
- package/dist/flexi-form/components/MemoField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/NumberField.svelte +12 -0
- package/dist/flexi-form/components/NumberField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/OptionsMultiSelectField.svelte +13 -0
- package/dist/flexi-form/components/OptionsMultiSelectField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/OptionsSelectField.svelte +13 -0
- package/dist/flexi-form/components/OptionsSelectField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/TextField.svelte +12 -0
- package/dist/flexi-form/components/TextField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/UnitNumberField.svelte +12 -0
- package/dist/flexi-form/components/UnitNumberField.svelte.d.ts +24 -0
- package/dist/flexi-form/components/UnknownTypeField.svelte +5 -0
- package/dist/flexi-form/components/UnknownTypeField.svelte.d.ts +18 -0
- package/dist/flexi-form/containers/FlexiPanel.svelte +13 -0
- package/dist/flexi-form/containers/FlexiPanel.svelte.d.ts +33 -0
- package/dist/flexi-form/flexi_card/FlexiCard.d.ts +64 -0
- package/dist/flexi-form/flexi_card/FlexiCard.js +66 -0
- package/dist/flexi-form/flexi_card/FlexiCardPanel.svelte +57 -0
- package/dist/flexi-form/flexi_card/FlexiCardPanel.svelte.d.ts +22 -0
- package/dist/flexi-form/flexi_composite/FlexiComposite.d.ts +50 -0
- package/dist/flexi-form/flexi_composite/FlexiComposite.js +26 -0
- package/dist/flexi-form/flexi_composite/FlexiCompositePanel.svelte +42 -0
- package/dist/flexi-form/flexi_composite/FlexiCompositePanel.svelte.d.ts +25 -0
- package/dist/flexi-form/flexi_composite/README.md +50 -0
- package/dist/flexi-form/flexi_datasheet/FlexiDataSheet.d.ts +4 -0
- package/dist/flexi-form/flexi_datasheet/FlexiDataSheet.js +2 -0
- package/dist/flexi-form/flexi_field/FlexiField.d.ts +76 -0
- package/dist/flexi-form/flexi_field/FlexiField.js +128 -0
- package/dist/flexi-form/flexi_field/FlexiFieldCell.svelte +35 -0
- package/dist/flexi-form/flexi_field/FlexiFieldCell.svelte.d.ts +25 -0
- package/dist/flexi-form/flexi_field/UnknownField.d.ts +3 -0
- package/dist/flexi-form/flexi_field/UnknownField.js +3 -0
- package/dist/flexi-form/flexi_form/FlexiForm.d.ts +127 -0
- package/dist/flexi-form/flexi_form/FlexiForm.js +160 -0
- package/dist/flexi-form/flexi_form/FlexiFormPanel.svelte +57 -0
- package/dist/flexi-form/flexi_form/FlexiFormPanel.svelte.d.ts +25 -0
- package/dist/flexi-form/index.d.ts +11 -0
- package/dist/flexi-form/index.js +11 -0
- package/dist/flexi-form/lib/ComponentBuilder.d.ts +15 -0
- package/dist/flexi-form/lib/ComponentBuilder.js +31 -0
- package/dist/flexi-form/lib/index.d.ts +5 -0
- package/dist/flexi-form/lib/index.js +2 -0
- package/dist/flexi-form/lib/types.d.ts +7 -0
- package/dist/flexi-form/lib/types.js +6 -0
- package/dist/flexi-form/lib/utils.d.ts +10 -0
- package/dist/flexi-form/lib/utils.js +48 -0
- package/dist/i18n-res/i18nRes.d.ts +2 -0
- package/dist/i18n-res/i18nRes.js +8 -0
- package/dist/i18n-res/index.d.ts +2 -0
- package/dist/i18n-res/index.js +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/uniface-flexi-module.css +46 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +8 -0
- package/package.json +135 -0
package/README_CN.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# @ticatec/uniface-flexi-form
|
|
2
|
+
|
|
3
|
+
为 Svelte 应用程序提供动态表单、条件面板和动态数据表的灵活表单框架。
|
|
4
|
+
|
|
5
|
+
## 特性
|
|
6
|
+
|
|
7
|
+
- 🚀 **动态表单生成**:基于 JSON 配置动态创建表单
|
|
8
|
+
- 🎨 **多种字段类型**:支持文本、数字、日期、选择、多选等多种类型
|
|
9
|
+
- 🔍 **条件面板**:高级搜索和筛选功能
|
|
10
|
+
- 📱 **响应式设计**:移动友好和自适应布局
|
|
11
|
+
- 🧩 **模块化架构**:易于扩展自定义组件
|
|
12
|
+
- 🎯 **类型安全**:完整的 TypeScript 支持和全面的类型定义
|
|
13
|
+
- 🎭 **Svelte 5 就绪**:为最新的 Svelte 版本构建
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
## 安装
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @ticatec/uniface-flexi-form
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
## 使用方法
|
|
24
|
+
|
|
25
|
+
1. 初始化`FlexContext`,设置通用数据字典加载的接口
|
|
26
|
+
2. 初始化`ModuleLoader`,设置读取动态模块的的加载接口
|
|
27
|
+
3. 初始化`Sandbox`,注入基础类,公共对象等。
|
|
28
|
+
4. 使用ModuleLoader加载指定的动态模块,然后前台展示
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## 组件
|
|
32
|
+
|
|
33
|
+
- `FlexiContext` [详情](./FLEXI_CONTEXT_GUIDE_CN.md)
|
|
34
|
+
- `ModuleLoader` [详情](./MODULE_LOADER_CN.md)
|
|
35
|
+
- `Sandbox` [详情](./SANDBOX_CN.md)
|
|
36
|
+
- 动态表单 `FlexiForm` [详情](./FLEXIFORM_GUIDE_CN.md)
|
|
37
|
+
- 条件面板 `FlexiCriteriaSet` [详情](./FLEXICRITERIASET_GUIDE_CN.md)
|
|
38
|
+
- 动态数据表 `FlexiDataTable` [详情](./FLEXIDATATABLE_GUIDE_CN.md)
|
|
39
|
+
- 动态数据展示 **TODO**
|
|
40
|
+
|
|
41
|
+
## 贡献
|
|
42
|
+
|
|
43
|
+
我们欢迎贡献!请阅读我们的贡献指南并向我们的仓库提交 pull request。
|
|
44
|
+
|
|
45
|
+
## 许可证
|
|
46
|
+
|
|
47
|
+
MIT 许可证 - 详情请见 LICENSE 文件。
|
|
48
|
+
|
|
49
|
+
## 支持
|
|
50
|
+
|
|
51
|
+
如需支持和问题咨询,请在我们的 [GitHub 仓库](https://github.com/ticatec-auckland/uniface-flexi-form/issues) 中开启 issue。
|
package/SANDBOX_CN.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Sandbox 类文档
|
|
2
|
+
|
|
3
|
+
`Sandbox` 是一个**单例沙盒执行环境**,用于在隔离的上下文中**安全执行动态 JavaScript 代码**(如用户生成的表单逻辑、插件脚本等)。
|
|
4
|
+
通过 `Proxy` 代理与 `with` 语句结合,提供受控的变量访问,防止污染全局作用域。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 目录
|
|
9
|
+
- [概述](#概述)
|
|
10
|
+
- [核心机制](#核心机制)
|
|
11
|
+
- [静态方法](#静态方法)
|
|
12
|
+
- [`initialize`](#initialize)
|
|
13
|
+
- [实例方法](#实例方法)
|
|
14
|
+
- [`createFormClass`](#createformclass)
|
|
15
|
+
- [使用示例](#使用示例)
|
|
16
|
+
- [安全机制说明](#安全机制说明)
|
|
17
|
+
- [高级用法](#高级用法)
|
|
18
|
+
- [注意事项](#注意事项)
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 概述
|
|
23
|
+
|
|
24
|
+
`Sandbox` 设计目标:
|
|
25
|
+
- 安全执行不受信任的代码
|
|
26
|
+
- 注入指定上下文变量
|
|
27
|
+
- 防止访问未授权的全局对象
|
|
28
|
+
- 提供友好的变量访问体验(类似全局可用)
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
export default class Sandbox { ... }
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
> 典型应用:动态表单引擎、插件系统、用户自定义逻辑、微前端脚本隔离。
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 核心机制
|
|
39
|
+
|
|
40
|
+
| 机制 | 说明 |
|
|
41
|
+
|------|------|
|
|
42
|
+
| **单例模式** | 全局唯一沙盒实例 |
|
|
43
|
+
| **依赖注入** | 通过 `injectedKeys` 指定可访问变量 |
|
|
44
|
+
| **Proxy 代理** | 控制 `in` 和 `get` 访问行为 |
|
|
45
|
+
| **with + const 解构** | 让注入变量在代码中像全局变量一样使用 |
|
|
46
|
+
| **双重上下文来源** | 支持 `ctx` 和 `ctx.window` 两个来源 |
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 静态方法
|
|
51
|
+
|
|
52
|
+
### `initialize`
|
|
53
|
+
|
|
54
|
+
初始化 `Sandbox` 单例实例。
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
static initialize(ctx: any, injectedKeys: Array<string>): Sandbox
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**参数:**
|
|
61
|
+
- `ctx`: `any` - 基础上下文对象(通常包含工具函数、API 等)
|
|
62
|
+
- `injectedKeys`: `string[]` - 允许注入到沙盒的变量名列表
|
|
63
|
+
|
|
64
|
+
**返回值:** `Sandbox` 实例
|
|
65
|
+
|
|
66
|
+
> 必须先调用 `initialize`,否则无法使用 `createFormClass`。
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 实例方法
|
|
71
|
+
|
|
72
|
+
### `createFormClass`
|
|
73
|
+
|
|
74
|
+
在沙盒中执行代码字符串,生成表单类逻辑。
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
createFormClass(code: string): any
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**参数:**
|
|
81
|
+
- `code`: `string` - 要执行的 JS 代码(支持 `return` 一个类或对象)
|
|
82
|
+
|
|
83
|
+
**返回值:** 代码执行结果(通常是一个类构造函数或配置对象)
|
|
84
|
+
|
|
85
|
+
**执行流程:**
|
|
86
|
+
1. 提取 `injectedKeys` 中存在的变量 → 注入 `injected`
|
|
87
|
+
2. 合并 `ctx` + `injected` → 形成 `sandboxContext`
|
|
88
|
+
3. 创建 `Proxy` 代理,控制变量访问
|
|
89
|
+
4. 使用 `with (sandbox) { const xxx = sandbox.xxx; ...code }`
|
|
90
|
+
5. 通过 `new Function` 执行包装后的代码
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## 使用示例
|
|
95
|
+
|
|
96
|
+
### 1. 基础使用:执行表单验证逻辑
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import Sandbox from './Sandbox';
|
|
100
|
+
|
|
101
|
+
// 准备上下文
|
|
102
|
+
const context = {
|
|
103
|
+
utils: {
|
|
104
|
+
isEmail: (str) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str),
|
|
105
|
+
required: (val) => val != null && val !== ''
|
|
106
|
+
},
|
|
107
|
+
api: {
|
|
108
|
+
submitForm: async (data) => {
|
|
109
|
+
console.log('提交表单:', data);
|
|
110
|
+
return { success: true };
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
window: window // 允许访问部分全局对象(如 console, Math)
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// 定义可注入的变量
|
|
117
|
+
const injectedKeys = ['utils', 'api', 'console', 'Math', 'Date'];
|
|
118
|
+
|
|
119
|
+
// 初始化沙盒
|
|
120
|
+
Sandbox.initialize(context, injectedKeys);
|
|
121
|
+
|
|
122
|
+
const sandbox = Sandbox.initialize(context, injectedKeys);
|
|
123
|
+
|
|
124
|
+
// 用户编写的动态代码
|
|
125
|
+
const userCode = `
|
|
126
|
+
class UserForm {
|
|
127
|
+
constructor(data) {
|
|
128
|
+
this.data = data;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
validate() {
|
|
132
|
+
if (!utils.required(this.data.email)) return '邮箱必填';
|
|
133
|
+
if (!utils.isEmail(this.data.email)) return '邮箱格式错误';
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async submit() {
|
|
138
|
+
const error = this.validate();
|
|
139
|
+
if (error) throw new Error(error);
|
|
140
|
+
return await api.submitForm(this.data);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return UserForm;
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
// 执行并获取类
|
|
148
|
+
const UserFormClass = sandbox.createFormClass(userCode);
|
|
149
|
+
|
|
150
|
+
// 使用
|
|
151
|
+
const form = new UserFormClass({ email: 'test@example.com' });
|
|
152
|
+
form.submit().then(console.log).catch(console.error);
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 安全机制说明
|
|
158
|
+
|
|
159
|
+
| 机制 | 效果 |
|
|
160
|
+
|------|------|
|
|
161
|
+
| `injectedKeys` 白名单 | 仅允许显式声明的变量可访问 |
|
|
162
|
+
| `Proxy.has` 控制 | `key in sandbox` 行为受控 |
|
|
163
|
+
| `Proxy.get` 警告 | 访问未定义变量时 `console.warn` |
|
|
164
|
+
| 无 `window` 直接暴露 | 必须通过 `injectedKeys` 授权 |
|
|
165
|
+
| `with` + `const` 解构 | 避免 `with` 污染外部作用域 |
|
|
166
|
+
|
|
167
|
+
> 注意:`new Function` 本身不解析词法作用域,天然隔离外部变量。
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### 动态注入运行时变量
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
const dynamicCtx = { currentUser: null };
|
|
175
|
+
Sandbox.initialize({ ...context, dynamicCtx }, [...injectedKeys, 'currentUser']);
|
|
176
|
+
|
|
177
|
+
// 后续更新
|
|
178
|
+
dynamicCtx.currentUser = { id: 1, name: 'Alice' };
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 注意事项
|
|
184
|
+
|
|
185
|
+
| 项目 | 说明 |
|
|
186
|
+
|------|------|
|
|
187
|
+
| **必须初始化** | 未调用 `initialize` 将导致 `instance` 为 `undefined` |
|
|
188
|
+
| **injectedKeys 必须精确** | 多注入风险,少注入功能缺失 |
|
|
189
|
+
| **避免注入危险对象** | 如 `eval`, `Function`, `window.fetch`(视需求) |
|
|
190
|
+
| **性能注意** | `new Function` 有编译开销,建议缓存编译结果 |
|
|
191
|
+
| **不支持 ES6 import** | 动态代码中无法使用 `import`,需通过注入提供 |
|
|
192
|
+
| **调试建议** | 开发时可临时注入 `console` 便于调试 |
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## API 汇总
|
|
197
|
+
|
|
198
|
+
| 方法 | 类型 | 描述 |
|
|
199
|
+
|------|------|------|
|
|
200
|
+
| `initialize` | `static` | 初始化沙盒上下文 |
|
|
201
|
+
| `createFormClass` | `instance` | 执行动态代码 |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export type DictionaryLoad = (dicNames: Array<string>) => Promise<any>;
|
|
2
|
+
export type Dictionaries = {
|
|
3
|
+
[key: string]: Array<any>;
|
|
4
|
+
};
|
|
5
|
+
export default class FlexiContext {
|
|
6
|
+
private readonly _dicLoad;
|
|
7
|
+
private static instance;
|
|
8
|
+
/**
|
|
9
|
+
* 初始化Context
|
|
10
|
+
* @param dictLoad
|
|
11
|
+
*/
|
|
12
|
+
static initialize(dictLoad: DictionaryLoad): FlexiContext;
|
|
13
|
+
/**
|
|
14
|
+
* 获取单例实例
|
|
15
|
+
*/
|
|
16
|
+
static getInstance(): FlexiContext;
|
|
17
|
+
/**
|
|
18
|
+
* 构造函数
|
|
19
|
+
* @private
|
|
20
|
+
* @param dictLoad
|
|
21
|
+
*/
|
|
22
|
+
private constructor();
|
|
23
|
+
/**
|
|
24
|
+
* 读取数据字典
|
|
25
|
+
* @param dicNames
|
|
26
|
+
*/
|
|
27
|
+
loadDictionaries(dicNames: Array<string> | string): Promise<Dictionaries>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { registerFormFieldBuilder } from "./flexi-form";
|
|
2
|
+
import { registerCriteriaFieldBuilder } from "./criteria-panel";
|
|
3
|
+
export default class FlexiContext {
|
|
4
|
+
_dicLoad;
|
|
5
|
+
static instance;
|
|
6
|
+
/**
|
|
7
|
+
* 初始化Context
|
|
8
|
+
* @param dictLoad
|
|
9
|
+
*/
|
|
10
|
+
static initialize(dictLoad) {
|
|
11
|
+
if (FlexiContext.instance == null) {
|
|
12
|
+
console.log('初始化FlexContext');
|
|
13
|
+
const instance = new FlexiContext(dictLoad);
|
|
14
|
+
FlexiContext.instance = instance;
|
|
15
|
+
registerFormFieldBuilder();
|
|
16
|
+
registerCriteriaFieldBuilder();
|
|
17
|
+
}
|
|
18
|
+
return FlexiContext.instance;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* 获取单例实例
|
|
22
|
+
*/
|
|
23
|
+
static getInstance() {
|
|
24
|
+
if (!FlexiContext.instance) {
|
|
25
|
+
throw new Error("FlexiContext hasn't been initialized.");
|
|
26
|
+
}
|
|
27
|
+
return FlexiContext.instance;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 构造函数
|
|
31
|
+
* @private
|
|
32
|
+
* @param dictLoad
|
|
33
|
+
*/
|
|
34
|
+
constructor(dictLoad) {
|
|
35
|
+
this._dicLoad = dictLoad;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 读取数据字典
|
|
39
|
+
* @param dicNames
|
|
40
|
+
*/
|
|
41
|
+
async loadDictionaries(dicNames) {
|
|
42
|
+
dicNames = Array.isArray(dicNames) ? dicNames : [dicNames];
|
|
43
|
+
return dicNames.length > 0 ? await this._dicLoad(dicNames) : {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 模块加载函数的类型定义
|
|
3
|
+
* @param params - 传递给模块加载器的参数
|
|
4
|
+
* @returns 返回已加载模块的Promise
|
|
5
|
+
*/
|
|
6
|
+
export type LoadModule = (params: any) => Promise<any>;
|
|
7
|
+
/**
|
|
8
|
+
* 单例模块加载器,为动态加载的模块提供缓存功能
|
|
9
|
+
* 确保模块只加载一次,后续请求返回缓存实例
|
|
10
|
+
*/
|
|
11
|
+
export default class ModuleLoader {
|
|
12
|
+
#private;
|
|
13
|
+
/**
|
|
14
|
+
* ModuleLoader的单例实例
|
|
15
|
+
*/
|
|
16
|
+
private static instance;
|
|
17
|
+
/**
|
|
18
|
+
* 按键存储已加载模块的缓存映射
|
|
19
|
+
*/
|
|
20
|
+
private modules;
|
|
21
|
+
/**
|
|
22
|
+
* 私有构造函数,用于强制单例模式
|
|
23
|
+
* @param loadModule - 处理模块加载的函数
|
|
24
|
+
*/
|
|
25
|
+
private constructor();
|
|
26
|
+
/**
|
|
27
|
+
* 初始化单例ModuleLoader实例
|
|
28
|
+
* @param loadModule - 处理模块加载的函数
|
|
29
|
+
* @returns ModuleLoader的单例实例
|
|
30
|
+
*/
|
|
31
|
+
static initialize(loadModule: LoadModule): ModuleLoader;
|
|
32
|
+
/**
|
|
33
|
+
* 通过键加载模块,支持缓存
|
|
34
|
+
* 如果模块已存在于缓存中,则返回缓存版本
|
|
35
|
+
* 否则使用提供的loadModule函数加载模块并缓存
|
|
36
|
+
* @param key - 模块的唯一标识符
|
|
37
|
+
* @param params - 传递给模块加载器的参数
|
|
38
|
+
* @returns 返回已加载模块的Promise
|
|
39
|
+
*/
|
|
40
|
+
load(key: string, params: any): Promise<any>;
|
|
41
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单例模块加载器,为动态加载的模块提供缓存功能
|
|
3
|
+
* 确保模块只加载一次,后续请求返回缓存实例
|
|
4
|
+
*/
|
|
5
|
+
export default class ModuleLoader {
|
|
6
|
+
/**
|
|
7
|
+
* ModuleLoader的单例实例
|
|
8
|
+
*/
|
|
9
|
+
static instance;
|
|
10
|
+
/**
|
|
11
|
+
* 私有模块加载函数
|
|
12
|
+
*/
|
|
13
|
+
#loadModule;
|
|
14
|
+
/**
|
|
15
|
+
* 按键存储已加载模块的缓存映射
|
|
16
|
+
*/
|
|
17
|
+
modules;
|
|
18
|
+
/**
|
|
19
|
+
* 私有构造函数,用于强制单例模式
|
|
20
|
+
* @param loadModule - 处理模块加载的函数
|
|
21
|
+
*/
|
|
22
|
+
constructor(loadModule) {
|
|
23
|
+
this.#loadModule = loadModule;
|
|
24
|
+
this.modules = new Map;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 初始化单例ModuleLoader实例
|
|
28
|
+
* @param loadModule - 处理模块加载的函数
|
|
29
|
+
* @returns ModuleLoader的单例实例
|
|
30
|
+
*/
|
|
31
|
+
static initialize(loadModule) {
|
|
32
|
+
if (ModuleLoader.instance == null) {
|
|
33
|
+
ModuleLoader.instance = new ModuleLoader(loadModule);
|
|
34
|
+
}
|
|
35
|
+
return ModuleLoader.instance;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 通过键加载模块,支持缓存
|
|
39
|
+
* 如果模块已存在于缓存中,则返回缓存版本
|
|
40
|
+
* 否则使用提供的loadModule函数加载模块并缓存
|
|
41
|
+
* @param key - 模块的唯一标识符
|
|
42
|
+
* @param params - 传递给模块加载器的参数
|
|
43
|
+
* @returns 返回已加载模块的Promise
|
|
44
|
+
*/
|
|
45
|
+
async load(key, params) {
|
|
46
|
+
if (this.modules.has(key)) {
|
|
47
|
+
return this.modules.get(key);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const module = await this.#loadModule(params);
|
|
51
|
+
this.modules.set(key, module);
|
|
52
|
+
return module;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 单例沙盒类,用于在隔离环境中安全执行代码
|
|
3
|
+
* 提供上下文注入和代理机制来控制代码执行环境
|
|
4
|
+
*/
|
|
5
|
+
export default class Sandbox {
|
|
6
|
+
#private;
|
|
7
|
+
/**
|
|
8
|
+
* Sandbox的单例实例
|
|
9
|
+
*/
|
|
10
|
+
private static instance;
|
|
11
|
+
/**
|
|
12
|
+
* 私有构造函数,用于强制单例模式
|
|
13
|
+
* @param ctx - 沙盒执行上下文
|
|
14
|
+
* @param injectedKeys - 需要注入的变量键名数组
|
|
15
|
+
*/
|
|
16
|
+
private constructor();
|
|
17
|
+
/**
|
|
18
|
+
* 初始化单例Sandbox实例
|
|
19
|
+
* @param ctx - 沙盒执行上下文
|
|
20
|
+
* @param injectedKeys - 需要注入的变量键名数组
|
|
21
|
+
* @returns Sandbox的单例实例
|
|
22
|
+
*/
|
|
23
|
+
static initialize(ctx: any, injectedKeys: Array<string>): Sandbox;
|
|
24
|
+
/**
|
|
25
|
+
* 在沙盒环境中创建并执行表单类代码
|
|
26
|
+
* 使用代理模式控制变量访问,确保代码在安全的上下文中执行
|
|
27
|
+
* @param code - 要执行的JavaScript代码字符串
|
|
28
|
+
* @param ctx
|
|
29
|
+
* @param keys
|
|
30
|
+
* @returns 代码执行结果
|
|
31
|
+
*/
|
|
32
|
+
createFormClass(code: string, ctx?: any, keys?: Array<string>): any;
|
|
33
|
+
}
|
package/dist/Sandbox.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import FlexiContext from "./FlexiContext";
|
|
2
|
+
import { ModuleLoader } from "./index";
|
|
3
|
+
import FlexiForm from "./flexi-form/flexi_form/FlexiForm";
|
|
4
|
+
import FlexiCard from "./flexi-form/flexi_card/FlexiCard";
|
|
5
|
+
import FlexiComposite from "./flexi-form/flexi_composite/FlexiComposite";
|
|
6
|
+
import FlexiCriteriaSet from "./criteria-panel/lib/FlexiCriteriaSet";
|
|
7
|
+
import FlexiDataTable from "./flexi-datatable/FlexiDataTable";
|
|
8
|
+
import { Visibility } from "./flexi-form/lib";
|
|
9
|
+
import { FlexiFormDialog } from "./flexi-form";
|
|
10
|
+
import { FlexiFormPage } from "./flexi-form";
|
|
11
|
+
/**
|
|
12
|
+
* 单例沙盒类,用于在隔离环境中安全执行代码
|
|
13
|
+
* 提供上下文注入和代理机制来控制代码执行环境
|
|
14
|
+
*/
|
|
15
|
+
export default class Sandbox {
|
|
16
|
+
/**
|
|
17
|
+
* 私有上下文对象,包含沙盒执行环境
|
|
18
|
+
*/
|
|
19
|
+
#ctx;
|
|
20
|
+
/**
|
|
21
|
+
* 私有注入键数组,定义需要注入到沙盒的变量名
|
|
22
|
+
*/
|
|
23
|
+
#injectedKeys;
|
|
24
|
+
/**
|
|
25
|
+
* Sandbox的单例实例
|
|
26
|
+
*/
|
|
27
|
+
static instance;
|
|
28
|
+
/**
|
|
29
|
+
* 私有构造函数,用于强制单例模式
|
|
30
|
+
* @param ctx - 沙盒执行上下文
|
|
31
|
+
* @param injectedKeys - 需要注入的变量键名数组
|
|
32
|
+
*/
|
|
33
|
+
constructor(ctx, injectedKeys) {
|
|
34
|
+
this.#ctx = { ...ctx, Visibility, FlexiContext, ModuleLoader, FlexiForm, FlexiCard, FlexiComposite, FlexiCriteriaSet, FlexiDataTable, FlexiFormPage, FlexiFormDialog };
|
|
35
|
+
this.#injectedKeys = [...injectedKeys, 'Dialog', 'MessageBox', 'Indicator', 'Toast'];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* 初始化单例Sandbox实例
|
|
39
|
+
* @param ctx - 沙盒执行上下文
|
|
40
|
+
* @param injectedKeys - 需要注入的变量键名数组
|
|
41
|
+
* @returns Sandbox的单例实例
|
|
42
|
+
*/
|
|
43
|
+
static initialize(ctx, injectedKeys) {
|
|
44
|
+
if (Sandbox.instance == null) {
|
|
45
|
+
Sandbox.instance = new Sandbox(ctx, injectedKeys);
|
|
46
|
+
}
|
|
47
|
+
return Sandbox.instance;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 在沙盒环境中创建并执行表单类代码
|
|
51
|
+
* 使用代理模式控制变量访问,确保代码在安全的上下文中执行
|
|
52
|
+
* @param code - 要执行的JavaScript代码字符串
|
|
53
|
+
* @param ctx
|
|
54
|
+
* @param keys
|
|
55
|
+
* @returns 代码执行结果
|
|
56
|
+
*/
|
|
57
|
+
createFormClass(code, ctx = {}, keys = []) {
|
|
58
|
+
const injected = {};
|
|
59
|
+
ctx = { ...this.#ctx, ...ctx };
|
|
60
|
+
keys = [...new Set([...this.#injectedKeys, ...keys])];
|
|
61
|
+
for (const key of keys) {
|
|
62
|
+
if (ctx.window && key in ctx.window) {
|
|
63
|
+
injected[key] = ctx.window[key];
|
|
64
|
+
}
|
|
65
|
+
else if (key in ctx) {
|
|
66
|
+
injected[key] = ctx[key];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// 组合最终上下文
|
|
70
|
+
const sandboxContext = { ...this.#ctx, ...injected };
|
|
71
|
+
const self = this;
|
|
72
|
+
const sandbox = new Proxy(sandboxContext, {
|
|
73
|
+
has(target, key) {
|
|
74
|
+
// 如果在 sandboxContext 或 window 中存在
|
|
75
|
+
if (key in target)
|
|
76
|
+
return true;
|
|
77
|
+
if (self.#ctx.window && key in self.#ctx.window)
|
|
78
|
+
return true;
|
|
79
|
+
return false; // 不存在就返回 false
|
|
80
|
+
},
|
|
81
|
+
get(target, key) {
|
|
82
|
+
if (key in target)
|
|
83
|
+
return target[key];
|
|
84
|
+
if (self.#ctx.window && key in self.#ctx.window)
|
|
85
|
+
return self.#ctx.window[key];
|
|
86
|
+
console.warn(`Sandbox: ${String(key)} not found`);
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
const wrappedCode = `
|
|
91
|
+
with (sandbox) {
|
|
92
|
+
${Object.keys(sandbox).map(k => `const ${k} = sandbox.${k};`).join('\n')}
|
|
93
|
+
|
|
94
|
+
${code}
|
|
95
|
+
}
|
|
96
|
+
`;
|
|
97
|
+
console.log('sandbox code: ', wrappedCode);
|
|
98
|
+
const fn = new Function('sandbox', wrappedCode);
|
|
99
|
+
return fn(sandbox);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
<script lang="ts">import { onMount } from "svelte";
|
|
2
|
+
import SearchField from "./components/SearchField.svelte";
|
|
3
|
+
export let criteriaSet;
|
|
4
|
+
export let criteria;
|
|
5
|
+
let variant = criteriaSet.variant;
|
|
6
|
+
let fields = [...criteriaSet.fields];
|
|
7
|
+
let arrangement = criteriaSet.arrangement;
|
|
8
|
+
let label$style = criteriaSet.label$style;
|
|
9
|
+
onMount(async () => {
|
|
10
|
+
criteriaSet.setInvalidateHandler(() => {
|
|
11
|
+
fields = [...criteriaSet.fields];
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<div class="uniface-flexi-criteria-panel {arrangement==='horizontal' ? 'field-layout-horizontal' : ''}">
|
|
17
|
+
{#if fields}
|
|
18
|
+
{#each fields as field}
|
|
19
|
+
{#if field.visible}
|
|
20
|
+
<SearchField {label$style} size={field.size} label={field.label}>
|
|
21
|
+
<svelte:component this={field.component} props={field.props} {...field.keys} events={field.events} {variant} bind:criteria/>
|
|
22
|
+
</SearchField>
|
|
23
|
+
{/if}
|
|
24
|
+
{/each}
|
|
25
|
+
{/if}
|
|
26
|
+
</div>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type FlexiCriteriaSet from "./lib/FlexiCriteriaSet";
|
|
2
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
3
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
4
|
+
$$bindings?: Bindings;
|
|
5
|
+
} & Exports;
|
|
6
|
+
(internal: unknown, props: Props & {
|
|
7
|
+
$$events?: Events;
|
|
8
|
+
$$slots?: Slots;
|
|
9
|
+
}): Exports & {
|
|
10
|
+
$set?: any;
|
|
11
|
+
$on?: any;
|
|
12
|
+
};
|
|
13
|
+
z_$$bindings?: Bindings;
|
|
14
|
+
}
|
|
15
|
+
declare const CriteriaFieldsPanel: $$__sveltets_2_IsomorphicComponent<{
|
|
16
|
+
criteriaSet: FlexiCriteriaSet;
|
|
17
|
+
criteria: any;
|
|
18
|
+
}, {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
}, {}, {}, string>;
|
|
21
|
+
type CriteriaFieldsPanel = InstanceType<typeof CriteriaFieldsPanel>;
|
|
22
|
+
export default CriteriaFieldsPanel;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<script lang="ts">import CascadeOptionSelect from "@ticatec/uniface-element/CascadeOptionsSelect";
|
|
2
|
+
export let keyField;
|
|
3
|
+
export let textField;
|
|
4
|
+
export let criteria;
|
|
5
|
+
export let props = null;
|
|
6
|
+
export let variant;
|
|
7
|
+
export let events = null;
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<CascadeOptionSelect {...props} {...events} {variant} text={criteria[textField]} bind:value={criteria[keyField]}/>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const CascadeSelectSearchField: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
keyField: any;
|
|
16
|
+
textField: any;
|
|
17
|
+
criteria: any;
|
|
18
|
+
props?: any;
|
|
19
|
+
variant: any;
|
|
20
|
+
events?: any;
|
|
21
|
+
}, {
|
|
22
|
+
[evt: string]: CustomEvent<any>;
|
|
23
|
+
}, {}, {}, string>;
|
|
24
|
+
type CascadeSelectSearchField = InstanceType<typeof CascadeSelectSearchField>;
|
|
25
|
+
export default CascadeSelectSearchField;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">import DateRange from "@ticatec/uniface-element/DateRange";
|
|
2
|
+
export let fromField;
|
|
3
|
+
export let toField;
|
|
4
|
+
export let criteria;
|
|
5
|
+
export let props;
|
|
6
|
+
export let variant;
|
|
7
|
+
export let events = null;
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
<DateRange {...props} {...events} {variant} bind:fromValue={criteria[fromField]} bind:toValue={criteria[toField]}/>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: Props & {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const DateRangeField: $$__sveltets_2_IsomorphicComponent<{
|
|
15
|
+
fromField: any;
|
|
16
|
+
toField: any;
|
|
17
|
+
criteria: any;
|
|
18
|
+
props: any;
|
|
19
|
+
variant: any;
|
|
20
|
+
events?: any;
|
|
21
|
+
}, {
|
|
22
|
+
[evt: string]: CustomEvent<any>;
|
|
23
|
+
}, {}, {}, string>;
|
|
24
|
+
type DateRangeField = InstanceType<typeof DateRangeField>;
|
|
25
|
+
export default DateRangeField;
|