@ticatec/uniface-flexi-module 0.2.0 → 0.2.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.
@@ -14,7 +14,7 @@ export default class FlexiCriteriaField {
14
14
  this.#set = set;
15
15
  this.visible = schema.visible != false;
16
16
  this.size = schema.size;
17
- this.label = schema.label.startsWith("@") ? utils.getVariable(schema.label) : schema.label;
17
+ this.label = utils.getScopeVariable(schema.label);
18
18
  if (schema.events) {
19
19
  for (let key in schema.events) {
20
20
  let eventHandler = schema.events[key];
@@ -23,7 +23,10 @@ export default class FlexiCriteriaField {
23
23
  }
24
24
  const cellField = CriteriaComponentBuilder.getInstance().buildField(schema, (name) => this.#set.getDictionary(name));
25
25
  this.component = cellField.component;
26
- this.#props = cellField.props;
26
+ this.#props = {};
27
+ for (let key of cellField.props) {
28
+ this.#props[key] = utils.getScopeVariable(cellField.props[key]);
29
+ }
27
30
  this.keys = cellField.keyFields;
28
31
  }
29
32
  get props() {
@@ -33,7 +33,7 @@ export default class FlexiDataTable {
33
33
  const render = colSchema.render ? this[colSchema.render] : null;
34
34
  const compareFunction = colSchema.compareFunction ? this[colSchema.compareFunction] : null;
35
35
  const column = {
36
- text: colSchema.text.startsWith("@") ? utils.getVariable(colSchema.text) : colSchema.text,
36
+ text: colSchema.text.startsWith("@") ? utils.getScopeVariable(colSchema.text) : colSchema.text,
37
37
  field: colSchema.field,
38
38
  frozen: colSchema.frozen,
39
39
  align: colSchema.align,
@@ -24,7 +24,7 @@ export default class FlexiField {
24
24
  constructor(parent, data, mode, schema) {
25
25
  this.#parent = parent;
26
26
  this.mode = mode;
27
- this.label = schema.label.startsWith("@") ? utils.getVariable(schema.label) : schema.label;
27
+ this.label = schema.label.startsWith("@") ? utils.getScopeVariable(schema.label) : schema.label;
28
28
  this.variant = schema.variant;
29
29
  this.isReadonly = schema.readonly == true;
30
30
  this.disabled = schema.disabled == true;
@@ -40,7 +40,10 @@ export default class FlexiField {
40
40
  this.#validation = this.parseValidationRule(schema.validation);
41
41
  const cellField = ComponentBuilder.getInstance().buildField(schema, (name) => card.form.getDictionary(name));
42
42
  this.component = cellField.component;
43
- this.#props = cellField.props;
43
+ this.#props = {};
44
+ for (let key of cellField.props) {
45
+ this.#props[key] = utils.getScopeVariable(cellField.props[key]);
46
+ }
44
47
  const result = utils.getParentAndKey(data, schema.keyField);
45
48
  this.keyField = result?.key;
46
49
  this.data = result?.parent;
@@ -54,6 +54,18 @@ export default abstract class FlexiForm {
54
54
  private _elements;
55
55
  private _style;
56
56
  protected constructor(data: any);
57
+ /**
58
+ * 创建响应式数据代理,只通知数据变化,不触发UI刷新
59
+ * @param data 原始数据对象
60
+ * @private
61
+ */
62
+ private createReactiveData;
63
+ /**
64
+ * 检查对象是否已经被代理
65
+ * @param obj
66
+ * @private
67
+ */
68
+ private isProxy;
57
69
  /**
58
70
  * 构造表单
59
71
  */
@@ -91,6 +103,18 @@ export default abstract class FlexiForm {
91
103
  * @param value
92
104
  */
93
105
  setInvalidateHandler(value?: FormInvalidateHandler): void;
106
+ /**
107
+ * 设置数据变化处理器(可选,用于监听字段级数据变化,不触发UI刷新)
108
+ * @param handler 回调函数,参数为(字段名, 新值, 旧值)
109
+ */
110
+ setDataChangeHandler(handler?: (fieldName: string, newValue: any, oldValue: any) => void): void;
111
+ /**
112
+ * 通知字段数据变化(由FlexiField内部调用)
113
+ * @param fieldName 字段名
114
+ * @param newValue 新值
115
+ * @param oldValue 旧值
116
+ */
117
+ notifyDataChange(fieldName: string, newValue: any, oldValue: any): void;
94
118
  /**
95
119
  * 刷新表单
96
120
  */
@@ -8,15 +8,72 @@ export default class FlexiForm {
8
8
  _props = {};
9
9
  _arrangement = "vertical";
10
10
  #data;
11
+ #rawData;
11
12
  _label$style = '';
12
13
  _variant;
13
14
  _elements;
14
15
  #invalidateHandler;
16
+ #dataChangeHandler;
15
17
  #actions;
16
18
  #dictionaries;
17
19
  _style;
18
20
  constructor(data) {
19
- this.#data = data;
21
+ this.#rawData = data;
22
+ this.#data = this.createReactiveData(data);
23
+ }
24
+ /**
25
+ * 创建响应式数据代理,只通知数据变化,不触发UI刷新
26
+ * @param data 原始数据对象
27
+ * @private
28
+ */
29
+ createReactiveData(data) {
30
+ const self = this;
31
+ const createProxy = (target, path = '') => {
32
+ return new Proxy(target, {
33
+ set(obj, prop, value) {
34
+ if (typeof prop === 'symbol') {
35
+ obj[prop] = value;
36
+ return true;
37
+ }
38
+ const oldValue = obj[prop];
39
+ // 如果新值是对象,也包装成Proxy
40
+ if (value !== null && typeof value === 'object' && !self.isProxy(value)) {
41
+ value = createProxy(value, path ? `${path}.${prop}` : prop);
42
+ }
43
+ obj[prop] = value;
44
+ // 只在值真正改变时通知(不触发invalidate)
45
+ if (oldValue !== value) {
46
+ const fieldPath = path ? `${path}.${prop}` : prop;
47
+ self.notifyDataChange(fieldPath, value, oldValue);
48
+ }
49
+ return true;
50
+ },
51
+ get(obj, prop) {
52
+ const value = obj[prop];
53
+ // 如果是对象或数组,也包装成Proxy以支持嵌套属性监听
54
+ if (value !== null && typeof value === 'object' && !self.isProxy(value)) {
55
+ const fieldPath = path ? `${path}.${String(prop)}` : String(prop);
56
+ return createProxy(value, fieldPath);
57
+ }
58
+ return value;
59
+ }
60
+ });
61
+ };
62
+ return createProxy(data);
63
+ }
64
+ /**
65
+ * 检查对象是否已经被代理
66
+ * @param obj
67
+ * @private
68
+ */
69
+ isProxy(obj) {
70
+ // 简单的检查:尝试给对象设置一个特殊属性,如果是Proxy会触发set trap
71
+ try {
72
+ return obj && obj.__isProxy === true;
73
+ }
74
+ catch {
75
+ return false;
76
+ }
20
77
  }
21
78
  /**
22
79
  * 构造表单
@@ -70,6 +127,22 @@ export default class FlexiForm {
70
127
  setInvalidateHandler(value) {
71
128
  this.#invalidateHandler = value;
72
129
  }
130
+ /**
131
+ * 设置数据变化处理器(可选,用于监听字段级数据变化,不触发UI刷新)
132
+ * @param handler 回调函数,参数为(字段名, 新值, 旧值)
133
+ */
134
+ setDataChangeHandler(handler) {
135
+ this.#dataChangeHandler = handler;
136
+ }
137
+ /**
138
+ * 通知字段数据变化(由FlexiField内部调用)
139
+ * @param fieldName 字段名
140
+ * @param newValue 新值
141
+ * @param oldValue 旧值
142
+ */
143
+ notifyDataChange(fieldName, newValue, oldValue) {
144
+ this.#dataChangeHandler?.(fieldName, newValue, oldValue);
145
+ }
73
146
  /**
74
147
  * 刷新表单
75
148
  */
package/dist/utils.d.ts CHANGED
@@ -7,6 +7,6 @@ declare const _default: {
7
7
  };
8
8
  formatText: (s: string, obj: any) => string;
9
9
  propsFilter: (attrs: any, excludes?: Array<string>) => any;
10
- getVariable: (key: string) => any;
10
+ getScopeVariable: (key: string) => any;
11
11
  };
12
12
  export default _default;
package/dist/utils.js CHANGED
@@ -5,14 +5,20 @@ const propsFilter = (attrs, excludes = []) => {
5
5
  }
6
6
  return obj;
7
7
  };
8
- const getVariable = (key) => {
9
- let attrs = key.split('.');
10
- if (attrs.length == 2) {
11
- // @ts-ignore
12
- return window[attrs[0]]?.[attrs[1]] ?? `Missing value ${key}`;
8
+ const getScopeVariable = (key) => {
9
+ if (key.startsWith("@")) {
10
+ let attrs = key.substring(1).split('.');
11
+ if (attrs.length == 2) {
12
+ let varName = attrs[0];
13
+ // @ts-ignore
14
+ return globalThis[varName]?.[attrs[1]] ?? `Missing value:${key}`;
15
+ }
16
+ else {
17
+ return `Missing key:${key}`;
18
+ }
13
19
  }
14
20
  else {
15
- return `Invalid key: ${key}`;
21
+ return key;
16
22
  }
17
23
  };
18
24
  const copyAttrs = (src, attrs) => {
@@ -62,4 +68,4 @@ const formatText = (s, obj) => {
62
68
  return obj.hasOwnProperty(key) ? String(obj[key]) : `{{${key}}}`;
63
69
  });
64
70
  };
65
- export default { copyAttrs, extractExpression, getParentAndKey, formatText, propsFilter, getVariable };
71
+ export default { copyAttrs, extractExpression, getParentAndKey, formatText, propsFilter, getScopeVariable };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ticatec/uniface-flexi-module",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "A flexible form framework for Svelte applications with dynamic field types, criteria panels, and modular components",
5
5
  "keywords": [
6
6
  "svelte",