lan-low-code-cli 2.3.1 → 2.4.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/README.md CHANGED
@@ -90,6 +90,7 @@ llc form create --name <名称> [选项]
90
90
  | `--fields <names>` | 仅生成指定字段,逗号分隔 |
91
91
  | `--add-field <spec>` | **新增/调整字段**,格式 `name:label[:dataType\|controlType[:controlType]]`,可重复;见「控件类型」章节 |
92
92
  | `--option <spec>` | 为下拉/单选/多选**新建选项**:`"字段名=选项1,选项2:值2"`,可重复 |
93
+ | `--org-type <spec>` | 地址本(`address`)**可选类型**:`"字段名=机构,部门,个人"`(或编码 `1/2/4/8/16/256`,`all`=除人员身份外全部),可重复 |
93
94
  | `--detail <spec>` | **新建/调整明细表**:`"明细表标题=字段1:标题1[:控件类型],..."`,可重复,见「明细表」章节 |
94
95
  | `--include-system` | 同时把系统字段渲染到表单上(默认只渲染业务字段) |
95
96
  | `--per-row <n>` | 每行控件数,默认 2 |
@@ -224,7 +225,7 @@ control list 的数据源是 `{origin}/web/sys/artifact/elements/index.json` +
224
225
  | 数值 | `numbertext`、`moneytext`、`rate`、`slider`、`timepicker`、`daterange` |
225
226
  | 选择 | `select`、`radio`、`checkbox`(均支持 `--option` 配选项) |
226
227
  | 日期 | `timestamp`、`timeZone` |
227
- | 组织人员 | `address`(**地址本**,选人/选组织,非地址文本,见下) |
228
+ | 组织人员 | `address`(**地址本**,选人/选组织,非地址文本,见下;可用 `--org-type` 配可选类型) |
228
229
  | 附件/媒体 | `attachment`、`image`、`video` |
229
230
  | 编码/码图 | `barcode`、`qrcode` |
230
231
  | 其它 | `switch`、`hidden`、`dividing`、`subject`、`relation`、`relationQuery` |
@@ -257,7 +258,7 @@ llc form autofill --id <fdId> --apply --add-field "fd_note:说明文字:desc" --
257
258
  | 属性 | 含义 |
258
259
  |---|---|
259
260
  | `range` | 选择范围:`all`(全部组织,默认)/ `custom`(自定义——此时才出现预选相关属性) |
260
- | `org.orgTypeArr` | 可选类型,**位掩码数组**:`1`=组织、`2`=部门、`4`=岗位、`8`=人员、`16`=用户组;组合值如 `3`=组织或部门、`12`=岗位或人员、`31`=全部。CLI 默认 `['8']`(仅人员) |
261
+ | `org.orgTypeArr` | **可选类型**,编码数组:`1`=机构、`2`=部门、`4`=岗位、`8`=个人、`16`=常用群组、`256`=人员身份(仅平台开启「多身份」时可选)。CLI 默认 `['8']`(仅个人);用 `--org-type` 指定,见下 |
261
262
  | `multi` | 是否多选(默认 `false`,单选) |
262
263
  | `preSelectType` / `preSelectValue` / `nextDept` | 仅 `range='custom'` 生效(预选类型 / 预选值 / 越过部门) |
263
264
  | `relation` | 联动传值(`relationKey`/`relationValue`/`relationEnum`/`relationTableName`) |
@@ -268,13 +269,32 @@ llc form autofill --id <fdId> --apply --add-field "fd_note:说明文字:desc" --
268
269
  如 `orgTypeArr:['8']` → `ORG_PERSON`、缺省则为 `ORG_ALL`)。CLI 两者都会写入并保持一致。
269
270
 
270
271
  ```bash
271
- # 选人字段(默认:全部范围 / 仅人员 / 单选)
272
+ # 选人字段(默认:全部范围 / 仅个人 / 单选)
272
273
  llc form autofill --id <fdId> --apply --add-field "fd_owner:责任人:address"
274
+
275
+ # 指定「可选类型」:部门 + 个人(字段名 = 可选类型,可重复,同一字段按顺序合并)
276
+ llc form autofill --id <fdId> --apply \
277
+ --add-field "fd_dept_user:部门人员:address" \
278
+ --org-type "fd_dept_user=部门,个人"
279
+ --org-type "fd_dept_user=2,8" # 等价写法:编码
280
+ --org-type "fd_dept_user=all" # 机构+部门+岗位+个人+常用群组
273
281
  ```
274
282
 
275
- > 需要「多选 / 自定义范围 / 可选部门」等配置时,用设计器改(CLI 会把这些配置**原样保留**,
283
+ `--org-type` 取值支持三种写法(可混用、逗号分隔、可重复):
284
+
285
+ | 写法 | 示例 |
286
+ |---|---|
287
+ | 中文 | `机构` / `组织`、`部门`、`岗位`、`个人` / `人员`、`常用群组` / `用户组`、`人员身份` |
288
+ | 编码 | `1`、`2`、`4`、`8`、`16`、`256` |
289
+ | 英文 | `org`、`dept`、`post`、`person`、`group`、`identity` |
290
+
291
+ `all` = `1,2,4,8,16`(不含 `256`——人员身份仅在平台开启「多身份」时才是合法选项,需要时显式写)。
292
+ 写入 `controlProps.org.orgTypeArr` 时会**保留 `org` 的其余键**(如 `defaultValueType`),
293
+ 目标字段不是地址本控件时告警并跳过。
294
+
295
+ > 需要「多选 / 自定义范围 / 预选值」时仍用设计器改(CLI 会把这些配置**原样保留**,
276
296
  > 不会因为重新生成而丢失);平台预置的 `fd_creator`/`fd_owner`/`fd_alter` 等也是 `address` 类型,
277
- > 但只靠 `fdFontExtendData.orgTypeArr` 表达类型(`fd_creator`=人员、`fd_creator_dept`=部门)。
297
+ > 但只靠 `fdFontExtendData.orgTypeArr` 表达类型(`fd_creator`=个人、`fd_creator_dept`=部门)。
278
298
 
279
299
  #### 关联类控件(`relation` / `relationQuery` / `association` / …)
280
300
 
@@ -373,6 +393,15 @@ llc form autofill --id 1k4ihs42swdw2vebw38dpgr036rj6uqi0tw0 --apply --publish \
373
393
  --option "fd_col_type=研发:rd,实施:impl,运维:ops" # 省略值则按 1..n
374
394
  ```
375
395
 
396
+ `--org-type` 为**地址本**(`address`)设置「可选类型」,写入 `controlProps.org.orgTypeArr`
397
+ 与 `fdFontExtendData.orgTypeArr`(`org` 的其余键保留):
398
+
399
+ ```bash
400
+ --org-type "fd_owner=机构,部门,个人"
401
+ --org-type "fd_owner=1,2,8" # 等价写法:编码
402
+ --org-type "fd_owner=all" # 除「人员身份」外的全部
403
+ ```
404
+
376
405
  ### 明细表
377
406
 
378
407
  ```bash
@@ -375,6 +375,38 @@ function parseOptionSpecs(items) {
375
375
  }
376
376
  return result;
377
377
  }
378
+ /**
379
+ * 解析 `--org-type`:`字段名=类型1,类型2`(可重复,同一字段合并)。
380
+ *
381
+ * 类型可写编码(`1`机构 / `2`部门 / `4`岗位 / `8`个人 / `16`常用群组 / `256`人员身份)、
382
+ * 中文名或英文别名,`all` = 机构+部门+岗位+个人+常用群组。
383
+ * 落库为 `controlProps.org.orgTypeArr`(地址本控件的「可选类型」),并同步到 `fdFontExtendData`。
384
+ */
385
+ function parseOrgTypeSpecs(items) {
386
+ const result = {};
387
+ for (const raw of items) {
388
+ const eq = raw.indexOf('=');
389
+ if (eq < 0) {
390
+ throw new Error(`--org-type 格式错误:${raw},应为 "字段名=机构,部门,个人" 或 "字段名=1,2,8"`);
391
+ }
392
+ const field = raw.slice(0, eq).trim();
393
+ const tokens = raw
394
+ .slice(eq + 1)
395
+ .split(',')
396
+ .map((item) => item.trim())
397
+ .filter(Boolean);
398
+ if (!field || tokens.length === 0) {
399
+ throw new Error(`--org-type 格式错误:${raw},字段名与可选类型都不能为空`);
400
+ }
401
+ const { codes, unknown } = (0, generator_1.parseOrgTypeTokens)(tokens);
402
+ if (unknown.length) {
403
+ throw new Error(`--org-type 无法识别的可选类型:${unknown.join('、')}` +
404
+ `(可用:机构/部门/岗位/个人/常用群组/人员身份,或编码 1/2/4/8/16/256,或 all)`);
405
+ }
406
+ result[field] = Array.from(new Set([...(result[field] ?? []), ...codes]));
407
+ }
408
+ return result;
409
+ }
378
410
  /** 合并某个操作的字段权限 */
379
411
  function mergePermissions(target, fields, patch) {
380
412
  const result = { ...(target ?? {}) };
@@ -675,6 +707,7 @@ function registerFormCommand(program) {
675
707
  .option('--fields <names>', '仅生成指定字段,逗号分隔(字段名或标题)')
676
708
  .option('--add-field <spec>', '新增字段,格式 name:label[:dataType|controlType[:controlType]],可重复;例 "fd_text:单行文本"、"fd_amt:预算金额:moneytext"', collect, [])
677
709
  .option('--option <spec>', '为下拉/单选/多选新建选项:"字段名=选项1,选项2:值2",可重复', collect, [])
710
+ .option('--org-type <spec>', '地址本「可选类型」:"字段名=机构,部门,个人"(或编码 1/2/4/8/16/256,all=全部),可重复', collect, [])
678
711
  .option('--detail <spec>', '新建/调整明细表:"明细表标题=字段1:标题1,字段2:标题2:控件类型",可重复', collect, [])
679
712
  .option('--include-system', '同时把系统字段渲染到表单上(默认只渲染业务字段)')
680
713
  .option('--per-row <n>', '每行控件数量', (v) => Number(v), 2)
@@ -869,6 +902,12 @@ function registerFormCommand(program) {
869
902
  const layoutOptions = resolveLayout(opts);
870
903
  const permissions = resolvePermissions(opts);
871
904
  const optionSpecs = parseOptionSpecs(opts.option ?? []);
905
+ const orgTypes = parseOrgTypeSpecs(opts.orgType ?? []);
906
+ if (Object.keys(orgTypes).length) {
907
+ logger_1.logger.info(` 地址本可选类型:${Object.entries(orgTypes)
908
+ .map(([name, codes]) => `${name}=${(0, generator_1.orgTypeText)(codes)}`)
909
+ .join(';')}`);
910
+ }
872
911
  const actionSpecs = resolveActions(opts);
873
912
  if (actionSpecs.length) {
874
913
  logger_1.logger.info(` 控件动作:${actionSpecs.length} 个`);
@@ -911,16 +950,24 @@ function registerFormCommand(program) {
911
950
  ...layoutOptions,
912
951
  permissions,
913
952
  options: optionSpecs,
953
+ orgTypes: Object.keys(orgTypes).length ? orgTypes : undefined,
914
954
  actions: actionSpecs,
915
955
  relations: relationSpecs.length ? relationSpecs : undefined,
916
956
  });
917
957
  if (stats.optionsCompleted) {
918
958
  logger_1.logger.info(` 完善选项多语言:${stats.optionsCompleted} 个`);
919
959
  }
960
+ if (stats.orgTypesCompleted) {
961
+ logger_1.logger.info(` 地址本可选类型:${stats.orgTypesCompleted} 个字段`);
962
+ }
920
963
  if (stats.actionsCompleted) {
921
964
  logger_1.logger.info(` 配置控件动作:${stats.actionsCompleted} 个`);
922
965
  }
923
- for (const warning of [...(stats.actionWarnings ?? []), ...(stats.controlWarnings ?? [])]) {
966
+ for (const warning of [
967
+ ...(stats.actionWarnings ?? []),
968
+ ...(stats.orgTypeWarnings ?? []),
969
+ ...(stats.controlWarnings ?? []),
970
+ ]) {
924
971
  logger_1.logger.warn(warning);
925
972
  }
926
973
  assertPropValidation(stats, opts, true);
@@ -1067,6 +1114,7 @@ function registerFormCommand(program) {
1067
1114
  .option('--fields <names>', '仅处理指定字段,逗号分隔')
1068
1115
  .option('--add-field <spec>', '新增字段,格式 name:label[:dataType|controlType[:controlType]],可重复', collect, [])
1069
1116
  .option('--option <spec>', '为下拉/单选/多选新建选项:"字段名=选项1,选项2:值2",可重复', collect, [])
1117
+ .option('--org-type <spec>', '地址本「可选类型」:"字段名=机构,部门,个人"(或编码 1/2/4/8/16/256,all=全部),可重复', collect, [])
1070
1118
  .option('--detail <spec>', '新建/调整明细表:"明细表标题=字段1:标题1,字段2:标题2:控件类型",可重复', collect, [])
1071
1119
  .option('--include-system', '同时把系统字段渲染到表单上(默认只渲染业务字段)')
1072
1120
  .option('--icon <icon>', '页面图标(图标名或图标 JSON);缺失时会自动补默认图标')
@@ -1134,6 +1182,12 @@ function registerFormCommand(program) {
1134
1182
  const layoutOptions = resolveLayout(opts);
1135
1183
  const permissions = resolvePermissions(opts);
1136
1184
  const optionSpecs = parseOptionSpecs(opts.option ?? []);
1185
+ const orgTypes = parseOrgTypeSpecs(opts.orgType ?? []);
1186
+ if (Object.keys(orgTypes).length) {
1187
+ logger_1.logger.info(` 地址本可选类型:${Object.entries(orgTypes)
1188
+ .map(([name, codes]) => `${name}=${(0, generator_1.orgTypeText)(codes)}`)
1189
+ .join(';')}`);
1190
+ }
1137
1191
  if (layoutOptions.layout && layoutOptions.layout !== 'rows') {
1138
1192
  logger_1.logger.info(` 布局:${layoutOptions.layout}`);
1139
1193
  }
@@ -1179,6 +1233,7 @@ function registerFormCommand(program) {
1179
1233
  ...layoutOptions,
1180
1234
  permissions,
1181
1235
  options: optionSpecs,
1236
+ orgTypes: Object.keys(orgTypes).length ? orgTypes : undefined,
1182
1237
  actions: actionSpecs,
1183
1238
  relations: relationSpecs.length ? relationSpecs : undefined,
1184
1239
  prevFormAttr: prev.prevFormAttr,
@@ -1190,11 +1245,15 @@ function registerFormCommand(program) {
1190
1245
  if (stats.optionsCompleted) {
1191
1246
  logger_1.logger.info(` 完善选项多语言:${stats.optionsCompleted} 个`);
1192
1247
  }
1248
+ if (stats.orgTypesCompleted) {
1249
+ logger_1.logger.info(` 地址本可选类型:${stats.orgTypesCompleted} 个字段`);
1250
+ }
1193
1251
  if (stats.actionsCompleted) {
1194
1252
  logger_1.logger.info(` 配置控件动作:${stats.actionsCompleted} 个`);
1195
1253
  }
1196
1254
  for (const warning of [
1197
1255
  ...(stats.actionWarnings ?? []),
1256
+ ...(stats.orgTypeWarnings ?? []),
1198
1257
  ...(stats.layoutWarnings ?? []),
1199
1258
  ...(stats.controlWarnings ?? []),
1200
1259
  ]) {
package/dist/constants.js CHANGED
@@ -3,8 +3,8 @@
3
3
  * 常量定义:与 sys-xform 前端 util/constant.ts 中的约定保持一致。
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.FIELD_NAME_PREFIX = exports.LOCALE_PATTERN = exports.LOCALE_ALL = exports.LOCALES = exports.DEFAULT_LOCALE = exports.DEFAULT_SPAN = exports.OPTION_DICT_TYPE = exports.OPTION_CONTROL_TYPES = exports.DETAIL_CONTROL_DEFAULTS = exports.DETAIL_MAIN_FIELD_BASE = exports.DETAIL_MAIN_FIELD_OPERATIONS = exports.DETAIL_ROW_FLAGS = exports.DETAIL_OPERATIONS = exports.DETAIL_SYSTEM_FIELDS = exports.DETAIL_CONTROL = exports.CONTROL_DESIGNER_DEFAULTS = exports.CONTROL_DESIGNER_NOTES = exports.CONTROL_NOTE_WITHOUT_ERRORS = exports.RELATION_FRONT_EXTEND_PATHS = exports.CONTROL_DEFAULT_PROPS = exports.CONTROL_SEMANTIC_RULES = exports.PLACEHOLDER_PANEL_PKGS = exports.PLACEHOLDER_LANG_KEY_CANDIDATES = exports.CONTROL_PLACEHOLDER_LANG_KEYS = exports.CONTAINER_CONTROL_TYPES = exports.CONTROL_TYPE_MAP = exports.FALLBACK_CONTROL = exports.DEFAULT_CONTROL_MAP = exports.ELEMENT_ARTIFACT_PREFIX = exports.DEFAULT_SCENE_NAME = exports.DEFAULT_SCENE_CODE = exports.MODELING_ENTITY_CODE = exports.MODELING_ENTITY_NAME = exports.ENTITY_CODE = exports.ENTITY_NAME = exports.MODULE = exports.REQUIRED_PROP_DEFAULTS = exports.I18N_PROP_TABS = exports.TAB_PANE_MOBILE = exports.TAB_PANE = exports.TABS_MOBILE = exports.TABS = exports.TAB_APPEARANCE_MOBILE = exports.TAB_APPEARANCE = exports.LAYOUT_GRID_ITEM = exports.LAYOUT_GRID = exports.LAYOUT = exports.ROW = exports.APPEARANCE = exports.MAIN = void 0;
7
- exports.DEFAULT_DETAIL_CONTROL_STYLE = exports.DEFAULT_CONTROL_STYLE = exports.DEFAULT_MOBILE_THEME = exports.DEFAULT_DESKTOP_THEME = exports.DEFAULT_FORM_ICON_JSON = exports.DEFAULT_FORM_ICON = void 0;
6
+ exports.DEFAULT_LOCALE = exports.DEFAULT_SPAN = exports.OPTION_DICT_TYPE = exports.OPTION_CONTROL_TYPES = exports.DETAIL_CONTROL_DEFAULTS = exports.DETAIL_MAIN_FIELD_BASE = exports.DETAIL_MAIN_FIELD_OPERATIONS = exports.DETAIL_ROW_FLAGS = exports.DETAIL_OPERATIONS = exports.DETAIL_SYSTEM_FIELDS = exports.DETAIL_CONTROL = exports.CONTROL_DESIGNER_DEFAULTS = exports.CONTROL_DESIGNER_NOTES = exports.CONTROL_NOTE_WITHOUT_ERRORS = exports.RELATION_FRONT_EXTEND_PATHS = exports.CONTROL_DEFAULT_PROPS = exports.CONTROL_SEMANTIC_RULES = exports.PLACEHOLDER_PANEL_PKGS = exports.PLACEHOLDER_LANG_KEY_CANDIDATES = exports.CONTROL_PLACEHOLDER_LANG_KEYS = exports.CONTAINER_CONTROL_TYPES = exports.CONTROL_TYPE_MAP = exports.ORG_TYPE_LABELS = exports.ORG_TYPE_ALL = exports.ORG_TYPE_ALIASES = exports.ADDRESS_CONTROL_PKG = exports.FALLBACK_CONTROL = exports.DEFAULT_CONTROL_MAP = exports.ELEMENT_ARTIFACT_PREFIX = exports.DEFAULT_SCENE_NAME = exports.DEFAULT_SCENE_CODE = exports.MODELING_ENTITY_CODE = exports.MODELING_ENTITY_NAME = exports.ENTITY_CODE = exports.ENTITY_NAME = exports.MODULE = exports.REQUIRED_PROP_DEFAULTS = exports.I18N_PROP_TABS = exports.TAB_PANE_MOBILE = exports.TAB_PANE = exports.TABS_MOBILE = exports.TABS = exports.TAB_APPEARANCE_MOBILE = exports.TAB_APPEARANCE = exports.LAYOUT_GRID_ITEM = exports.LAYOUT_GRID = exports.LAYOUT = exports.ROW = exports.APPEARANCE = exports.MAIN = void 0;
7
+ exports.DEFAULT_DETAIL_CONTROL_STYLE = exports.DEFAULT_CONTROL_STYLE = exports.DEFAULT_MOBILE_THEME = exports.DEFAULT_DESKTOP_THEME = exports.DEFAULT_FORM_ICON_JSON = exports.DEFAULT_FORM_ICON = exports.FIELD_NAME_PREFIX = exports.LOCALE_PATTERN = exports.LOCALE_ALL = exports.LOCALES = void 0;
8
8
  /** 设计器主容器 key */
9
9
  exports.MAIN = 'main';
10
10
  /** 外观容器 */
@@ -187,6 +187,70 @@ exports.DEFAULT_CONTROL_MAP = {
187
187
  };
188
188
  /** 兜底控件(未知类型) */
189
189
  exports.FALLBACK_CONTROL = exports.DEFAULT_CONTROL_MAP.varchar;
190
+ /** 地址本控件包名(可选类型 orgTypeArr 只对此控件生效) */
191
+ exports.ADDRESS_CONTROL_PKG = '@elem/xform-address';
192
+ /**
193
+ * 地址本「可选类型」(`controlProps.org.orgTypeArr`)取值别名表。
194
+ *
195
+ * 取值依据前端 `sys-xform` 属性面板控件 `components/ide/configuration/controls/orgType/index.tsx`
196
+ * 的 options(与设计器落库数据一致):
197
+ * `1`=机构、`2`=部门、`4`=岗位、`8`=个人、`16`=常用群组;
198
+ * `256`=人员身份(仅平台开启「多身份」时该选项才出现,默认不带)。
199
+ *
200
+ * 键为 `--org-type` 允许输入的写法(编码 / 中文 / 英文),值为落库编码。
201
+ */
202
+ exports.ORG_TYPE_ALIASES = {
203
+ // 编码
204
+ '1': '1',
205
+ '2': '2',
206
+ '4': '4',
207
+ '8': '8',
208
+ '16': '16',
209
+ '256': '256',
210
+ // 中文(含常见同义写法)
211
+ 机构: '1',
212
+ 组织: '1',
213
+ 单位: '1',
214
+ 部门: '2',
215
+ 岗位: '4',
216
+ 个人: '8',
217
+ 人员: '8',
218
+ 常用群组: '16',
219
+ 用户组: '16',
220
+ 群组: '16',
221
+ 人员身份: '256',
222
+ 身份: '256',
223
+ // 英文
224
+ org: '1',
225
+ organization: '1',
226
+ organisation: '1',
227
+ dept: '2',
228
+ department: '2',
229
+ post: '4',
230
+ position: '4',
231
+ person: '8',
232
+ people: '8',
233
+ user: '8',
234
+ group: '16',
235
+ usergroup: '16',
236
+ identity: '256',
237
+ };
238
+ /**
239
+ * `all` 展开的预设项(机构/部门/岗位/个人/常用群组)。
240
+ *
241
+ * 不含 `256`(人员身份)——它仅在平台开启「多身份」时才是合法选项,
242
+ * 需要时请显式写 `256` / `人员身份`。
243
+ */
244
+ exports.ORG_TYPE_ALL = ['1', '2', '4', '8', '16'];
245
+ /** 地址本「可选类型」中文文案(用于日志/报错提示) */
246
+ exports.ORG_TYPE_LABELS = {
247
+ '1': '机构',
248
+ '2': '部门',
249
+ '4': '岗位',
250
+ '8': '个人',
251
+ '16': '常用群组',
252
+ '256': '人员身份',
253
+ };
190
254
  /**
191
255
  * 控件映射:**控件逻辑类型(xform.type)→ 桌面/移动端控件包 + 数据项类型**。
192
256
  *
@@ -1,6 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GLOBAL_ACTION_EVENTS = exports.ACTION_GLOBAL_TARGET = void 0;
4
+ exports.parseOrgTypeTokens = parseOrgTypeTokens;
5
+ exports.orgTypeText = orgTypeText;
4
6
  exports.buildRelationProps = buildRelationProps;
5
7
  exports.resolveLocales = resolveLocales;
6
8
  exports.completeOptionsI18n = completeOptionsI18n;
@@ -14,6 +16,41 @@ const constants_1 = require("../constants");
14
16
  const locale_1 = require("../utils/locale");
15
17
  const random_1 = require("../utils/random");
16
18
  const widgets_1 = require("../widgets");
19
+ /**
20
+ * 解析地址本「可选类型」输入项(`--org-type` 的等号右侧,逗号分隔)。
21
+ *
22
+ * 接受编码(`1`/`2`/`4`/`8`/`16`/`256`)、中文(机构/部门/岗位/个人/常用群组/人员身份)
23
+ * 与英文(org/dept/post/person/group/identity)写法,`all` 展开为 `ORG_TYPE_ALL`。
24
+ * 结果按 `ORG_TYPE_ALL` 的语义排序去重,便于稳定输出。
25
+ *
26
+ * @returns `codes` 落库编码(按规范顺序)、`unknown` 无法识别的输入项
27
+ */
28
+ function parseOrgTypeTokens(input) {
29
+ const codes = [];
30
+ const unknown = [];
31
+ for (const raw of input) {
32
+ const token = String(raw).trim();
33
+ if (!token)
34
+ continue;
35
+ if (token.toLowerCase() === 'all' || token === '全部') {
36
+ codes.push(...constants_1.ORG_TYPE_ALL);
37
+ continue;
38
+ }
39
+ const code = constants_1.ORG_TYPE_ALIASES[token] ?? constants_1.ORG_TYPE_ALIASES[token.toLowerCase()];
40
+ if (code)
41
+ codes.push(code);
42
+ else
43
+ unknown.push(token);
44
+ }
45
+ const order = [...constants_1.ORG_TYPE_ALL, '256'];
46
+ const unique = Array.from(new Set(codes));
47
+ unique.sort((a, b) => order.indexOf(a) - order.indexOf(b));
48
+ return { codes: unique, unknown };
49
+ }
50
+ /** 地址本「可选类型」编码 → 中文文案(用于日志) */
51
+ function orgTypeText(codes) {
52
+ return codes.map((code) => `${constants_1.ORG_TYPE_LABELS[code] ?? code}(${code})`).join('、');
53
+ }
17
54
  /** `$global`:动作目标为表单全局(onLoad / onBeforeSubmit / onAfterSubmit) */
18
55
  exports.ACTION_GLOBAL_TARGET = '$global';
19
56
  /** 建模表单的数据模型类名(业务关联的 `modelName`,取自真实表单) */
@@ -510,6 +547,14 @@ function buildFieldAttribute(params) {
510
547
  $$tableType: tableType,
511
548
  $$tableName: tableName,
512
549
  };
550
+ // 地址本「可选类型」(--org-type):覆盖 org.orgTypeArr,
551
+ // 保留 org 的其余键(defaultValueType 等)——设计器改「可选类型」时也只重置该键。
552
+ if (params.orgTypeArr?.length) {
553
+ const prevOrg = controlProps.org && typeof controlProps.org === 'object' && !Array.isArray(controlProps.org)
554
+ ? controlProps.org
555
+ : {};
556
+ controlProps.org = { ...prevOrg, orgTypeArr: params.orgTypeArr };
557
+ }
513
558
  if (typeof fdLength === 'number' && fdLength > 0) {
514
559
  controlProps.maxLength = fdLength;
515
560
  }
@@ -713,6 +758,20 @@ async function buildField(field, model, options, lang, locales) {
713
758
  return { label: key, value };
714
759
  })
715
760
  : undefined;
761
+ // 地址本「可选类型」(--org-type):仅对地址本控件生效;目标不是地址本时告警并跳过
762
+ const requestedOrgTypes = options.orgTypes?.[field.fdName];
763
+ let orgTypeArr;
764
+ let orgTypeWarning;
765
+ if (requestedOrgTypes?.length) {
766
+ if (resolved.desktopPkg === constants_1.ADDRESS_CONTROL_PKG) {
767
+ orgTypeArr = requestedOrgTypes;
768
+ }
769
+ else {
770
+ orgTypeWarning =
771
+ `--org-type 目标「${field.fdLabel || field.fdName}」不是地址本控件` +
772
+ `(当前控件:${resolved.logicalType} / ${resolved.desktopPkg}),可选类型未写入`;
773
+ }
774
+ }
716
775
  const { attribute, config } = buildFieldAttribute({
717
776
  fieldUuid: field.uuid,
718
777
  langKey,
@@ -727,6 +786,7 @@ async function buildField(field, model, options, lang, locales) {
727
786
  options: prevOptions.length ? prevOptions : defaultOptions,
728
787
  prevControlProps: prevAttr?.config?.controlProps,
729
788
  extraControlProps: relationSpec ? buildRelationProps(relationSpec) : undefined,
789
+ orgTypeArr,
730
790
  });
731
791
  field.fdAttribute = attribute;
732
792
  // 前端扩展数据同步(如 address 的 orgTypeArr/multi/range)
@@ -766,7 +826,17 @@ async function buildField(field, model, options, lang, locales) {
766
826
  const propErrors = (0, widgets_1.validateRequiredProps)(resolved.meta, config);
767
827
  // 控件语义校验(属性面板/数据源弹窗强制的规则,如业务关联的关联表单与显示项)
768
828
  const semanticErrors = validateSemanticProps(resolved.logicalType, (config.controlProps ?? {}));
769
- return { field, model, resolved, langKey, optionCount, propErrors, semanticErrors };
829
+ return {
830
+ field,
831
+ model,
832
+ resolved,
833
+ langKey,
834
+ optionCount,
835
+ orgTypeApplied: Boolean(orgTypeArr?.length),
836
+ orgTypeWarning,
837
+ propErrors,
838
+ semanticErrors,
839
+ };
770
840
  }
771
841
  /** 构建虚拟行:控件节点在持久化格式中**只保留 key 引用** */
772
842
  function buildRows(built, options) {
@@ -1453,11 +1523,18 @@ async function buildFdConfig(models, options = {}, stats) {
1453
1523
  const actionTargets = new Map();
1454
1524
  /** 必填属性校验失败汇总(对齐设计器发布前校验) */
1455
1525
  const validationErrors = [];
1526
+ /** 地址本「可选类型」(--org-type)写入告警与命中计数 */
1527
+ const orgTypeWarnings = [];
1528
+ let orgTypesCompleted = 0;
1456
1529
  for (const field of renderFields) {
1457
1530
  const builtField = await buildField(field, main, options, lang, locales);
1458
1531
  built.push(builtField);
1459
1532
  if (stats)
1460
1533
  stats.optionsCompleted += builtField.optionCount;
1534
+ if (builtField.orgTypeApplied)
1535
+ orgTypesCompleted++;
1536
+ if (builtField.orgTypeWarning)
1537
+ orgTypeWarnings.push(builtField.orgTypeWarning);
1461
1538
  actionTargets.set(builtField.field.fdName, `${mainTableName}.${builtField.field.uuid}`);
1462
1539
  for (const error of builtField.propErrors) {
1463
1540
  validationErrors.push(`字段 ${field.fdName}(${builtField.resolved.desktopPkg}):请输入${error.label}(${error.key})`);
@@ -1486,6 +1563,10 @@ async function buildFdConfig(models, options = {}, stats) {
1486
1563
  fields.push(builtField);
1487
1564
  if (stats)
1488
1565
  stats.optionsCompleted += builtField.optionCount;
1566
+ if (builtField.orgTypeApplied)
1567
+ orgTypesCompleted++;
1568
+ if (builtField.orgTypeWarning)
1569
+ orgTypeWarnings.push(builtField.orgTypeWarning);
1489
1570
  actionTargets.set(builtField.field.fdName, `${model.fdTableName}.${builtField.field.uuid}`);
1490
1571
  for (const error of builtField.propErrors) {
1491
1572
  validationErrors.push(`明细字段 ${model.fdTableName}.${field.fdName}(${builtField.resolved.desktopPkg}):请输入${error.label}(${error.key})`);
@@ -1620,6 +1701,9 @@ async function buildFdConfig(models, options = {}, stats) {
1620
1701
  const actionResult = applyControlActions(formAttr, actionTargets, options.actions ?? []);
1621
1702
  if (stats) {
1622
1703
  stats.actionsCompleted = actionResult.completed;
1704
+ stats.orgTypesCompleted = orgTypesCompleted;
1705
+ if (orgTypeWarnings.length)
1706
+ stats.orgTypeWarnings = orgTypeWarnings;
1623
1707
  if (actionResult.warnings.length)
1624
1708
  stats.actionWarnings = actionResult.warnings;
1625
1709
  if (validationErrors.length)
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ const field_1 = require("./commands/field");
9
9
  const form_1 = require("./commands/form");
10
10
  const locale_1 = require("./commands/locale");
11
11
  const logger_1 = require("./utils/logger");
12
- const VERSION = '2.3.1';
12
+ const VERSION = '2.4.0';
13
13
  const program = new commander_1.Command();
14
14
  exports.program = program;
15
15
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lan-low-code-cli",
3
- "version": "2.3.1",
3
+ "version": "2.4.0",
4
4
  "description": "lan-low-code cli:低代码表单引擎命令行工具(创建表单、获取可用字段、自动完善表单字段)",
5
5
  "keywords": [
6
6
  "low-code",