lan-low-code-cli 2.5.0 → 2.7.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 +183 -0
- package/dist/api/flow.js +119 -0
- package/dist/api/formDefine.js +31 -1
- package/dist/api/operation.js +27 -0
- package/dist/api/template.js +76 -0
- package/dist/api/view.js +23 -0
- package/dist/commands/flow.js +755 -0
- package/dist/commands/form.js +181 -1
- package/dist/commands/operation.js +730 -0
- package/dist/commands/template.js +541 -0
- package/dist/generator/flow/compiler.js +397 -0
- package/dist/generator/flow/index.js +22 -0
- package/dist/generator/flow/layout.js +136 -0
- package/dist/generator/flow/schema-resolver.js +133 -0
- package/dist/generator/flow/schema.js +96 -0
- package/dist/generator/flow/types.js +10 -0
- package/dist/generator/flow/validate.js +129 -0
- package/dist/index.js +20 -1
- package/package.json +49 -49
- package/skills/lan-low-code-cli/SKILL.md +20 -5
- package/skills/lan-low-code-cli/SKILL.zh-CN.md +19 -4
- package/skills/lan-low-code-cli/references/cli-contract.md +167 -8
- package/skills/lan-low-code-cli/references/cli-contract.zh-CN.md +162 -7
- package/skills/lan-low-code-cli/references/mkxform-api.md +2652 -2652
- package/skills/lan-low-code-cli/references/operation-script-context.md +220 -0
package/dist/commands/form.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.injectNewFields = injectNewFields;
|
|
3
4
|
exports.registerFormCommand = registerFormCommand;
|
|
4
5
|
const fs_1 = require("fs");
|
|
5
6
|
const path_1 = require("path");
|
|
@@ -674,6 +675,155 @@ async function loadModels(client, formId, fromModel) {
|
|
|
674
675
|
}
|
|
675
676
|
return (await formDefine_1.dataModelApi.loadByFormId(client, formId)) ?? [];
|
|
676
677
|
}
|
|
678
|
+
/** 分类表单默认图标(与平台分类表单弹窗一致) */
|
|
679
|
+
const CATEGORY_FORM_ICON = {
|
|
680
|
+
category: '{"name":"iconCommon_line_16_classificationTemplateModel","type":"vector","style":{"backgroundColor":"","color":"#F6940A","borderRadius":0,"fontSize":""},"normalize":true}',
|
|
681
|
+
simpleCategory: '{"name":"iconCommon_line_16_simpleClassificationModel","type":"vector","style":{"backgroundColor":"","color":"#5D4DD5","borderRadius":0,"fontSize":""},"normalize":true}',
|
|
682
|
+
};
|
|
683
|
+
function normalizeCategoryType(raw) {
|
|
684
|
+
if (!raw)
|
|
685
|
+
return undefined;
|
|
686
|
+
const key = raw.trim().toLowerCase().replace(/[-_\s]/g, '');
|
|
687
|
+
if (key === 'category' || key === 'categoryform')
|
|
688
|
+
return 'category';
|
|
689
|
+
if (key === 'simplecategory' || key === 'simplecategoryform')
|
|
690
|
+
return 'simpleCategory';
|
|
691
|
+
return undefined;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* 构造分类表单的 mechanisms:init 返回的每个机制补上 fdName / fdTableName(主表名),
|
|
695
|
+
* 与前端 categoryModal 的 mergeData 保持一致。
|
|
696
|
+
*/
|
|
697
|
+
function buildCategoryMechanisms(source, fdName, fdTableName) {
|
|
698
|
+
const result = {};
|
|
699
|
+
Object.keys(source ?? {}).forEach((key) => {
|
|
700
|
+
const value = source?.[key];
|
|
701
|
+
result[key] = {
|
|
702
|
+
...(value && typeof value === 'object' ? value : {}),
|
|
703
|
+
fdName,
|
|
704
|
+
fdTableName,
|
|
705
|
+
};
|
|
706
|
+
});
|
|
707
|
+
return result;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* 创建分类表单 / 简单分类表单:categoryModel/init → add →(--publish 时 save + publish)。
|
|
711
|
+
*
|
|
712
|
+
* 注意:分类表单本身不含业务字段,字段属于「模板(模板表单)」;
|
|
713
|
+
* 模板表元数据由平台设计器首次保存时生成,CLI 侧 template 创建需在该操作之后。
|
|
714
|
+
*/
|
|
715
|
+
async function createCategoryForm(client, opts, type) {
|
|
716
|
+
const appId = String(opts.appId ?? '').trim();
|
|
717
|
+
if (!appId)
|
|
718
|
+
throw new Error('分类表单(--type category|simpleCategory)必须提供 --app-id');
|
|
719
|
+
if (opts.addField?.length || opts.fields || opts.fromModel) {
|
|
720
|
+
throw new Error('分类表单本身没有业务字段,不支持 --add-field / --fields / --from-model;字段请在模板(模板表单)中配置');
|
|
721
|
+
}
|
|
722
|
+
const name = String(opts.name ?? '').trim();
|
|
723
|
+
if (!name)
|
|
724
|
+
throw new Error('--name 不能为空');
|
|
725
|
+
if (name.length > 20)
|
|
726
|
+
throw new Error('分类表单名称最长 20 个字符');
|
|
727
|
+
const app = await formDefine_1.modelingAppApi.get(client, appId);
|
|
728
|
+
const appCode = String(app.fdAppCode ?? '').trim();
|
|
729
|
+
if (!appCode)
|
|
730
|
+
throw new Error(`未能读取应用编码(appId=${appId})`);
|
|
731
|
+
logger_1.logger.step('初始化分类表单(categoryModel/init)');
|
|
732
|
+
const init = await formDefine_1.categoryModelApi.init(client);
|
|
733
|
+
if (!init?.fdId)
|
|
734
|
+
throw new Error('categoryModel/init 未返回 fdId');
|
|
735
|
+
const takeTableName = async (given, label) => {
|
|
736
|
+
const explicit = String(given ?? '').trim();
|
|
737
|
+
if (explicit)
|
|
738
|
+
return explicit;
|
|
739
|
+
logger_1.logger.step(`生成${label}(sysModelingXForm/generateTableName)`);
|
|
740
|
+
return formDefine_1.modelingXFormApi.generateTableName(client);
|
|
741
|
+
};
|
|
742
|
+
const isSimple = type === 'simpleCategory';
|
|
743
|
+
const fdType = isSimple ? 2 : 1;
|
|
744
|
+
const fdMainTableName = await takeTableName(opts.tableName, '主表名');
|
|
745
|
+
let fdCategoryTableName = '';
|
|
746
|
+
let fdTemplateTableName = '';
|
|
747
|
+
let fdPolymersTableName = '';
|
|
748
|
+
let fdSupportHierarchy = opts.supportHierarchy !== false;
|
|
749
|
+
if (isSimple) {
|
|
750
|
+
fdPolymersTableName = await takeTableName(opts.polymersTableName, '聚合表名');
|
|
751
|
+
// 简单分类表单固定多层级
|
|
752
|
+
fdSupportHierarchy = true;
|
|
753
|
+
}
|
|
754
|
+
else {
|
|
755
|
+
fdCategoryTableName = await takeTableName(opts.categoryTableName, '分类表名');
|
|
756
|
+
fdTemplateTableName = await takeTableName(opts.templateTableName, '模板表名');
|
|
757
|
+
}
|
|
758
|
+
// 共享已有分类:沿用对方的分类表与层级配置
|
|
759
|
+
const shareCategory = String(opts.shareCategory ?? '').trim();
|
|
760
|
+
if (shareCategory) {
|
|
761
|
+
if (isSimple)
|
|
762
|
+
throw new Error('简单分类表单不支持共享已有分类');
|
|
763
|
+
const shared = await formDefine_1.categoryModelApi.list(client, {
|
|
764
|
+
conditions: { fdCode: shareCategory, fdType: { $eq: 1 } },
|
|
765
|
+
pageSize: 1,
|
|
766
|
+
});
|
|
767
|
+
const target = shared?.content?.[0];
|
|
768
|
+
if (!target?.fdCategoryTableName)
|
|
769
|
+
throw new Error(`未找到可共享的分类表单:${shareCategory}`);
|
|
770
|
+
fdCategoryTableName = String(target.fdCategoryTableName);
|
|
771
|
+
fdSupportHierarchy = Boolean(target.fdSupportHierarchy);
|
|
772
|
+
}
|
|
773
|
+
const payload = stripUndefined({
|
|
774
|
+
fdId: init.fdId,
|
|
775
|
+
fdType,
|
|
776
|
+
fdAppId: appId,
|
|
777
|
+
fdAppCode: appCode,
|
|
778
|
+
fdName: name,
|
|
779
|
+
fdCode: String(opts.code ?? '').trim() || `category_${Date.now().toString(36).slice(-6)}`,
|
|
780
|
+
fdIcon: opts.icon ? (0, icon_1.normalizeIcon)(opts.icon) : CATEGORY_FORM_ICON[type],
|
|
781
|
+
fdShareCategory: Boolean(shareCategory),
|
|
782
|
+
fdSupportHierarchy,
|
|
783
|
+
fdCategoryTableName: fdCategoryTableName || undefined,
|
|
784
|
+
fdTemplateTableName: fdTemplateTableName || undefined,
|
|
785
|
+
fdPolymersTableName: fdPolymersTableName || undefined,
|
|
786
|
+
fdMainTableName,
|
|
787
|
+
mechanisms: buildCategoryMechanisms(init.mechanisms, name, fdMainTableName),
|
|
788
|
+
});
|
|
789
|
+
logger_1.logger.info(logger_1.color.gray(`类型:${isSimple ? '简单分类表单' : '分类表单'} 应用:${appCode} 主表:${fdMainTableName} ` +
|
|
790
|
+
(isSimple
|
|
791
|
+
? `聚合表:${fdPolymersTableName}`
|
|
792
|
+
: `分类表:${fdCategoryTableName} 模板表:${fdTemplateTableName}`)));
|
|
793
|
+
if (opts.dryRun) {
|
|
794
|
+
logger_1.logger.title('【dry-run】将提交(categoryModel/add)');
|
|
795
|
+
logger_1.logger.json(payload);
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
logger_1.logger.step(`创建分类表单:${name}`);
|
|
799
|
+
const created = await formDefine_1.categoryModelApi.add(client, payload);
|
|
800
|
+
const fdId = created?.fdId ?? init.fdId;
|
|
801
|
+
logger_1.logger.success(`分类表单创建成功,fdId = ${fdId}`);
|
|
802
|
+
if (opts.publish) {
|
|
803
|
+
logger_1.logger.step('发布分类表单(categoryModel/save → publish)');
|
|
804
|
+
const detail = await formDefine_1.categoryModelApi.get(client, fdId);
|
|
805
|
+
const fdConfig = detail.fdConfig ?? JSON.stringify({ PC: {}, mobile: {} });
|
|
806
|
+
await formDefine_1.categoryModelApi.save(client, { ...detail, fdConfig });
|
|
807
|
+
await formDefine_1.categoryModelApi.publish(client, { ...detail, fdConfig, fdStatus: 'official' });
|
|
808
|
+
logger_1.logger.success('分类表单已发布');
|
|
809
|
+
}
|
|
810
|
+
if (opts.json) {
|
|
811
|
+
logger_1.logger.json({
|
|
812
|
+
fdId,
|
|
813
|
+
type,
|
|
814
|
+
fdType,
|
|
815
|
+
tables: {
|
|
816
|
+
main: fdMainTableName,
|
|
817
|
+
category: fdCategoryTableName || undefined,
|
|
818
|
+
template: fdTemplateTableName || undefined,
|
|
819
|
+
polymers: fdPolymersTableName || undefined,
|
|
820
|
+
},
|
|
821
|
+
});
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
824
|
+
logger_1.logger.info(logger_1.color.gray('提示:分类表单的模板(模板表单)需在平台「发起页设计器」中创建;' +
|
|
825
|
+
'模板表元数据由设计器首次保存时生成,CLI 直接调用 categoryTemplate/init 会报空指针。'));
|
|
826
|
+
}
|
|
677
827
|
function registerFormCommand(program) {
|
|
678
828
|
const form = program.command('form').description('表单相关操作(创建 / 查询 / 发布 / 自动完善字段)');
|
|
679
829
|
// ------------------------------------------------------------------ create
|
|
@@ -682,13 +832,20 @@ function registerFormCommand(program) {
|
|
|
682
832
|
.description('创建表单,并(可选)根据数据模型自动完善字段配置')
|
|
683
833
|
.requiredOption('--name <name>', '表单名称')
|
|
684
834
|
.option('--code <code>', '表单业务编码,默认自动生成')
|
|
685
|
-
.option('--type <type>', '表单类型:common|general|config|modal|template|refer
|
|
835
|
+
.option('--type <type>', '表单类型:common|general|config|modal|template|refer,' +
|
|
836
|
+
'或 category(分类表单)| simpleCategory(简单分类表单)。' +
|
|
837
|
+
'缺省时 general 族用 general、其余用 common')
|
|
686
838
|
.option('--app-id <appId>', '表单所属应用 id(应用主键 fdId)。给出后默认走 modeling 族,写入 fdAppId')
|
|
687
839
|
.option('--fd-entity-id <id>', '业务建模对应 appId / 应用模块对应 templateId(默认取 --app-id)')
|
|
688
840
|
.option('--fd-entity-name <name>', '所属实体 model 名称,例如 com.xxx.YourEntity')
|
|
689
841
|
.option('--fd-entity-key <key>', '实体扩展键(预留)')
|
|
690
842
|
.option('--fd-run-entity-name <name>', '表单运行时实体名称')
|
|
691
843
|
.option('--table-name <name>', '主表名(不传则调用对应接口自动生成)')
|
|
844
|
+
.option('--category-table-name <name>', '分类表名(--type category,不传自动生成)')
|
|
845
|
+
.option('--template-table-name <name>', '模板表名(--type category,不传自动生成)')
|
|
846
|
+
.option('--polymers-table-name <name>', '聚合表名(--type simpleCategory,不传自动生成)')
|
|
847
|
+
.option('--share-category <code>', '共享已有分类表单的分类(--type category,传对方 fdCode)')
|
|
848
|
+
.option('--no-support-hierarchy', '分类层级为单层级(默认多层级;简单分类强制多层级)')
|
|
692
849
|
.option('--api <family>', '接口族:auto(默认)| modeling | general | design')
|
|
693
850
|
.option('--group-id <fdGroupId>', '表单所属分组 id(modeling 族)')
|
|
694
851
|
.option('--edit-draft', '草稿状态允许编辑(modeling 族,默认 true)')
|
|
@@ -736,6 +893,12 @@ function registerFormCommand(program) {
|
|
|
736
893
|
const client = createClient(opts);
|
|
737
894
|
const appId = opts.appId;
|
|
738
895
|
const explicitType = opts.type;
|
|
896
|
+
// 分类表单 / 简单分类表单:走 categoryModel 链路(与普通表单完全不同的接口与表结构)
|
|
897
|
+
const categoryType = normalizeCategoryType(explicitType);
|
|
898
|
+
if (categoryType) {
|
|
899
|
+
await createCategoryForm(client, opts, categoryType);
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
739
902
|
const parsedType = explicitType ? parseFormType(explicitType) : undefined;
|
|
740
903
|
const { family, mechanismEntityName, mechanismEntityCode } = generatorOptions(opts, parsedType, appId);
|
|
741
904
|
// 未显式指定类型时:审批意见表单(general) 用 2,其余(含建模应用表单)用 1(普通表单)
|
|
@@ -1055,6 +1218,23 @@ function registerFormCommand(program) {
|
|
|
1055
1218
|
.option('--json', '以 JSON 输出')
|
|
1056
1219
|
.action(async (opts) => {
|
|
1057
1220
|
const client = createClient(opts);
|
|
1221
|
+
// 分类表单 / 简单分类表单与普通表单不在同一张表,优先按分类表单读取
|
|
1222
|
+
let categoryVo;
|
|
1223
|
+
try {
|
|
1224
|
+
categoryVo = await formDefine_1.categoryModelApi.get(client, opts.id);
|
|
1225
|
+
}
|
|
1226
|
+
catch {
|
|
1227
|
+
categoryVo = undefined;
|
|
1228
|
+
}
|
|
1229
|
+
if (categoryVo?.fdId) {
|
|
1230
|
+
logger_1.logger.json(categoryVo);
|
|
1231
|
+
const isSimple = categoryVo.fdType === 2;
|
|
1232
|
+
logger_1.logger.info(logger_1.color.gray(`类型:${isSimple ? '简单分类表单' : '分类表单'} 主表:${categoryVo.fdMainTableName ?? ''}` +
|
|
1233
|
+
(isSimple
|
|
1234
|
+
? ` 聚合表:${categoryVo.fdPolymersTableName ?? ''}`
|
|
1235
|
+
: ` 分类表:${categoryVo.fdCategoryTableName ?? ''} 模板表:${categoryVo.fdTemplateTableName ?? ''}`)));
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1058
1238
|
let vo;
|
|
1059
1239
|
// 依次尝试 建模应用接口 -> 审批意见表单接口 -> 表单引擎接口
|
|
1060
1240
|
try {
|