committed by
GitHub
17 changed files with 814 additions and 22 deletions
@ -0,0 +1,139 @@ |
|||||
|
using LINGYUN.Abp.Cli.UI; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.Cli.ServiceProxying; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands; |
||||
|
public class GenerateViewCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public const string Name = "generate-view"; |
||||
|
|
||||
|
protected string CommandName => Name; |
||||
|
|
||||
|
protected AbpCliViewGeneratorOptions ViewGeneratorOptions { get; } |
||||
|
|
||||
|
protected IServiceScopeFactory ServiceScopeFactory { get; } |
||||
|
|
||||
|
public GenerateViewCommand( |
||||
|
IOptions<AbpCliViewGeneratorOptions> viewGeneratorOptions, |
||||
|
IServiceScopeFactory serviceScopeFactory) |
||||
|
{ |
||||
|
ServiceScopeFactory = serviceScopeFactory; |
||||
|
ViewGeneratorOptions = viewGeneratorOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public async Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var generateType = commandLineArgs.Options.GetOrNull(Options.GenerateType.Short, Options.GenerateType.Long)?.ToUpper(); |
||||
|
|
||||
|
if (!ViewGeneratorOptions.Generators.ContainsKey(generateType)) |
||||
|
{ |
||||
|
throw new CliUsageException("Option Type value is invalid" + |
||||
|
Environment.NewLine + |
||||
|
GetUsageInfo()); |
||||
|
} |
||||
|
|
||||
|
using var scope = ServiceScopeFactory.CreateScope(); |
||||
|
var generatorType = ViewGeneratorOptions.Generators[generateType]; |
||||
|
var serviceProxyGenerator = scope.ServiceProvider.GetService(generatorType).As<IViewGenerator>(); |
||||
|
|
||||
|
await serviceProxyGenerator.GenerateAsync(BuildArgs(commandLineArgs)); |
||||
|
} |
||||
|
|
||||
|
private GenerateViewArgs BuildArgs(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
var url = commandLineArgs.Options.GetOrNull(Options.Url.Short, Options.Url.Long); |
||||
|
var output = commandLineArgs.Options.GetOrNull(Options.Output.Short, Options.Output.Long); |
||||
|
var module = commandLineArgs.Options.GetOrNull(Options.Module.Short, Options.Module.Long) ?? "app"; |
||||
|
var serviceTypeArg = commandLineArgs.Options.GetOrNull(Options.ServiceType.Short, Options.ServiceType.Long); |
||||
|
|
||||
|
ServiceType? serviceType = null; |
||||
|
if (!serviceTypeArg.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
serviceType = serviceTypeArg.ToLower() == "application" |
||||
|
? ServiceType.Application |
||||
|
: serviceTypeArg.ToLower() == "integration" |
||||
|
? ServiceType.Integration |
||||
|
: null; |
||||
|
} |
||||
|
|
||||
|
return new GenerateViewArgs( |
||||
|
module, |
||||
|
url, |
||||
|
output, |
||||
|
serviceType); |
||||
|
} |
||||
|
|
||||
|
public string GetShortDescription() |
||||
|
{ |
||||
|
return "Generate the view code from the http api proxy."; |
||||
|
} |
||||
|
|
||||
|
public string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine($" labp {CommandName}"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Options:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("-t<type> Generate ui script(vben-view、vben-model)."); |
||||
|
sb.AppendLine("See the documentation for more info: https://docs.abp.io/en/abp/latest/CLI"); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Examples:"); |
||||
|
sb.AppendLine(""); |
||||
|
|
||||
|
sb.AppendLine(" labp generate-proxy -t vben-view -m identity -o api/identity -url https://localhost:44302/"); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
public static class Options |
||||
|
{ |
||||
|
public static class GenerateType |
||||
|
{ |
||||
|
public const string Short = "t"; |
||||
|
public const string Long = "type"; |
||||
|
} |
||||
|
|
||||
|
public static class Module |
||||
|
{ |
||||
|
public const string Short = "m"; |
||||
|
public const string Long = "module"; |
||||
|
} |
||||
|
|
||||
|
public static class Output |
||||
|
{ |
||||
|
public const string Short = "o"; |
||||
|
public const string Long = "output"; |
||||
|
} |
||||
|
|
||||
|
public static class Folder |
||||
|
{ |
||||
|
public const string Long = "folder"; |
||||
|
} |
||||
|
|
||||
|
public static class Url |
||||
|
{ |
||||
|
public const string Short = "u"; |
||||
|
public const string Long = "url"; |
||||
|
} |
||||
|
|
||||
|
public static class ServiceType |
||||
|
{ |
||||
|
public const string Short = "st"; |
||||
|
public const string Long = "service-type"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI; |
||||
|
public class AbpCliViewGeneratorOptions |
||||
|
{ |
||||
|
public IDictionary<string, Type> Generators { get; } |
||||
|
|
||||
|
public AbpCliViewGeneratorOptions() |
||||
|
{ |
||||
|
Generators = new Dictionary<string, Type>(StringComparer.InvariantCultureIgnoreCase); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using Volo.Abp.Cli.ServiceProxying; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI; |
||||
|
|
||||
|
public class GenerateViewArgs |
||||
|
{ |
||||
|
public GenerateViewArgs( |
||||
|
string module, |
||||
|
string url, |
||||
|
string output, |
||||
|
ServiceType? serviceType = null) |
||||
|
{ |
||||
|
Module = module; |
||||
|
Url = url; |
||||
|
Output = output; |
||||
|
ServiceType = serviceType; |
||||
|
} |
||||
|
|
||||
|
public string Module { get; } |
||||
|
|
||||
|
public string Output { get; } |
||||
|
|
||||
|
public string Url { get; } |
||||
|
|
||||
|
public ServiceType? ServiceType { get; } |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI; |
||||
|
public interface IViewGenerator |
||||
|
{ |
||||
|
Task GenerateAsync(GenerateViewArgs args); |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
|
||||
|
public interface IVbenModelScriptGenerator |
||||
|
{ |
||||
|
Task<string> CreateModel( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel); |
||||
|
|
||||
|
Task<string> CreateTable( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel); |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
public interface IVbenViewScriptGenerator |
||||
|
{ |
||||
|
Task<string> CreateModal( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel); |
||||
|
|
||||
|
Task<string> CreateTable( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel); |
||||
|
|
||||
|
Task<string> CreateIndex( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel); |
||||
|
} |
||||
@ -0,0 +1,212 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.TextTemplating; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
|
||||
|
public class VbenModelScriptGenerator : IVbenModelScriptGenerator, ISingletonDependency |
||||
|
{ |
||||
|
private readonly ITemplateRenderer _templateRenderer; |
||||
|
|
||||
|
public VbenModelScriptGenerator( |
||||
|
ITemplateRenderer templateRenderer) |
||||
|
{ |
||||
|
_templateRenderer = templateRenderer; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> CreateModel( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel) |
||||
|
{ |
||||
|
var searchModels = new List<ComponentModel>(); |
||||
|
var inputModels = new List<ComponentModel>(); |
||||
|
|
||||
|
var moduleDefinition = appModel.Modules |
||||
|
.Where(module => module.Key.Equals(args.Module)) |
||||
|
.Select(module => module.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var listResultAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.ReturnValue.TypeSimple.Contains("ListResultDto")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
searchModels.Add( |
||||
|
new ComponentModel |
||||
|
{ |
||||
|
Name = "filter", |
||||
|
Component = "Input", |
||||
|
DisplayName = "Search", |
||||
|
ColProps = "{" + |
||||
|
"span: 24" + |
||||
|
"}", |
||||
|
}); |
||||
|
|
||||
|
if (listResultAction != null) |
||||
|
{ |
||||
|
foreach (var inputParamter in listResultAction.Parameters) |
||||
|
{ |
||||
|
if (appModel.Types.TryGetValue(inputParamter.Type, out var inputModelType)) |
||||
|
{ |
||||
|
var span = inputModelType.Properties.Length > 3 ? 8 |
||||
|
: inputModelType.Properties.Length > 2 ? 12 |
||||
|
: 24; |
||||
|
foreach (var inputModelProp in inputModelType.Properties) |
||||
|
{ |
||||
|
var component = new ComponentModel |
||||
|
{ |
||||
|
Name = inputModelProp.JsonName ?? inputModelProp.Name.ToCamelCase(), |
||||
|
Component = "Input", |
||||
|
DisplayName = "DisplayName:" + inputModelProp.Name.ToPascalCase(), |
||||
|
Required = inputModelProp.IsRequired, |
||||
|
ColProps = "" + |
||||
|
"{" + |
||||
|
$"span: {span}" + |
||||
|
"}", |
||||
|
}; |
||||
|
|
||||
|
if (appModel.Types.TryGetValue(inputModelProp.Type, out var inputModelPropType) && |
||||
|
inputModelPropType.IsEnum) |
||||
|
{ |
||||
|
component.Component = "Select"; |
||||
|
|
||||
|
var optionsStr = Environment.NewLine; |
||||
|
|
||||
|
var options = new object[inputModelPropType.EnumNames.Length]; |
||||
|
for (var index = 0; index < inputModelPropType.EnumNames.Length; index++) |
||||
|
{ |
||||
|
optionsStr += "" + |
||||
|
"{" + |
||||
|
$"label: {inputModelPropType.EnumNames[index]}," + |
||||
|
$"value: {inputModelPropType.EnumValues[index]}," + |
||||
|
"}" + |
||||
|
"" + Environment.NewLine; |
||||
|
} |
||||
|
component.ComponentProps = "" + |
||||
|
"{" + |
||||
|
$"options: [{optionsStr}]" + |
||||
|
"}"; |
||||
|
} |
||||
|
|
||||
|
searchModels.Add(component); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var createOrUpdateAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.UniqueName.Contains("Create") || action.Value.UniqueName.Contains("Update")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
if (createOrUpdateAction != null) |
||||
|
{ |
||||
|
foreach (var createOrUpdateParamter in createOrUpdateAction.Parameters) |
||||
|
{ |
||||
|
if (appModel.Types.TryGetValue(createOrUpdateParamter.Type, out var inputModelType)) |
||||
|
{ |
||||
|
foreach (var inputModelProp in inputModelType.Properties) |
||||
|
{ |
||||
|
var component = new ComponentModel |
||||
|
{ |
||||
|
Name = inputModelProp.JsonName ?? inputModelProp.Name.ToCamelCase(), |
||||
|
Component = "Input", |
||||
|
DisplayName = "DisplayName:" + inputModelProp.Name.ToPascalCase(), |
||||
|
Required = inputModelProp.IsRequired, |
||||
|
ColProps = "" + |
||||
|
"{" + |
||||
|
"span: 24" + |
||||
|
"}", |
||||
|
ComponentProps = "{}" |
||||
|
}; |
||||
|
|
||||
|
inputModels.Add(component); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var modelDataContent = await _templateRenderer.RenderAsync( |
||||
|
"VbenModelData", |
||||
|
new |
||||
|
{ |
||||
|
RemoteService = moduleDefinition.RemoteServiceName, |
||||
|
ExistsSearchModels = searchModels.Any(), |
||||
|
SearchModels = searchModels, |
||||
|
InputModels = inputModels, |
||||
|
}); |
||||
|
|
||||
|
return modelDataContent; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> CreateTable( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel) |
||||
|
{ |
||||
|
var ouputModels = new List<ComponentModel>(); |
||||
|
|
||||
|
var moduleDefinition = appModel.Modules |
||||
|
.Where(module => module.Key.Equals(args.Module)) |
||||
|
.Select(module => module.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var listResultAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.ReturnValue.TypeSimple.Contains("ListResultDto") |
||||
|
|| action.Value.ReturnValue.TypeSimple.Contains("PagedResultDto")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
if (listResultAction != null) |
||||
|
{ |
||||
|
foreach (var inputParamter in listResultAction.Parameters) |
||||
|
{ |
||||
|
if (appModel.Types.TryGetValue(inputParamter.Type, out var inputModelType)) |
||||
|
{ |
||||
|
var span = inputModelType.Properties.Length > 3 ? 8 |
||||
|
: inputModelType.Properties.Length > 2 ? 12 |
||||
|
: 24; |
||||
|
foreach (var inputModelProp in inputModelType.Properties) |
||||
|
{ |
||||
|
var component = new ComponentModel |
||||
|
{ |
||||
|
Name = inputModelProp.JsonName ?? inputModelProp.Name.ToCamelCase(), |
||||
|
DisplayName = "DisplayName:" + inputModelProp.Name.ToPascalCase() |
||||
|
}; |
||||
|
|
||||
|
ouputModels.Add(component); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
var tableDataContent = await _templateRenderer.RenderAsync( |
||||
|
"VbenTableData", |
||||
|
new |
||||
|
{ |
||||
|
RemoteService = moduleDefinition.RemoteServiceName, |
||||
|
OuputModels = ouputModels, |
||||
|
}); |
||||
|
|
||||
|
return tableDataContent; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class ComponentModel |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
public string Component { get; set; } |
||||
|
public string DisplayName { get; set; } |
||||
|
public object ColProps { get; set; } |
||||
|
public object ComponentProps { get; set; } |
||||
|
public string Align { get; set; } = "left"; |
||||
|
public int Width { get; set; } = 120; |
||||
|
public bool Sorter { get; set; } = true; |
||||
|
public bool Resizable { get; set; } = true; |
||||
|
public bool Required { get; set; } = false; |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.TextTemplating; |
||||
|
using static Volo.Abp.Cli.Commands.AddPackageCommand.Options; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
|
||||
|
public class VbenScriptTemplateDefinitionProvider : TemplateDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(ITemplateDefinitionContext context) |
||||
|
{ |
||||
|
context.Add(CreateCliTemplates()); |
||||
|
} |
||||
|
|
||||
|
private static TemplateDefinition[] CreateCliTemplates() |
||||
|
{ |
||||
|
return new[] |
||||
|
{ |
||||
|
new TemplateDefinition( |
||||
|
"VbenModelData", |
||||
|
typeof(DefaultResource), |
||||
|
L("Templates:VbenModelData") |
||||
|
).WithVirtualFilePath("/LINGYUN/Abp/Cli/UI/Vben/Templates/VbenModelDataScript.tpl", true), |
||||
|
new TemplateDefinition( |
||||
|
"VbenModalView", |
||||
|
typeof(DefaultResource), |
||||
|
L("Templates:VbenModalView") |
||||
|
).WithVirtualFilePath("/LINGYUN/Abp/Cli/UI/Vben/Templates/VbenModalViewScript.tpl", true), |
||||
|
new TemplateDefinition( |
||||
|
"VbenTableData", |
||||
|
typeof(DefaultResource), |
||||
|
L("Templates:VbenTableData") |
||||
|
).WithVirtualFilePath("/LINGYUN/Abp/Cli/UI/Vben/Templates/VbenTableDataScript.tpl", true), |
||||
|
new TemplateDefinition( |
||||
|
"VbenTableView", |
||||
|
typeof(DefaultResource), |
||||
|
L("Templates:VbenTableView") |
||||
|
).WithVirtualFilePath("/LINGYUN/Abp/Cli/UI/Vben/Templates/VbenTableViewScript.tpl", true), |
||||
|
new TemplateDefinition( |
||||
|
"VbenComponentIndex", |
||||
|
typeof(DefaultResource), |
||||
|
L("Templates:VbenComponentIndex") |
||||
|
).WithVirtualFilePath("/LINGYUN/Abp/Cli/UI/Vben/Templates/VbenComponentIndexScript.tpl", true), |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<DefaultResource>(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,111 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli.Http; |
||||
|
using Volo.Abp.Cli.ServiceProxying; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.IO; |
||||
|
using Volo.Abp.Json; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
public class VbenViewGenerator : ViewGeneratorBase<VbenViewGenerator>, ISingletonDependency |
||||
|
{ |
||||
|
public const string Name = "Vben-View"; |
||||
|
|
||||
|
protected IVbenModelScriptGenerator ModelScriptGenerator { get; } |
||||
|
protected IVbenViewScriptGenerator ViewScriptGenerator { get; } |
||||
|
public VbenViewGenerator( |
||||
|
CliHttpClientFactory cliHttpClientFactory, |
||||
|
IJsonSerializer jsonSerializer, |
||||
|
IVbenModelScriptGenerator modelScriptGenerator, |
||||
|
IVbenViewScriptGenerator viewScriptGenerator) |
||||
|
: base(cliHttpClientFactory, jsonSerializer) |
||||
|
{ |
||||
|
ModelScriptGenerator = modelScriptGenerator; |
||||
|
ViewScriptGenerator = viewScriptGenerator; |
||||
|
} |
||||
|
|
||||
|
private async Task CreateAndSaveSciptToDisk(string scriptFile, string script) |
||||
|
{ |
||||
|
Logger.LogInformation($"The script output file: {scriptFile}."); |
||||
|
Logger.LogInformation($"Saving script: {scriptFile}."); |
||||
|
|
||||
|
FileHelper.DeleteIfExists(scriptFile); |
||||
|
|
||||
|
await File.AppendAllTextAsync(scriptFile, script); |
||||
|
|
||||
|
Logger.LogInformation($"Saved script: {scriptFile} has successful."); |
||||
|
} |
||||
|
|
||||
|
public async override Task GenerateAsync(GenerateViewArgs args) |
||||
|
{ |
||||
|
var applicationApiDescriptionModel = await GetApplicationApiDescriptionModelAsync( |
||||
|
args, |
||||
|
new ApplicationApiDescriptionModelRequestDto |
||||
|
{ |
||||
|
IncludeTypes = true |
||||
|
}); |
||||
|
var outputFolderRoot = args.Output; |
||||
|
|
||||
|
foreach (var module in applicationApiDescriptionModel.Modules) |
||||
|
{ |
||||
|
Logger.LogInformation($"Generating script with remote service: {module.Value.RemoteServiceName}."); |
||||
|
|
||||
|
foreach (var controller in module.Value.Controllers) |
||||
|
{ |
||||
|
var componentScriptPath = Path.Combine( |
||||
|
outputFolderRoot, |
||||
|
module.Value.RemoteServiceName.ToKebabCase(), |
||||
|
controller.Value.ControllerName.ToKebabCase()); |
||||
|
|
||||
|
var modelScriptPath = Path.Combine(componentScriptPath, "datas"); |
||||
|
DirectoryHelper.CreateIfNotExists(modelScriptPath); |
||||
|
|
||||
|
await CreateAndSaveSciptToDisk( |
||||
|
Path.Combine(modelScriptPath, "ModalData.ts"), |
||||
|
await ModelScriptGenerator.CreateModel( |
||||
|
args, |
||||
|
applicationApiDescriptionModel, |
||||
|
controller.Value)); |
||||
|
|
||||
|
await CreateAndSaveSciptToDisk( |
||||
|
Path.Combine(modelScriptPath, "TableData.ts"), |
||||
|
await ModelScriptGenerator.CreateTable( |
||||
|
args, |
||||
|
applicationApiDescriptionModel, |
||||
|
controller.Value)); |
||||
|
|
||||
|
var viewScriptPath = Path.Combine(componentScriptPath, "components"); |
||||
|
DirectoryHelper.CreateIfNotExists(viewScriptPath); |
||||
|
|
||||
|
await CreateAndSaveSciptToDisk( |
||||
|
Path.Combine(viewScriptPath, $"{controller.Value.ControllerName.ToPascalCase()}Modal.vue"), |
||||
|
await ViewScriptGenerator.CreateModal( |
||||
|
args, |
||||
|
applicationApiDescriptionModel, |
||||
|
controller.Value)); |
||||
|
|
||||
|
await CreateAndSaveSciptToDisk( |
||||
|
Path.Combine(viewScriptPath, $"{controller.Value.ControllerName.ToPascalCase()}Table.vue"), |
||||
|
await ViewScriptGenerator.CreateTable( |
||||
|
args, |
||||
|
applicationApiDescriptionModel, |
||||
|
controller.Value)); |
||||
|
|
||||
|
await CreateAndSaveSciptToDisk( |
||||
|
Path.Combine(componentScriptPath, "index.vue"), |
||||
|
await ViewScriptGenerator.CreateIndex( |
||||
|
args, |
||||
|
applicationApiDescriptionModel, |
||||
|
controller.Value)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected override ServiceType? GetDefaultServiceType(GenerateViewArgs args) |
||||
|
{ |
||||
|
return ServiceType.Application; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,103 @@ |
|||||
|
using System; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.TextTemplating; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI.Vben; |
||||
|
public class VbenViewScriptGenerator : IVbenViewScriptGenerator, ISingletonDependency |
||||
|
{ |
||||
|
private readonly ITemplateRenderer _templateRenderer; |
||||
|
|
||||
|
public VbenViewScriptGenerator( |
||||
|
ITemplateRenderer templateRenderer) |
||||
|
{ |
||||
|
_templateRenderer = templateRenderer; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> CreateModal( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel) |
||||
|
{ |
||||
|
var moduleDefinition = appModel.Modules |
||||
|
.Where(module => module.Key.Equals(args.Module)) |
||||
|
.Select(module => module.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var modalContent = await _templateRenderer.RenderAsync( |
||||
|
"VbenModalView", |
||||
|
new |
||||
|
{ |
||||
|
Application = controllerModel.ControllerName, |
||||
|
ApiPath = $"/@/api/{moduleDefinition.RemoteServiceName.ToKebabCase()}/{controllerModel.ControllerName.ToKebabCase()}", |
||||
|
RemoteService = moduleDefinition.RemoteServiceName, |
||||
|
}); |
||||
|
|
||||
|
return modalContent; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> CreateTable( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel) |
||||
|
{ |
||||
|
var moduleDefinition = appModel.Modules |
||||
|
.Where(module => module.Key.Equals(args.Module)) |
||||
|
.Select(module => module.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var pagedResultAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.ReturnValue.TypeSimple.Contains("PagedResultDto")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var deleteAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.Name.Contains("DeleteAsync")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
var updateAction = controllerModel.Actions |
||||
|
.Where(action => action.Value.Name.Contains("UpdateAsync")) |
||||
|
.Select(action => action.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var tableContent = await _templateRenderer.RenderAsync( |
||||
|
"VbenTableView", |
||||
|
new |
||||
|
{ |
||||
|
PagedRequest = pagedResultAction != null, |
||||
|
UpdatePermission = updateAction != null && updateAction.AllowAnonymous != null && updateAction.AllowAnonymous != true, |
||||
|
UpdatePermissionName = $"{moduleDefinition.RemoteServiceName.ToKebabCase()}.{controllerModel.ControllerName.ToKebabCase()}.Update", |
||||
|
DeletePermission = deleteAction != null && deleteAction.AllowAnonymous != null && deleteAction.AllowAnonymous != true, |
||||
|
DeletePermissionName = $"{moduleDefinition.RemoteServiceName.ToKebabCase()}.{controllerModel.ControllerName.ToKebabCase()}.Delete", |
||||
|
Application = controllerModel.ControllerName, |
||||
|
ModalName = $"{controllerModel.ControllerName.ToPascalCase()}Modal", |
||||
|
ApiPath = $"/@/api/{moduleDefinition.RemoteServiceName.ToKebabCase()}/{controllerModel.ControllerName.ToKebabCase()}", |
||||
|
RemoteService = moduleDefinition.RemoteServiceName, |
||||
|
}); |
||||
|
|
||||
|
return tableContent; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<string> CreateIndex( |
||||
|
GenerateViewArgs args, |
||||
|
ApplicationApiDescriptionModel appModel, |
||||
|
ControllerApiDescriptionModel controllerModel) |
||||
|
{ |
||||
|
var moduleDefinition = appModel.Modules |
||||
|
.Where(module => module.Key.Equals(args.Module)) |
||||
|
.Select(module => module.Value) |
||||
|
.FirstOrDefault(); |
||||
|
|
||||
|
var modalContent = await _templateRenderer.RenderAsync( |
||||
|
"VbenComponentIndex", |
||||
|
new |
||||
|
{ |
||||
|
TableName = $"{controllerModel.ControllerName}Table", |
||||
|
Application = $"{moduleDefinition.RemoteServiceName.ToPascalCase()}{controllerModel.ControllerName.ToPascalCase()}".EnsureEndsWith('s') |
||||
|
}); |
||||
|
|
||||
|
return modalContent; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,70 @@ |
|||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Http; |
||||
|
using Volo.Abp.Cli.ServiceProxying; |
||||
|
using Volo.Abp.Http.Modeling; |
||||
|
using Volo.Abp.Json; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.UI; |
||||
|
public abstract class ViewGeneratorBase<T> : IViewGenerator where T : IViewGenerator |
||||
|
{ |
||||
|
public IJsonSerializer JsonSerializer { get; } |
||||
|
|
||||
|
public CliHttpClientFactory CliHttpClientFactory { get; } |
||||
|
|
||||
|
public ILogger<T> Logger { get; set; } |
||||
|
|
||||
|
protected ViewGeneratorBase(CliHttpClientFactory cliHttpClientFactory, IJsonSerializer jsonSerializer) |
||||
|
{ |
||||
|
CliHttpClientFactory = cliHttpClientFactory; |
||||
|
JsonSerializer = jsonSerializer; |
||||
|
Logger = NullLogger<T>.Instance; |
||||
|
} |
||||
|
|
||||
|
protected virtual async Task<ApplicationApiDescriptionModel> GetApplicationApiDescriptionModelAsync(GenerateViewArgs args, ApplicationApiDescriptionModelRequestDto requestDto = null) |
||||
|
{ |
||||
|
Check.NotNull(args.Url, nameof(args.Url)); |
||||
|
|
||||
|
var client = CliHttpClientFactory.CreateClient(); |
||||
|
|
||||
|
var apiDefinitionResult = await client.GetStringAsync(CliUrls.GetApiDefinitionUrl(args.Url, requestDto)); |
||||
|
var apiDefinition = JsonSerializer.Deserialize<ApplicationApiDescriptionModel>(apiDefinitionResult); |
||||
|
|
||||
|
var moduleDefinition = apiDefinition.Modules.FirstOrDefault(x => string.Equals(x.Key, args.Module, StringComparison.CurrentCultureIgnoreCase)).Value; |
||||
|
if (moduleDefinition == null) |
||||
|
{ |
||||
|
throw new CliUsageException($"Module name: {args.Module} is invalid"); |
||||
|
} |
||||
|
|
||||
|
var serviceType = GetServiceType(args); |
||||
|
switch (serviceType) |
||||
|
{ |
||||
|
case ServiceType.Application: |
||||
|
moduleDefinition.Controllers.RemoveAll(x => !x.Value.IsRemoteService); |
||||
|
break; |
||||
|
case ServiceType.Integration: |
||||
|
moduleDefinition.Controllers.RemoveAll(x => !x.Value.IsIntegrationService); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
var apiDescriptionModel = ApplicationApiDescriptionModel.Create(); |
||||
|
apiDescriptionModel.Types = apiDefinition.Types; |
||||
|
apiDescriptionModel.AddModule(moduleDefinition); |
||||
|
return apiDescriptionModel; |
||||
|
} |
||||
|
|
||||
|
protected virtual ServiceType? GetServiceType(GenerateViewArgs args) |
||||
|
{ |
||||
|
return args.ServiceType ?? GetDefaultServiceType(args); |
||||
|
} |
||||
|
|
||||
|
protected abstract ServiceType? GetDefaultServiceType(GenerateViewArgs args); |
||||
|
|
||||
|
public abstract Task GenerateAsync(GenerateViewArgs args); |
||||
|
} |
||||
Loading…
Reference in new issue