@lcap/asl
Version:
NetEase Application Specific Language
307 lines (283 loc) • 14.9 kB
text/typescript
import { Resolver } from '../Entity';
import { config, dataTypesMap, vertexsMap, Entity, EntityProperty, View, Enum, LEVEL_ENUM, utils } from '../..';
import { NameGroup, genUniqueQueryNameGroup, filterProperty, getParamFromResolver, getFirstDisplayedProperty, genEnumSelectBlock, genCallComponentLogic, genCallInterface, genLoadSelectLogic } from '.';
export function genCreateFormTemplate(entity: Entity, nameGroup: NameGroup, selectNameGroupMap: Map<string, NameGroup>) {
const propertyList = entity.propertyList
.filter(filterProperty('inForm'));
return `<u-form ref="form1">
${propertyList.map((property) => {
const label = property.label || property.name;
const required = !!property.required;
const rules = [];
if (property.rules && property.rules.length) {
property.rules.forEach((rule) => rules.push(rule));
}
if (required)
rules.push('required');
const rulesStr = rules.join(' | ');
let formItem = ` <u-form-item label="${label}"${required ? ' required' : ''}${rulesStr.length ? ` rules="${rulesStr}"` : ''}>\n`;
if (property.$relationEntity) { // 有外键关联
const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
if (relationEntity) {
const relationProperty = vertexsMap.get(property.$relationProperty) as EntityProperty;
const displayedProperty = getFirstDisplayedProperty(relationEntity, 'inForm');
if (displayedProperty) {
const lowerEntityName = utils.firstLowerCase(relationEntity.name);
formItem += `
<u-select clearable placeholder="请选择${label}" :data-source="${selectNameGroupMap.get(relationEntity.id).load}"
text-field="${lowerEntityName}.${displayedProperty.name}" value-field="${lowerEntityName}.${relationProperty.name}" pageable remote-paging v-model="${nameGroup.model}.${property.name}">
</u-select>
`;
} else
return '';
} else
return '';
} else if (property.typeKey === '#/basicTypes/Boolean') {
formItem += `<u-checkbox v-model="${nameGroup.model}.${property.name}"></u-checkbox>`;
} else if (property.typeKey === '#/basicTypes/Integer' || property.typeKey === '#/basicTypes/Long') {
formItem += `<u-number-input v-model="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-number-input>`;
} else if (property.typeKey === '#/basicTypes/Decimal') {
formItem += `<u-number-input v-model="${nameGroup.model}.${property.name}" :precision="0" :step="0" placeholder="请输入${label}"></u-number-input>`;
} else if (property.typeKey === '#/basicTypes/Text') {
formItem += `<u-textarea v-model="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-textarea>`;
} else if (property.typeKey === '#/basicTypes/Date') {
formItem += `<u-date-picker clearable :date.sync="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-date-picker>`;
} else if (property.typeKey === '#/basicTypes/Time') {
formItem += `<u-time-picker :time.sync="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-time-picker>`;
} else if (property.typeKey === '#/basicTypes/DateTime') {
formItem += `<u-date-time-picker clearable :date.sync="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-date-time-picker>`;
} else if (dataTypesMap[property.typeKey].type === 'enum') {
formItem += genEnumSelectBlock(dataTypesMap[property.typeKey] as Enum, `${nameGroup.model}.${property.name}`, '', `请选择${label}`);
} else {
formItem += `<u-input v-model="${nameGroup.model}.${property.name}" placeholder="请输入${label}"></u-input>`;
}
formItem += ` </u-form-item>\n`;
return formItem;
}).join('')}
<u-form-item>
<u-button color="primary" @click="${nameGroup.submit}()">立即创建</u-button>
</u-form-item>
</u-form>`;
}
export function genH5CreateFormTemplate(entity: Entity, nameGroup: NameGroup, selectNameGroupMap: Map<string, NameGroup>) {
const propertyList = entity.propertyList
.filter(filterProperty('inForm'));
return `<van-form ref="form1">
${propertyList.map((property) => {
const label = property.label || property.name;
const required = !!property.required;
const rules = [];
if (property.rules && property.rules.length) {
property.rules.forEach((rule) => rules.push(rule));
}
if (required)
rules.push('required');
const rulesStr = rules.join(' | ');
let formItem = ` <van-field drole="other" label="${property.label || property.name}"${required ? ' required' : ''}${rulesStr.length ? ` rules="${rulesStr}"` : ''}>\n`;
if (property.$relationEntity) { // 有外键关联
const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
if (relationEntity) {
const relationProperty = vertexsMap.get(property.$relationProperty) as EntityProperty;
const displayedProperty = getFirstDisplayedProperty(relationEntity, 'inForm');
if (displayedProperty) {
const lowerEntityName = utils.firstLowerCase(relationEntity.name);
formItem += `
<template #input><van-cascader title="请选择${label}" placeholder="请选择${label}"
v-model="${nameGroup.model}.${property.name}" :data-source="${selectNameGroupMap.get(relationEntity.id).load}"
text-field="${lowerEntityName}.${displayedProperty.name}" value-field="${lowerEntityName}.${relationProperty.name}"
pageable remote-paging></van-cascader></template>
`;
} else
return '';
} else
return '';
} else if (property.typeKey === '#/basicTypes/Boolean') {
formItem += `<template #input><van-switch v-model="${nameGroup.model}.${property.name}"></van-switch></template>`;
} else if (property.typeKey === '#/basicTypes/Integer' || property.typeKey === '#/basicTypes/Long') {
formItem += `<template #input><van-stepper v-model="${nameGroup.model}.${property.name}" placeholder="请输入${property.label || property.name}"></van-stepper></template>`;
} else if (property.typeKey === '#/basicTypes/Decimal') {
formItem += `<template #input><van-stepper v-model="${nameGroup.model}.${property.name}" placeholder="请输入${property.label || property.name}"></van-stepper></template>`;
} else if (property.typeKey === '#/basicTypes/Text') {
formItem = formItem.replace(/other/g, '');
formItem += `<van-input v-model="${nameGroup.model}.${property.name}" placeholder="请输入${property.label || property.name}"></van-input>`;
} else if (property.typeKey === '#/basicTypes/Date') {
formItem += `<template #input><van-calendar v-model="${nameGroup.model}.${property.name}" title="请输入${property.label || property.name}"></van-calendar></template>`;
} else if (property.typeKey === '#/basicTypes/Time') {
formItem += `<template #input><van-datetime-picker type="time" v-model="${nameGroup.model}.${property.name}" title="请输入${property.label || property.name}"></van-datetime-picker></template>`;
} else if (property.typeKey === '#/basicTypes/DateTime') {
formItem += `<template #input><van-datetime-picker type="datetime" v-model="${nameGroup.model}.${property.name}" title="请输入${property.label || property.name}"></van-datetime-picker></template>`;
} else if (dataTypesMap[property.typeKey].type === 'enum') {
formItem += '<template #input>' + genEnumSelectBlock(dataTypesMap[property.typeKey] as Enum, `${nameGroup.model}.${property.name}`, '', `请选择${property.label || property.name}`) + '</template>';
} else {
formItem = formItem.replace(/other/g, '');
formItem += `<van-input v-model="${nameGroup.model}.${property.name}" placeholder="请输入${property.label || property.name}"></van-input>`;
}
formItem += ` </van-field>\n`;
formItem = formItem.replace(/>\n<van-input|<\/van-input>/g, '');
return formItem;
}).join('')}
<div>
<van-button round block="blockb" type="info" @click="${nameGroup.submit}()" text="立即创建"></van-button>
</div>
</van-form>`;
}
function genSubmitLogic(resolver: Resolver, nameGroup: NameGroup) {
const bodyParam = getParamFromResolver(resolver, 'body');
return {
level: 'logic',
name: nameGroup.submit,
params: [] as any,
returns: [] as any,
variables: [
{
level: 'variable',
type: 'Identifier',
name: 'validateResult',
description: '',
schema: {
$ref: '#/systemTypes/ValidateEvent',
},
isLeaf: true,
},
],
body: [
{
level: 'logicNode',
type: 'Start',
label: '开始',
},
{
level: 'logicNode',
type: 'AssignmentExpression',
label: '赋值',
operator: '=',
left: {
level: 'expressionNode',
type: 'Identifier',
name: 'validateResult',
},
right: genCallComponentLogic('form1', 'validate'),
},
{
level: 'logicNode',
type: 'IfStatement',
label: '条件分支',
test: {
level: 'expressionNode',
type: 'MemberExpression',
name: 'name',
hide: false,
object: {
level: 'expressionNode',
type: 'Identifier',
name: 'validateResult',
},
property: {
level: 'expressionNode',
type: 'Identifier',
name: 'valid',
},
},
consequent: [
genCallInterface(resolver.interface, [
{
parentAttr: 'params',
level: LEVEL_ENUM.param,
type: 'CallInterParam',
name: '',
callInterParam: `#/${bodyParam.id}`,
callInterParamValue: {
parentAttr: 'callInterParamValue',
level: 'expressionNode',
type: 'Identifier',
name: nameGroup.model,
},
},
]),
{
level: 'logicNode',
parentAttr: 'consequent',
label: '弹出消息',
folded: false,
type: 'CallMessageShow',
arguments: [
{
level: 'expressionNode',
parentAttr: 'arguments',
label: '原子项',
folded: false,
type: 'StringLiteral',
value: '创建成功!',
},
],
},
],
alternate: [] as any,
},
{
level: 'logicNode',
type: 'End',
label: '结束',
}],
};
}
/**
* 生成创建页区块
* @param resolver 实体创建 Action
*/
export function genCreateBlock(entity: Entity, view: View) {
const resolver = entity.resolvers.find((item) => item.name.startsWith('create'));
const modelSchema = {
$ref: entity.schemaRef,
};
const existingNameSets = {
viewLogic: new Set(view.$def.logics.map((logic) => logic.name)),
interface: new Set(entity.dataNode.service.interfaces.map((itface) => itface.name)),
structure: new Set(entity.dataNode.structures.map((structure) => structure.name)),
};
const nameGroup: NameGroup = {
model: utils.firstLowerCase(entity.name),
};
nameGroup.submit = utils.unique('submit', existingNameSets.viewLogic);
// 收集所有和本实体关联的实体
const allEntities = [entity];
entity.propertyList.forEach((property) => {
if (property.$relationEntity) { // 有外键关联
const relationEntity = vertexsMap.get(property.$relationEntity) as Entity;
if (relationEntity) {
const displayedProperty = getFirstDisplayedProperty(relationEntity);
if (displayedProperty)
allEntities.push(relationEntity);
}
}
});
const newStructures: Array<any> = [];
const newInterfaces: Array<any> = [];
const selectNameGroupMap: Map<string, NameGroup> = new Map();
const loadSelectLogics = allEntities.slice(1).map((entity) => {
const selectNameGroup = genUniqueQueryNameGroup(existingNameSets, view.name, 'select', false, entity.name);
selectNameGroupMap.set(entity.id, selectNameGroup);
return genLoadSelectLogic(entity, selectNameGroup, newStructures, newInterfaces);
});
return `<template>
${config.scope === 'h5' ? genH5CreateFormTemplate(entity, nameGroup, selectNameGroupMap) : genCreateFormTemplate(entity, nameGroup, selectNameGroupMap)}
</template>
<definition>
{
"variables": [{
"level": "variable",
"type": "Identifier",
"name": "${nameGroup.model}",
"schema": ${JSON.stringify(modelSchema)}
}],
"logics": [
${JSON.stringify(genSubmitLogic(resolver, nameGroup))}
${loadSelectLogics.map((logic) => ',' + JSON.stringify(logic)).join('\n')}
],
"interfaces": ${JSON.stringify(newInterfaces)},
"structures": ${JSON.stringify(newStructures)}
}
</definition>
`;
}
export default genCreateBlock;