大佬教程收集整理的这篇文章主要介绍了Abp Vnext Vue3 的版本实现,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
Abp Vnext Pro 的 Vue3 实现版本 开箱即用的中后台前端/设计解决方案
.
├── Directory.build.props nuget 版本控制
├── frameworks # 公共模块
│ ├── CAP # dotnetcore.cap
│ └── Extensions # 自定义扩展
├── gateways # 网关
├── modules # 模块
│ ├── DataDictionarymanagement # 数据字典
│ └── NotificationManagement # 通知服务
├── services # 公共静态资源目录
│ ├── host # 启动模块
│ ├── CompanyName.ProjectName.httpApi.Host # admin ui host
│ └── CompanyName.ProjectName.IdentityServer # IdentityServer host
│ ├── src # 源码
│ └── CompanyName.ProjectName.DbMigrator # 迁移控制台程序
│ └── test # 单元测试
.
├── _nginx # docker 打包
├── build # 打包脚本相关
│ ├── config # 配置文件
│ ├── generate # 生成器
│ ├── script # 脚本
│ └── vite # vite配置
├── mock # mock文件夹
├── public # 公共静态资源目录
├── src # 主目录
│ ├── api # 接口文件
│ ├── assets # 资源文件
│ │ ├── icons # icon sprite 图标文件夹
│ │ ├── images # 项目存放图片的文件夹
│ │ └── svg # 项目存放svg图片的文件夹
│ ├── components # 公共组件
│ ├── design # 样式文件
│ ├── directives # 指令
│ ├── enums # 枚举/常量
│ ├── hooks # hook
│ │ ├── component # 组件相关hook
│ │ ├── core # 基础hook
│ │ ├── event # 事件相关hook
│ │ ├── setTing # 配置相关hook
│ │ └── web # web相关hook
│ ├── layouts # 布局文件
│ │ ├── default # 默认布局
│ │ ├── iframe # iframe布局
│ │ └── page # 页面布局
│ ├── locales # 多语言
│ ├── logics # 逻辑
│ ├── main.ts # 主入口
│ ├── router # 路由配置
│ ├── services # Nswag生成的代理
│ │ ├── serviceProxies.ts # Nswag生成的代理
│ │ ├── serviceProxyBase.ts # Nswag生成的代理拦截器
│ ├── setTings # 项目配置
│ │ ├── componentSetTing.ts # 组件配置
│ │ ├── designSetTing.ts # 样式配置
│ │ ├── encryptionSetTing.ts # 加密配置
│ │ ├── localeSetTing.ts # 多语言配置
│ │ ├── projectSetTing.ts # 项目配置
│ │ └── siteSetTing.ts # 站点配置
│ ├── store # 数据仓库
│ ├── utils # 工具类
│ └── views # 页面
├── test # 测试
│ └── server # 测试用到的服务
│ ├── api # 测试服务器
│ ├── upload # 测试上传服务器
│ └── websocket # 测试ws服务器
├── types # 类型文件
├── vite.config.ts # vite配置文件
└── windi.config.ts # windcss配置文件
docker run --name mymysql -p 3306:3306 -e MYSQL_ROOT_password=1q2w3E* -d mysql:5.7 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
docker run --name myredis -p 6379:6379 -d redis:latest redis-server
RabbitMq 非必须
appsetTing.development.json-> CAP:Enabled 设置为 false
docker run -d --name myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management
ELK 非必须
appsetTing.development.json-> LogToElasticSearch:Enabled 设置为 false
安装 Node.js, Npm Or Yarn
git clone https://github.com/WangJunZzz/abp-vnext-pro.git
OR
git clone https://github.com/WangJunZzz/abp-vnext-pro-gui.git
{
// Serilog 日志配置,生成环境修改日志级别
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Information",
"Volo.Abp": "Information",
"Hangfire": "Information",
"DotNetCore.CAP": "Information",
"Serilog.AspNetCore": "Information"
}
}
},
// 跨域设置
"App": {
"CorsOrigins": "https://*.ProjectName.com,http://localhost:4200,http://localhost:3100"
},
// 数据库连接字符串,修改为你本地的mysql地址
"ConnectionStrings": {
"Default": "Data source=localhost;Database=CompanyNameProjectNameDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
},
// redis缓存
"Cache": {
"redis": {
"ConnectionString": "localhost",
"password": "mypassword",
"DatabasEID": 0
}
},
// Jwt配置
"Jwt": {
"Audience": "CompanyNameProjectName",
//客户端标识
"SecurityKey": "dzehzRz9a8asdfasfdadfasdfasdfafsdadfasbasdf=",
"Issuer": "CompanyNameProjectName",
//签发者
"ExpirationTime": 24
//过期时间 hour
},
// 使用了Dotnetcore.cap的rabbitmq,false的情况基于内存
"Cap": {
"Enabled": "false",
"RabbitMq": {
"HostName": "localhost",
"UserName": "admin",
"password": "admin"
}
},
// es日志地址配置
"LogToElasticSearch": {
"Enabled": "true",
"ElasticSearch": {
"Url": "http://es.cn",
"IndexFormat": "companyname.projectname.development",
"UserName": "elastic",
"password": "aVVhjQ95RP7nbwNy",
"DashboardIndex": "companyname.projectname"
}
},
// identityserver地址
"httpClient": {
"Sts": {
"Url": "http://localhost:44354"
}
},
// Consul 服务发现和治理
"Consul": {
"Enabled": false,
"Host": "http://localhost:8500",
"service": "Project-service"
}
}
{
"App": {
"SelfUrl": "https://localhost:44354",
"ClientUrl": "http://localhost:4200",
"CorsOrigins": "https://*.ProjectName.com,http://localhost:4200,https://localhost:44307,https://localhost:44315",
"RedirectAllowedUrls": "http://localhost:4200,https://localhost:44307"
},
// mysql连接字符串
"ConnectionStrings": {
"Default": "Data source=localhost;Database=CompanyNameProjectNameDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
},
// redis
"redis": {
"Configuration": "localhost,password=mypassword"
}
}
// 迁移数据库
"ConnectionStrings": {
"Default": "Data source=localhost;Database=CompanyNameProjectNameDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
}
// 一定要打Tags,因为前端会根据这个生成代理类
// 建议参数都封装为一个Input
[SwaggerOperation(sumMary: "登录", Tags = new[] {"Account"})]
public Task<LoginOutput> LoginAsync(LoginInput input)
{
return _loginAppservice.LoginAsync(input);
}
在前端目录下配置代理的地址
"documentGenerator": {
"fromDocument": {
"url": "http://localhost:44315/swagger/v1/swagger.json", // 代理地址,只有生成的时候用,不区分环境
}
}
npm run nswag
前端多环境,.env.development 和.env.production
权限配置
菜单权限
/// <sumMary>
/// 发送普通文本消息
/// </sumMary>
/// <returns></returns>
/// <exception cref="NotificationManagementDomainException"></exception>
public async Task<Notification> SendCommontextAsync(String title, String content, List<Guid> receivEIDs)
{
if (receivEIDs is {Count: 0})
{
throw new NotificationManagementDomainException("消息接收人不能为空");
var senderId = Guid.Empty;
if (_currentUser?.Id != null)
{
senderId = _currentUser.Id.Value;
var entity = new Notification(GuidGenerator.Create(), title, content, messageType.Text, senderId);
foreach (var item in receivEIDs)
{
entity.AddNotificationSubscription(GuidGenerator.Create(), item);
var notificationEto = ObjectMapper.Map<Notification, NotificationEto>(entity);
// 发送集成事件
entity.AddCreatedNotificationDiStributedEvent(new CreatedNotificationDiStributedEvent(notificationEto));
return entity = await _notificationRepository.InsertAsync(entity);
}
/// <sumMary>
/// 发送消息
/// </sumMary>
public async Task SendmessageAsync(String title, String content, messageType messageType, List<String> users)
{
switch (messageTypE)
{
case messageType.Text:
await SendmessageToClientByUserIdAsync(new SendNotificationDto(title, content, messageTypE), users);
break;
case messageType.broadCast:
await SendmessageToAllClientAsync(new SendNotificationDto(title, content, messageTypE));
break;
default:
throw new UserFriendlyException("未知的消息类型");
}
}
// src/hooks/web/useSignalR.js
import * as signalR from "@microsoft/signalr";
import { usemessage } from "/@/hooks/web/usemessage";
import { useUserStoreWithOut } from "/@/store/modules/user";
export function useSignalR() {
/**
* 开始连接SignalR
*/
function startConnect(): void {
let connection = connectionsignalR();
//接收普通文本消息
connection.on("ReceiveTextmessageAsync", ReceiveTextmessageHandlerAsync);
//接收广播消息
connection.on("ReceiveBroadCastmessageAsync", ReceiveBroadCastmessageHandlerAsync);
//开始连接
connection.start();
}
/**
* 连接signalr
*/
function connectionsignalR(): signalR.HubConnection {
const userStore = useUserStoreWithOut();
const token = userStore.getToken;
const url = (import.meta.env.VITE_WEBSOCKE_URL as String) + "/ws/signalr/notification";
const connection = new signalR.HubConnectionBuilder()
.withUrl(url, {
accessTokenFactory: () => token,
skipNegotiation: true,
transport: signalR.httpTransportType.WebSockets,
})
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: (retryContext) => {
//重连规则:重连次数<300:间隔1s;重试次数<3000:间隔3s;重试次数>3000:间隔30s
let count = retryContext.previousRetryCount / 300;
if (count < 1) {
//重试次数<300,间隔1s
return 1000;
} else if (count < 10) {
//重试次数>300:间隔5s
return 1000 * 5;
} //重试次数>3000:间隔30s
else {
return 1000 * 30;
}
},
})
.configureLogging(signalR.LogLevel.Debug)
.build();
return connection;
}
/**
* 接收文本消息
* @param message 消息体
*/
function ReceiveTextmessageHandlerAsync(message: any) {
console.log(messagE);
const { notification } = usemessage();
notification.open({
message: message.title,
description: message.content,
});
}
/**
* 接收广播消息
* @param message 消息体
*/
function ReceiveBroadCastmessageHandlerAsync(message: any) {
const { notification } = usemessage();
notification.open({
message: message.title,
description: message.content,
});
}
return { startConnect };
}
"LogToElasticSearch": {
"Enabled": "false", // 如果为fasel,日志也会写入到本地,安装ELK,参考上面的docker-compose
"ElasticSearch": {
"Url": "http://es.cn",
"IndexFormat": "companyname.projectname.development",
"UserName": "elastic",
"password": "aVVhjQ95RP7nbwNy",
"DashboardIndex": "companyname.projectname"
}
},
public override void OnPostApplicationInitialization(ApplicationInitializationContext context)
{
context.CreateRecurringJob();
base.onPostApplicationInitialization(context);
}
集成 dotnetcore.CAP
在 appsetTing.development.json 设置是否开启
"Cap": {
"Enabled": "false", //如果为false 默认使用内存级别的队列,否则请安装rabbitmq
"RabbitMq": {
"HostName": "localhost",
"UserName": "admin",
"password": "admin"
}
},
private void ConfigurationCap(serviceConfigurationContext context)
{
var configuration = context.services.GetConfiguration();
var enabled = configuration.GetValue<bool>("Cap:Enabled", falsE);
if (enabled)
{
context.AddAbpCap(capOptions =>
{
capOptionS.UseEntityFramework<ProjectNameDbContext>();
capOptionS.UseRabbitMQ(option =>
{
option.HostName = configuration.GetValue<String>("Cap:rabbitMq:HostName");
option.UserName = configuration.GetValue<String>("Cap:rabbitMq:UserName");
option.password = configuration.GetValue<String>("Cap:rabbitMq:password");
});
var hosTingEnvironment = context.services.GetHosTingEnvironment();
bool auth = !hosTingEnvironment.IsDevelopment();
capOptionS.UseDashboard(options => { optionS.UseAuth = auth; });
});
}
else
{
context.AddAbpCap(capOptions =>
{
capOptionS.UseInMemoryStorage();
capOptionS.UseInMemorymessageQueue();
var hosTingEnvironment = context.services.GetHosTingEnvironment();
bool auth = !hosTingEnvironment.IsDevelopment();
capOptionS.UseDashboard(options => { optionS.UseAuth = auth; });
});
}
}
// 发送集成事件
entity.AddCreatedNotificationDiStributedEvent(new CreatedNotificationDiStributedEvent(notificationEto));
/// <sumMary>
/// 创建消息事件处理
/// </sumMary>
public class
CreatedNotificationDiStributedEventHandler : IDiStributedEventHandler<CreatedNotificationDiStributedEvent>,
ITransientDependency
{
private readonly INotificationAppservice _hubAppservice;
public CreatedNotificationDiStributedEventHandler(INotificationAppservice hubAppservicE)
{
_hubAppservice = hubAppservice;
}
public Task HandleEventAsync(CreatedNotificationDiStributedEvent eventData)
{
return _hubAppservice.SendmessageAsync(
eventData.NotificationEto.title,
eventData.NotificationEto.Content,
eventData.NotificationEto.messageType,
eventData.NotificationEto.NotificationSubscriptions.SELEct(e => e.ReceivEID.ToString()).ToList());
}
}
发布 httpApi.Host 到和 Dockerfile 同级目录
-- publish
-- Dockerfile
Dockerfile
FROM mcr.microsoft.com/dotnet/aspnet:5.0
# 创建目录
RUN mkdir /app
COPY publish /app
# 设置工作目录
WORKDIR /app
# 暴露80端口
EXPOSE 80
# 设置环境变量
ENV ASPNETCORE_ENVIRONMENT=Production
ENTRYPOINT ["dotnet", "CompanyName.ProjectName.httpApi.Host.dll"]
docker build -t abp-vnext-pro-admin .
docker run -itd --name abp-vnext-pro-admin -p 8011:80 abp-vnext-pro-admin
npm run build
FROM nginx:1.17.3-alpine as base
EXPOSE 80
COPY /_nginx/nginx.conf /etc/nginx/nginx.conf
COPY /_nginx/env.js /etc/nginx/env.js
COPY /_nginx/default.conf /etc/nginx/conf.d/default.conf
COPY /dist/ /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]
docker build -t abp-vnext-pro-ui .
docker run -itd --name abp-vnext-pro-ui -p 8012:80 abp-vnext-pro-ui
以上是大佬教程为你收集整理的Abp Vnext Vue3 的版本实现全部内容,希望文章能够帮你解决Abp Vnext Vue3 的版本实现所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。