74 Commits
Author SHA1 Message Date
不做码农 166975802b v3.7.8 2022-03-16 19:55:36 +08:00
不做码农 c9ee8d8cc3 优化菜单名称过长悬停显示标题 2022-03-15 16:55:46 +08:00
不做码农 22ba88a92c 修改批量删除字典数据信息问题 2022-03-15 15:52:58 +08:00
不做码农 a97c647b91 格式化代码 2022-03-13 19:17:25 +08:00
不做码农 ec1061f700 fix 单词拼写错误 2022-03-12 21:51:28 +08:00
不做码农 82aafaea8f 🌻🌻🌻update README.md 2022-03-11 20:53:59 +08:00
不做码农 bb806063a0 fix单词拼写错误 2022-03-11 20:51:02 +08:00
不做码农 eb32117b8c 优化文件存储 2022-03-10 21:39:46 +08:00
不做码农 3555833ae7 修改sys_file表 id为bigint类型移除自增改用雪花id 2022-03-10 21:33:14 +08:00
不做码农 a605e704e9 xignalR新增加自动重连 2022-03-10 15:07:36 +08:00
不做码农 6fd004cd35 修改文件存储默认排序为倒序 2022-03-10 15:05:58 +08:00
不做码农 7828f5995e 格式化代码 2022-03-10 15:04:23 +08:00
不做码农 d2077762d1 文件上传新增复制路径 2022-03-10 15:03:42 +08:00
不做码农 321619763e 文件上传增加拖拽 2022-03-10 15:02:59 +08:00
不做码农 075bdb8667 优化signalR连接 2022-03-09 21:30:59 +08:00
不做码农 6a3547dad2 新增signalR自动重连 2022-03-07 12:27:53 +08:00
不做码农 77c57dc459 !1 update document/admin-sqlserver.sql.
Merge pull request !1 from 武穆逸仙/N/A
2022-03-06 07:19:10 +00:00
武穆逸仙 1bed8cd217 update document/admin-sqlserver.sql.
1、插入sys_dept示例数据错误:
INSERT INTO sys_dept(parentId, deptName, orderNum, status, delFlag, create_by, create_time) VALUES (100, '研发部门',   1,  '0,100', '0', 'admin', GETDATE());
【 '0,100'对应的status字段,调整为0】



2、创建表错误:
CREATE TABLE sys_role_dept  (
  roleId bigint(20) NOT NULL, 				-- '角色ID',
  deptId bigint(20) NOT NULL ,				-- '部门ID',
)

修改为
CREATE TABLE sys_role_dept  (
  roleId bigint NOT NULL, 				-- '角色ID',
  deptId bigint NOT NULL ,				-- '部门ID',
)
2022-03-06 07:14:17 +00:00
不做码农 013b6ea4db fix Action参数校验问题 2022-03-06 12:01:52 +08:00
不做码农 e462b00e8e 前端新增缓存插件 2022-03-06 09:25:37 +08:00
不做码农 e14182c883 优化登录日志记录 2022-03-05 18:54:10 +08:00
不做码农 283472b424 新增不能对管理员账号进行删除 2022-03-05 18:53:04 +08:00
不做码农 acc10fde4a 优化代码 2022-03-05 16:48:40 +08:00
不做码农 6e8e649e88 删除 LogActionFilter.cs 2022-03-04 22:05:01 +08:00
不做码农 314eb40ed9 优化全局过滤器日志记录 2022-03-04 21:50:19 +08:00
不做码农 76c53b9915 update login.vue 2022-03-04 21:48:04 +08:00
不做码农 7bbb076c0e 优化日志记录 2022-03-04 21:00:21 +08:00
不做码农 af07ffc5d1 fix 修改用户信息、密码、头像提示没有权限操作 2022-03-04 18:30:14 +08:00
不做码农 261955e605 fix 操作日志没有数据弹出提示 2022-03-04 18:25:02 +08:00
不做码农 b7b32f509f 🍟🍟🍟 2022-03-03 21:07:58 +08:00
不做码农 35219931b0 优化appsetting.json配置文件 2022-03-03 20:55:37 +08:00
不做码农 9c89842ede ☕☕☕ 2022-03-03 18:39:31 +08:00
不做码农 dd01e00bb6 个人中心增加查看自己操作日志 2022-03-03 12:48:27 +08:00
不做码农 989700cb30 fix 登出bug 2022-03-03 09:44:28 +08:00
不做码农 9dddbd874b 优化代码 2022-03-02 21:55:30 +08:00
不做码农 c273ec2d25 优化Nlog记录日志 2022-03-02 21:22:44 +08:00
不做码农 e0c223d9e3 操作日志列表新增业务类型显示 2022-03-02 21:21:59 +08:00
不做码农 1c366f51c4 没有权限新增权限提示 2022-03-02 21:20:26 +08:00
不做码农 8c474aa450 操作日志列表新增业务类型显示 2022-03-02 21:18:20 +08:00
不做码农 cc3b329c3e 操作类型新增其他类型 2022-03-02 21:16:35 +08:00
不做码农 ef6ad49cec 优化代码,新增自定义字典方法封装 2022-03-01 21:26:18 +08:00
不做码农 e9b249c7ad update README.md 2022-03-01 21:25:19 +08:00
不做码农 8492d1f2b6 用户信息修改制定字段 2022-03-01 16:54:30 +08:00
不做码农 5e3d6a3c84 add HubsConstant.cs 2022-03-01 14:28:58 +08:00
不做码农 c6d8909994 删除Quartz.NET.WindowsService 2022-03-01 14:28:14 +08:00
不做码农 267469dc55 新增系统通知实时通知给连接的客户端 2022-03-01 14:04:21 +08:00
不做码农 06b81d5f5e 新增加icon菜单 2022-03-01 12:33:56 +08:00
不做码农 8c8b438ad4 新增加弹框modal封装 2022-03-01 11:09:16 +08:00
不做码农 3d457bc8c5 修改制台首页功能 2022-02-28 21:37:25 +08:00
不做码农 57eb5d6da5 升级包 2022-02-28 19:48:40 +08:00
不做码农 5c9b44727b 修改控制台首页 2022-02-28 18:38:14 +08:00
不做码农 f3724848eb 新增vue-seamless-scroll包 2022-02-28 18:37:57 +08:00
不做码农 a054dea93c 新增获取最新文章 2022-02-28 18:37:41 +08:00
不做码农 6c2b4bc56f 新增加signalR连接jwt认证 2022-02-28 18:37:23 +08:00
不做码农 c067951d50 更改signalR连接 2022-02-28 18:36:06 +08:00
不做码农 748b9065db 新增signalR连接 2022-02-27 21:11:46 +08:00
不做码农 2a84f7d322 修改文件上传表单字段可清空 2022-02-27 18:21:36 +08:00
不做码农 a7a0e5c16b 定时任务列表新增备注字段显示 2022-02-27 16:54:05 +08:00
不做码农 87163ae93a 修复选项卡点击右键刷新丢失参数问题 2022-02-27 16:38:44 +08:00
不做码农 58a4a54ed0 fix 用户多角色查询重复菜单bug 2022-02-27 09:02:18 +08:00
不做码农 1de9db2b77 升级部分包 2022-02-26 11:09:17 +08:00
不做码农 ae6ef55378 优化代码 2022-02-25 17:01:11 +08:00
不做码农 30566d8562 优化前端代码 2022-02-24 20:59:00 +08:00
不做码农 d4cbd437f7 页面若未匹配到字典标签则返回原字典值 2022-02-24 20:55:32 +08:00
不做码农 4754253e7c 删除 ConfigUtils.cs 2022-02-24 20:27:34 +08:00
不做码农 d4288331b4 优化代码生成模板 2022-02-24 20:23:34 +08:00
不做码农 ae31b3ec69 优化代码 2022-02-23 21:17:46 +08:00
不做码农 31cee32404 新增导航栏显示系统通知 2022-02-23 21:17:36 +08:00
不做码农 356ceb514f 优化样式 2022-02-23 20:04:51 +08:00
不做码农 6a209ec308 优化样式 2022-02-23 18:30:34 +08:00
不做码农 e98bde7ad5 优化配置文件查询 2022-02-23 18:30:17 +08:00
不做码农 3981fa2303 增加时间戳转换方法 2022-02-22 18:35:40 +08:00
不做码农 015fac766e Merge branch 'master' of https://gitee.com/izory/ZrAdminNetCore 2022-02-22 16:10:16 +08:00
不做码农 9d2c669bf5 任务新增异常信息记录 2022-02-22 16:09:18 +08:00
122 changed files with 2296 additions and 2030 deletions
+1
View File
@@ -269,3 +269,4 @@ __pycache__/
/ZR.Admin.WebApi/Properties/launchSettings.json /ZR.Admin.WebApi/Properties/launchSettings.json
/ZR.Admin.WebApi/ZRAdmin.xml /ZR.Admin.WebApi/ZRAdmin.xml
/ZR.Admin.WebApi/DataProtection /ZR.Admin.WebApi/DataProtection
/Quartz.NET.WindowsService
+78
View File
@@ -0,0 +1,78 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Infrastructure
{
public class AppSettings
{
static IConfiguration Configuration { get; set; }
public AppSettings(IConfiguration configuration)
{
Configuration = configuration;
}
/// <summary>
/// 封装要操作的字符
/// </summary>
/// <param name="sections">节点配置</param>
/// <returns></returns>
public static string App(params string[] sections)
{
try
{
if (sections.Any())
{
return Configuration[string.Join(":", sections)];
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return "";
}
/// <summary>
/// 递归获取配置信息数组
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sections"></param>
/// <returns></returns>
public static List<T> App<T>(params string[] sections)
{
List<T> list = new();
// 引用 Microsoft.Extensions.Configuration.Binder 包
Configuration.Bind(string.Join(":", sections), list);
return list;
}
public static T Bind<T>(string key, T t)
{
Configuration.Bind(key, t);
return t;
}
public static T GetAppConfig<T>(string key, T defaultValue = default)
{
T setting = (T)Convert.ChangeType(Configuration[key], typeof(T));
var value = setting;
if (setting == null)
value = defaultValue;
return value;
}
/// <summary>
/// 获取配置文件
/// </summary>
/// <param name="key">eg: WeChat:Token</param>
/// <returns></returns>
public static string GetConfig(string key)
{
return Configuration[key];
}
}
}
-61
View File
@@ -1,61 +0,0 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
/// <summary>
/// 需要引用包
/// Microsoft.Extensions.Configuration;
/// Microsoft.Extensions.DependencyInjection;
namespace Infrastructure
{
public class ConfigUtils
{
#region 单例访问
static ConfigUtils()
{
Configuration = App.ServiceProvider.GetRequiredService<IConfiguration>();
if (Instance == null)
Instance = new ConfigUtils();
}
public static ConfigUtils Instance { get; private set; }
#endregion
private static IConfiguration Configuration { get; set; }
public T GetAppConfig<T>(string key, T defaultValue = default(T))
{
T setting = (T)Convert.ChangeType(Configuration[key], typeof(T));
var value = setting;
if (setting == null)
value = defaultValue;
return value;
}
public T Bind<T>(string key, T t)
{
Configuration.Bind(key, t);
return t;
}
/// <summary>
/// 获取配置文件
/// </summary>
/// <param name="key">eg: WeChat:Token</param>
/// <returns></returns>
public string GetConfig(string key)
{
return Configuration[key];
}
/// <summary>
/// 获取数据库字符串连接串
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string GetConnectionString(string key)
{
return Configuration.GetConnectionString(key);
}
}
}
+16
View File
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Infrastructure.Constant
{
public class HubsConstant
{
private const string V = "receiveNotice";
public static string ReceiveNotice = V;
public static string OnlineNum = "onlineNum";
public static string MoreNotice = "moreNotice";
}
}
+28
View File
@@ -25,5 +25,33 @@ namespace Infrastructure
/// 用户权限缓存key /// 用户权限缓存key
/// </summary> /// </summary>
public static string UserPermKEY = "CACHE-USER-PERM"; public static string UserPermKEY = "CACHE-USER-PERM";
/// <summary>
/// 欢迎语
/// </summary>
public static string[] WelcomeMessages = new string[] {
"祝你开心每一天!",
"忙碌了一周,停一停脚步!",
"世间美好,与你环环相扣!",
"永远相信美好的事情即将发生!",
"每一天,遇见更好的自己!",
"保持热爱,奔赴山海!",
"生活明朗,万物可爱!",
"愿每一天醒来都是美好的开始!",
"没有希望的地方,就没有奋斗!",
"我最珍贵的时光都行走在路上!",
"成功,往往住在失败的隔壁!",
"人只要不失去方向,就不会失去自己!",
"每条堵住的路,都有一个出口!",
"没有谁能击垮你,除非你自甘堕落!",
"微笑着的人并非没有痛苦!",
"生活变的再糟糕,也不妨碍我变得更好!",
"你要悄悄努力,然后惊艳众人!",
"人与人之间最大的信任是精诚相见",
"人生就像爬坡,要一步一步来。",
"今天的目标完成了吗?",
"高效工作,告别996",
"销售是从别人拒绝开始的!"
};
} }
} }
+39
View File
@@ -19,6 +19,45 @@ namespace Infrastructure
} }
return dateTime ?? DateTime.Now; return dateTime ?? DateTime.Now;
} }
#region 时间戳转换
/// <summary>
/// 时间戳转本地时间-时间戳精确到秒
/// </summary>
public static DateTime ToLocalTimeDateBySeconds(long unix)
{
var dto = DateTimeOffset.FromUnixTimeSeconds(unix);
return dto.ToLocalTime().DateTime;
}
/// <summary>
/// 时间转时间戳Unix-时间戳精确到秒
/// </summary>
public static long ToUnixTimestampBySeconds(DateTime dt)
{
DateTimeOffset dto = new DateTimeOffset(dt);
return dto.ToUnixTimeSeconds();
}
/// <summary>
/// 时间戳转本地时间-时间戳精确到毫秒
/// </summary>
public static DateTime ToLocalTimeDateByMilliseconds(long unix)
{
var dto = DateTimeOffset.FromUnixTimeMilliseconds(unix);
return dto.ToLocalTime().DateTime;
}
/// <summary>
/// 时间转时间戳Unix-时间戳精确到毫秒
/// </summary>
public static long ToUnixTimestampByMilliseconds(DateTime dt)
{
DateTimeOffset dto = new DateTimeOffset(dt);
return dto.ToUnixTimeMilliseconds();
}
#endregion
#region 毫秒转天时分秒 #region 毫秒转天时分秒
/// <summary> /// <summary>
+1 -1
View File
@@ -12,7 +12,7 @@
<PackageReference Include="AspectCore.Abstractions" Version="2.2.0" /> <PackageReference Include="AspectCore.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" /> <PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="5.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+5
View File
@@ -111,6 +111,11 @@ namespace Infrastructure.Model
/// <param name="msg"></param> /// <param name="msg"></param>
/// <returns></returns> /// <returns></returns>
public static ApiResult Error(string msg) { return new ApiResult((int)ResultCode.CUSTOM_ERROR, msg); } public static ApiResult Error(string msg) { return new ApiResult((int)ResultCode.CUSTOM_ERROR, msg); }
public override string ToString()
{
return $"msg={Msg},data={Data}";
}
} }
public class ApiResult<T> : ApiResult public class ApiResult<T> : ApiResult
-10
View File
@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<appSettings>
<add key="url" value="http://127.0.0.1:8085/Health/index"/>
<add key="interval" value="1"/><!--执行时间间隔(分钟)-->
</appSettings>
</configuration>
-5
View File
@@ -1,5 +0,0 @@
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe G:\live_zhaorui\ZrryAdmin\ZrryAdmin_api\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe
Net Start Quartz.Net
sc config Quartz.Net start= auto
@@ -1,316 +0,0 @@
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
在“安装”阶段发生异常。
System.ComponentModel.Win32Exception: 指定的服务已存在。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“回退”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
在“安装”阶段发生异常。
System.ComponentModel.Win32Exception: 指定的服务已存在。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“回退”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
在“安装”阶段发生异常。
System.ComponentModel.Win32Exception: 指定的服务已存在。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“回退”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“安装”阶段已成功完成,正在开始“提交”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“提交”阶段已成功完成。
已完成事务处理安装。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
在“安装”阶段发生异常。
System.ComponentModel.Win32Exception: 指定的服务已存在。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“回退”阶段已成功完成。
已完成事务处理安装。
正在开始卸载。
查看日志文件的内容以获得 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
卸载完成。
正在运行事务处理安装。
正在开始安装的“安装”阶段。
查看日志文件的内容以获得 G:\live_zhaorui\ZrryAdmin\ZrryAdmin_api\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 G:\live_zhaorui\ZrryAdmin\ZrryAdmin_api\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
在“安装”阶段发生异常。
System.Security.SecurityException: 未找到源,但未能搜索某些或全部事件日志。 不可访问的日志: Security。
正在开始安装的“回退”阶段。
查看日志文件的内容以获得 G:\live_zhaorui\ZrryAdmin\ZrryAdmin_api\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe 程序集的进度。
该文件位于 G:\live_zhaorui\ZrryAdmin\ZrryAdmin_api\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.InstallLog。
“回退”阶段已成功完成。
已完成事务处理安装。
-25
View File
@@ -1,25 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace Quartz.NET.WindowsService
{
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
-57
View File
@@ -1,57 +0,0 @@
namespace Quartz.NET.WindowsService
{
partial class ProjectInstaller
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
this.Quartz定时作业 = new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// Quartz定时作业
//
this.Quartz定时作业.ServiceName = "Quartz.Net";
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.Quartz定时作业});
}
#endregion
private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1;
private System.ServiceProcess.ServiceInstaller Quartz定时作业;
}
}
@@ -1,19 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Linq;
using System.Threading.Tasks;
namespace Quartz.NET.WindowsService
{
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
public ProjectInstaller()
{
InitializeComponent();
}
}
}
@@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="serviceProcessInstaller1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="Quartz定时作业.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>243, 17</value>
</metadata>
<metadata name="$this.TrayLargeIcon" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
</root>
@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的一般信息由以下
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("Quartz.NET.WindowsService")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("Quartz.NET.WindowsService")]
[assembly: AssemblyCopyright("Copyright © Microsoft 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
//请将此类型的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("3040dd22-663e-44cb-909b-3d0043867361")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 生成号
// 修订号
//
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -1,108 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3040DD22-663E-44CB-909B-3D0043867361}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Quartz.NET.WindowsService</RootNamespace>
<AssemblyName>Quartz.NET.WindowsService</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<AutorunEnabled>true</AutorunEnabled>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Configuration.Install" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Runtime.Remoting" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ProjectInstaller.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ProjectInstaller.Designer.cs">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</Compile>
<Compile Include="Service1.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="Service1.Designer.cs">
<DependentUpon>Service1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="ProjectInstaller.resx">
<DependentUpon>ProjectInstaller.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.6.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.6.1 %28x86 和 x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
-37
View File
@@ -1,37 +0,0 @@
namespace Quartz.NET.WindowsService
{
partial class Service1
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region 组件设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要修改
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
this.ServiceName = "Service1";
}
#endregion
}
}
-94
View File
@@ -1,94 +0,0 @@
using System;
using System.Configuration;
using System.IO;
using System.Net;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Quartz.NET.WindowsService
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
Task.Run(() =>
{
Start();
});
}
private void Start()
{
string path = AppDomain.CurrentDomain.BaseDirectory + "\\log\\";
//默认1分钟调用一次
int interval = 1;
string message = "";
string url = "";
while (true)
{
try
{
ConfigurationManager.RefreshSection("appSettings");
url = ConfigurationManager.AppSettings["url"];
interval = Convert.ToInt32(ConfigurationManager.AppSettings["interval"]);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
Stream responseStream = response.GetResponseStream();
StreamReader streamReader = new StreamReader(responseStream, Encoding.UTF8);
message = streamReader.ReadToEnd();
}
}
catch (Exception ex)
{
message= url+ ",interval:["+ interval + "],"+ ex.Message;
}
finally
{
try
{
message = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "__" + message + "\r\n";
WriteFile(path, DateTime.Now.ToString("yyyy-MM-dd") + ".txt", message, true);
}
catch (Exception ex)
{
}
Thread.Sleep(new TimeSpan(0,interval,0));
}
}
}
private static void WriteFile(string path, string fileName, string content, bool appendToLast = false)
{
if (!Directory.Exists(path))//如果不存在就创建file文件夹
{
Directory.CreateDirectory(path);
}
using (FileStream stream = File.Open(path + fileName, FileMode.OpenOrCreate, FileAccess.Write))
{
byte[] by = Encoding.Default.GetBytes(content);
if (appendToLast)
{
stream.Position = stream.Length;
}
else
{
stream.SetLength(0);
}
stream.Write(by, 0, by.Length);
}
}
protected override void OnStop()
{
}
}
}
-1
View File
@@ -1 +0,0 @@
%SystemRoot%\Microsoft.NET\Framework\v4.0.30319\installutil.exe /u E:\Quartz.NET\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="Quartz" version="3.0.7" targetFramework="net461" />
<package id="Quartz.Serialization.Json" version="3.0.7" targetFramework="net461" />
</packages>
@@ -1,9 +0,0 @@
如果你只是将本项目发布到IIS,IIS应用池回收后就不能执行任务了,那么可以使用此windows服务器定时调用本项目的站点
1、修改App.config中的url属性value值为你当前部署的quertz.net的站点+/Common/Health
2、用记事本打开Install.bat文件修改 项目发布后的目录\bin\Debug\Quartz.NET.WindowsService.exe
改为:(这里填写你项目所在路径)\Quartz.NET.WindowsService\bin\Debug\Quartz.NET.WindowsService.exe
3、编译项目
4、点击Install.bat安装windows服务
卸载服务:运行Uninstall.bat(运行前按上面一样将修改Quartz.NET.WindowsService.exe路径)
+3 -3
View File
@@ -2,7 +2,7 @@
## 🍟概述 ## 🍟概述
* 本项目适合有一定NetCore和 vue基础的开发人员 * 本项目适合有一定NetCore和 vue基础的开发人员
* 基于.NET 5实现的通用权限管理平台(RBAC模式)。整合最新技术高效快速开发,前后端分离模式,开箱即用。 * 基于.NET5/.NET6实现的通用权限管理平台(RBAC模式)。整合最新技术高效快速开发,前后端分离模式,开箱即用。
* 代码量少、学习简单、通俗易懂、功能强大、易扩展、轻量级,让web开发更快速、简单高效(从此告别996),解决70%的重复工作,专注您的业务,轻松开发从现在开始! * 代码量少、学习简单、通俗易懂、功能强大、易扩展、轻量级,让web开发更快速、简单高效(从此告别996),解决70%的重复工作,专注您的业务,轻松开发从现在开始!
* 前端采用Vue2.0、Element UI。 * 前端采用Vue2.0、Element UI。
* 后端采用Net5、Sqlsugar、MySQL。 * 后端采用Net5、Sqlsugar、MySQL。
@@ -29,7 +29,7 @@
Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 element-ui,前端采用vscode工具开发 Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 element-ui,前端采用vscode工具开发
## 🍀后端技术 ## 🍀后端技术
核心框架:.Net5.0 + Web API + sqlsugar + swagger 核心框架:.Net5.0/.Net6 + Web API + sqlsugar + swagger + signalR
定时计划任务:Quartz.Net组件 定时计划任务:Quartz.Net组件
@@ -56,7 +56,7 @@ Vue版前端技术栈 :基于vue、vuex、vue-router 、vue-cli 、axios 和 e
12. 文章管理:可以写文章记录。 12. 文章管理:可以写文章记录。
13. 代码生成:可以一键生成前后端代码(.cs、.vue、.js、SQL文件等),支持下载,自定义配置前端展示控件、让开发更快捷高效。 13. 代码生成:可以一键生成前后端代码(.cs、.vue、.js、SQL文件等),支持下载,自定义配置前端展示控件、让开发更快捷高效。
14. 文件管理:可以上传文件 14. 文件管理:可以上传文件
15. 通知管理:系统通知公告信息发布维护。 15. 通知管理:系统通知公告信息发布维护,使用signalr实现对用户实时通知。
16. 参数管理:对系统动态配置常用参数。 16. 参数管理:对系统动态配置常用参数。
## 🍻项目结构 ## 🍻项目结构
@@ -12,7 +12,6 @@ using ZR.Admin.WebApi.Filters;
namespace ZR.Admin.WebApi.Controllers namespace ZR.Admin.WebApi.Controllers
{ {
[LogActionFilter]
public class BaseController : ControllerBase public class BaseController : ControllerBase
{ {
public static string TIME_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss"; public static string TIME_FORMAT_FULL = "yyyy-MM-dd HH:mm:ss";
+18 -12
View File
@@ -7,9 +7,11 @@ using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newtonsoft.Json; using Newtonsoft.Json;
using Snowflake.Core;
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Extensions;
using ZR.Admin.WebApi.Filters; using ZR.Admin.WebApi.Filters;
using ZR.Common; using ZR.Common;
@@ -158,25 +160,29 @@ namespace ZR.Admin.WebApi.Controllers
[HttpPost] [HttpPost]
[Verify] [Verify]
[ActionPermissionFilter(Permission = "common")] [ActionPermissionFilter(Permission = "common")]
public IActionResult UploadFileAliyun([FromForm(Name = "file")] IFormFile formFile, string fileName = "", string fileDir = "") public async Task<IActionResult> UploadFileAliyun([FromForm(Name = "file")] IFormFile formFile, string fileName = "", string fileDir = "")
{ {
if (fileDir.IsEmpty()) fileDir = "uploads";
if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空"); if (formFile == null) throw new CustomException(ResultCode.PARAM_ERROR, "上传文件不能为空");
string fileExt = Path.GetExtension(formFile.FileName); string fileExt = Path.GetExtension(formFile.FileName);//文件后缀
string[] AllowedFileExtensions = new string[] { ".jpg", ".gif", ".png", ".jpeg", ".webp", ".svga", ".xls", ".doc", ".zip", ".json", ".txt", ".bundle" }; double fileSize = formFile.Length / 1024.0;//文件大小KB
int MaxContentLength = 1024 * 1024 * 15; string[] NotAllowedFileExtensions = new string[] { ".bat", ".exe", ".jar", ".js" };
double fileSize = formFile.Length / 1024; int MaxContentLength = 15;
if (!AllowedFileExtensions.Contains(fileExt)) if (NotAllowedFileExtensions.Contains(fileExt))
{ {
return ToResponse(ResultCode.CUSTOM_ERROR, "上传失败,未经允许上传类型"); return ToResponse(ResultCode.CUSTOM_ERROR, "上传失败,未经允许上传类型");
} }
if ((fileSize / 1024) > MaxContentLength)
if (formFile.Length > MaxContentLength)
{ {
return ToResponse(ResultCode.CUSTOM_ERROR, "上传文件过大,不能超过 " + (MaxContentLength / 1024).ToString() + " MB"); return ToResponse(ResultCode.CUSTOM_ERROR, "上传文件过大,不能超过 " + MaxContentLength + " MB");
} }
(bool, string, string) result = SysFileService.SaveFile(fileDir, formFile, fileName); (bool, string, string) result = new();
long fileId = SysFileService.InsertFile(new SysFile() await Task.Run(() =>
{
result = SysFileService.SaveFile(fileDir, formFile, fileName, "");
});
long id = SysFileService.InsertFile(new SysFile()
{ {
AccessUrl = result.Item2, AccessUrl = result.Item2,
Create_by = HttpContext.GetName(), Create_by = HttpContext.GetName(),
@@ -193,7 +199,7 @@ namespace ZR.Admin.WebApi.Controllers
{ {
url = result.Item2, url = result.Item2,
fileName = result.Item3, fileName = result.Item3,
fileId fileId = id
}); });
} }
#endregion #endregion
@@ -54,6 +54,27 @@ namespace ZR.Admin.WebApi.Controllers
return SUCCESS(response); return SUCCESS(response);
} }
/// <summary>
/// 查询最新文章列表
/// </summary>
/// <returns></returns>
[HttpGet("newList")]
public IActionResult QueryNew()
{
//开始拼装查询条件
var predicate = Expressionable.Create<Article>();
//搜索条件
predicate = predicate.And(m => m.Status == "1");
var response = _ArticleService.Queryable()
.Where(predicate.ToExpression())
.Take(10)
.OrderBy(f => f.UpdateTime, OrderByType.Desc).ToList();
return SUCCESS(response);
}
/// <summary> /// <summary>
/// 获取文章目录,前端没用到 /// 获取文章目录,前端没用到
/// </summary> /// </summary>
@@ -237,7 +237,7 @@ namespace ZR.Admin.WebApi.Controllers
var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId); var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId);
genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId); genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId);
dto.DbType = ConfigUtils.Instance.GetAppConfig(OptionsSetting.ConnBusDbType, 0); dto.DbType = AppSettings.GetAppConfig(OptionsSetting.ConnBusDbType, 0);
dto.GenTable = genTableInfo; dto.GenTable = genTableInfo;
dto.IsPreview = true; dto.IsPreview = true;
//生成代码 //生成代码
@@ -263,7 +263,7 @@ namespace ZR.Admin.WebApi.Controllers
var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId); var genTableInfo = GenTableService.GetGenTableInfo(dto.TableId);
genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId); genTableInfo.Columns = GenTableColumnService.GenTableColumns(dto.TableId);
dto.DbType = ConfigUtils.Instance.GetAppConfig(OptionsSetting.ConnBusDbType, 0); dto.DbType = AppSettings.GetAppConfig(OptionsSetting.ConnBusDbType, 0);
dto.GenTable = genTableInfo; dto.GenTable = genTableInfo;
//自定义路径 //自定义路径
if (genTableInfo.GenType == "1") if (genTableInfo.GenType == "1")
@@ -46,7 +46,7 @@ namespace ZR.Admin.WebApi.Controllers
predicate = predicate.AndIF(parm.FileId != null, m => m.Id == parm.FileId); predicate = predicate.AndIF(parm.FileId != null, m => m.Id == parm.FileId);
//搜索条件查询语法参考Sqlsugar //搜索条件查询语法参考Sqlsugar
var response = _SysFileService.GetPages(predicate.ToExpression(), parm); var response = _SysFileService.GetPages(predicate.ToExpression(), parm, x => x.Id, OrderByType.Desc);
return SUCCESS(response); return SUCCESS(response);
} }
@@ -57,74 +57,13 @@ namespace ZR.Admin.WebApi.Controllers
/// <returns></returns> /// <returns></returns>
[HttpGet("{Id}")] [HttpGet("{Id}")]
[ActionPermissionFilter(Permission = "tool:file:query")] [ActionPermissionFilter(Permission = "tool:file:query")]
public IActionResult GetSysFile(int Id) public IActionResult GetSysFile(long Id)
{ {
var response = _SysFileService.GetFirst(x => x.Id == Id); var response = _SysFileService.GetFirst(x => x.Id == Id);
return SUCCESS(response); return SUCCESS(response);
} }
///// <summary>
///// 添加文件存储
///// </summary>
///// <returns></returns>
//[HttpPost]
//[ActionPermissionFilter(Permission = "tool:file:add")]
//[Log(Title = "文件存储", BusinessType = BusinessType.INSERT)]
//public IActionResult AddSysFile([FromBody] SysFileDto parm)
//{
// if (parm == null)
// {
// throw new CustomException("请求参数错误");
// }
// //从 Dto 映射到 实体
// var model = parm.Adapt<SysFile>().ToCreate(HttpContext);
// var response = _SysFileService.Insert(model, it => new
// {
// it.FileName,
// it.FileUrl,
// it.StorePath,
// it.FileSize,
// it.FileExt,
// it.Create_by,
// it.Create_time,
// it.StoreType,
// it.AccessUrl,
// });
// return ToResponse(response);
//}
///// <summary>
///// 更新文件存储
///// </summary>
///// <returns></returns>
//[HttpPut]
//[ActionPermissionFilter(Permission = "tool:file:update")]
//[Log(Title = "文件存储", BusinessType = BusinessType.UPDATE)]
//public IActionResult UpdateSysFile([FromBody] SysFileDto parm)
//{
// if (parm == null)
// {
// throw new CustomException("请求实体不能为空");
// }
// //从 Dto 映射到 实体
// var model = parm.Adapt<SysFile>().ToUpdate(HttpContext);
// var response = _SysFileService.Update(w => w.Id == model.Id, it => new SysFile()
// {
// //Update 字段映射
// FileUrl = model.FileUrl,
// StorePath = model.StorePath,
// FileSize = model.FileSize,
// FileExt = model.FileExt,
// StoreType = model.StoreType,
// AccessUrl = model.AccessUrl,
// });
// return ToResponse(response);
//}
/// <summary> /// <summary>
/// 删除文件存储 /// 删除文件存储
/// </summary> /// </summary>
@@ -134,7 +73,7 @@ namespace ZR.Admin.WebApi.Controllers
[Log(Title = "文件存储", BusinessType = BusinessType.DELETE)] [Log(Title = "文件存储", BusinessType = BusinessType.DELETE)]
public IActionResult DeleteSysFile(string ids) public IActionResult DeleteSysFile(string ids)
{ {
int[] idsArr = Tools.SpitIntArrary(ids); long[] idsArr = Tools.SpitLongArrary(ids);
if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); } if (idsArr.Length <= 0) { return ToResponse(ApiResult.Error($"删除失败Id 不能为空")); }
var response = _SysFileService.Delete(idsArr); var response = _SysFileService.Delete(idsArr);
@@ -17,6 +17,8 @@ using Hei.Captcha;
using ZR.Common; using ZR.Common;
using ZR.Service.System; using ZR.Service.System;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using UAParser;
using IPTools.Core;
namespace ZR.Admin.WebApi.Controllers.System namespace ZR.Admin.WebApi.Controllers.System
{ {
@@ -66,7 +68,7 @@ namespace ZR.Admin.WebApi.Controllers.System
/// <returns></returns> /// <returns></returns>
[Route("login")] [Route("login")]
[HttpPost] [HttpPost]
[Log(Title = "登录")] //[Log(Title = "登录")]
public IActionResult Login([FromBody] LoginBodyDto loginBody) public IActionResult Login([FromBody] LoginBodyDto loginBody)
{ {
if (loginBody == null) { throw new CustomException("请求参数错误"); } if (loginBody == null) { throw new CustomException("请求参数错误"); }
@@ -77,13 +79,11 @@ namespace ZR.Admin.WebApi.Controllers.System
return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误"); return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误");
} }
var user = sysLoginService.Login(loginBody, AsyncFactory.RecordLogInfo(httpContextAccessor.HttpContext, "0", "login")); var user = sysLoginService.Login(loginBody, RecordLogInfo(httpContextAccessor.HttpContext));
#region 存入cookie Action校验权限使用
List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId); List<SysRole> roles = roleService.SelectUserRoleListByUserId(user.UserId);
//权限集合 eg *:*:*,system:user:list //权限集合 eg *:*:*,system:user:list
List<string> permissions = permissionService.GetMenuPermission(user); List<string> permissions = permissionService.GetMenuPermission(user);
#endregion
LoginUser loginUser = new(user, roles, permissions); LoginUser loginUser = new(user, roles, permissions);
CacheHelper.SetCache(GlobalConstant.UserPermKEY + user.UserId, loginUser); CacheHelper.SetCache(GlobalConstant.UserPermKEY + user.UserId, loginUser);
@@ -104,9 +104,10 @@ namespace ZR.Admin.WebApi.Controllers.System
// await HttpContext.SignOutAsync(); // await HttpContext.SignOutAsync();
//}).Wait(); //}).Wait();
var id = HttpContext.GetUId(); var id = HttpContext.GetUId();
var name = HttpContext.GetName();
CacheHelper.Remove(GlobalConstant.UserPermKEY + id); CacheHelper.Remove(GlobalConstant.UserPermKEY + id);
return SUCCESS(1); return SUCCESS(new { name , id});
} }
/// <summary> /// <summary>
@@ -125,7 +126,7 @@ namespace ZR.Admin.WebApi.Controllers.System
List<string> roles = permissionService.GetRolePermission(user); List<string> roles = permissionService.GetRolePermission(user);
//权限集合 eg *:*:*,system:user:list //权限集合 eg *:*:*,system:user:list
List<string> permissions = permissionService.GetMenuPermission(user); List<string> permissions = permissionService.GetMenuPermission(user);
user.WelcomeContent = GlobalConstant.WelcomeMessages[new Random().Next(0, GlobalConstant.WelcomeMessages.Length)];
return SUCCESS(new { user, roles, permissions }); return SUCCESS(new { user, roles, permissions });
} }
@@ -179,5 +180,27 @@ namespace ZR.Admin.WebApi.Controllers.System
return ToJson(1, obj); return ToJson(1, obj);
} }
/// <summary>
/// 记录用户登陆信息
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public SysLogininfor RecordLogInfo(HttpContext context)
{
var ipAddr = context.GetClientUserIp();
var ip_info = IpTool.Search(ipAddr);
ClientInfo clientInfo = context.GetClientInfo();
SysLogininfor sysLogininfor = new()
{
browser = clientInfo.Device.Family,
os = clientInfo.OS.ToString(),
ipaddr = ipAddr,
userName = context.GetName(),
loginLocation = ip_info.Province + "-" + ip_info.City
};
return sysLogininfor;
}
} }
} }
@@ -1,8 +1,5 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System; using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Infrastructure; using Infrastructure;
using Infrastructure.Attribute; using Infrastructure.Attribute;
using Infrastructure.Enums; using Infrastructure.Enums;
@@ -15,6 +12,9 @@ using ZR.Common;
using ZR.Model.Dto; using ZR.Model.Dto;
using ZR.Model.Models; using ZR.Model.Models;
using ZR.Service.System.IService; using ZR.Service.System.IService;
using ZR.Admin.WebApi.Hubs;
using Microsoft.AspNetCore.SignalR;
using Infrastructure.Constant;
namespace ZR.Admin.WebApi.Controllers.System namespace ZR.Admin.WebApi.Controllers.System
{ {
@@ -26,10 +26,28 @@ namespace ZR.Admin.WebApi.Controllers.System
/// 通知公告表接口 /// 通知公告表接口
/// </summary> /// </summary>
private readonly ISysNoticeService _SysNoticeService; private readonly ISysNoticeService _SysNoticeService;
private readonly IHubContext<MessageHub> _hubContext;
public SysNoticeController(ISysNoticeService SysNoticeService) public SysNoticeController(ISysNoticeService SysNoticeService, IHubContext<MessageHub> hubContext)
{ {
_SysNoticeService = SysNoticeService; _SysNoticeService = SysNoticeService;
_hubContext = hubContext;
}
/// <summary>
/// 查询通知公告表列表
/// </summary>
/// <returns></returns>
[HttpGet("queryNotice")]
public IActionResult QueryNotice([FromQuery] SysNoticeQueryDto parm)
{
//开始拼装查询条件
var predicate = Expressionable.Create<SysNotice>();
//搜索条件查询语法参考Sqlsugar
predicate = predicate.And(m => m.Status == "0");
var response = _SysNoticeService.GetPages(predicate.ToExpression(), parm);
return SUCCESS(response);
} }
/// <summary> /// <summary>
@@ -47,6 +65,7 @@ namespace ZR.Admin.WebApi.Controllers.System
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.NoticeTitle), m => m.NoticeTitle.Contains(parm.NoticeTitle)); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.NoticeTitle), m => m.NoticeTitle.Contains(parm.NoticeTitle));
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.NoticeType), m => m.NoticeType == parm.NoticeType); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.NoticeType), m => m.NoticeType == parm.NoticeType);
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.CreateBy), m => m.Create_by.Contains(parm.CreateBy) || m.Update_by.Contains(parm.CreateBy)); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.CreateBy), m => m.Create_by.Contains(parm.CreateBy) || m.Update_by.Contains(parm.CreateBy));
predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.Status), m => m.Status == parm.Status);
var response = _SysNoticeService.GetPages(predicate.ToExpression(), parm); var response = _SysNoticeService.GetPages(predicate.ToExpression(), parm);
return SUCCESS(response); return SUCCESS(response);
} }
@@ -79,11 +98,11 @@ namespace ZR.Admin.WebApi.Controllers.System
throw new CustomException("请求参数错误"); throw new CustomException("请求参数错误");
} }
//从 Dto 映射到 实体 //从 Dto 映射到 实体
var model = parm.Adapt<SysNotice>().ToCreate(HttpContext); var modal = parm.Adapt<SysNotice>().ToCreate(HttpContext);
model.Create_by = User.Identity.Name; modal.Create_by = User.Identity.Name;
model.Create_time = DateTime.Now; modal.Create_time = DateTime.Now;
return SUCCESS(_SysNoticeService.Insert(model, it => new int result = _SysNoticeService.Insert(modal, it => new
{ {
it.NoticeTitle, it.NoticeTitle,
it.NoticeType, it.NoticeType,
@@ -92,7 +111,9 @@ namespace ZR.Admin.WebApi.Controllers.System
it.Remark, it.Remark,
it.Create_by, it.Create_by,
it.Create_time it.Create_time
})); });
return SUCCESS(result);
} }
/// <summary> /// <summary>
@@ -125,6 +146,26 @@ namespace ZR.Admin.WebApi.Controllers.System
return SUCCESS(response); return SUCCESS(response);
} }
/// <summary>
/// 发送通知公告表
/// </summary>
/// <returns></returns>
[HttpPut("send/{NoticeId}")]
[ActionPermissionFilter(Permission = "system:notice:update")]
[Log(Title = "通知公告表", BusinessType = BusinessType.OTHER)]
public IActionResult SendNotice(int NoticeId = 0)
{
if (NoticeId <= 0)
{
throw new CustomException("请求实体不能为空");
}
var response = _SysNoticeService.GetFirst(x => x.NoticeId == NoticeId);
if (response != null && response.Status == "0")
{
_hubContext.Clients.All.SendAsync(HubsConstant.ReceiveNotice, response.NoticeTitle, response.NoticeContent);
}
return SUCCESS(response);
}
/// <summary> /// <summary>
/// 删除通知公告表 /// 删除通知公告表
@@ -69,7 +69,7 @@ namespace ZR.Admin.WebApi.Controllers.System
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPut] [HttpPut]
[ActionPermissionFilter(Permission = "system")] [ActionPermissionFilter(Permission = "common")]
[Log(Title = "修改信息", BusinessType = BusinessType.UPDATE)] [Log(Title = "修改信息", BusinessType = BusinessType.UPDATE)]
public IActionResult UpdateProfile([FromBody] SysUserDto userDto) public IActionResult UpdateProfile([FromBody] SysUserDto userDto)
{ {
@@ -89,7 +89,7 @@ namespace ZR.Admin.WebApi.Controllers.System
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPut("updatePwd")] [HttpPut("updatePwd")]
[ActionPermissionFilter(Permission = "system")] [ActionPermissionFilter(Permission = "common")]
[Log(Title = "修改密码", BusinessType = BusinessType.UPDATE)] [Log(Title = "修改密码", BusinessType = BusinessType.UPDATE)]
public IActionResult UpdatePwd(string oldPassword, string newPassword) public IActionResult UpdatePwd(string oldPassword, string newPassword)
{ {
@@ -122,7 +122,7 @@ namespace ZR.Admin.WebApi.Controllers.System
/// <param name="formFile"></param> /// <param name="formFile"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost("Avatar")] [HttpPost("Avatar")]
[ActionPermissionFilter(Permission = "system")] [ActionPermissionFilter(Permission = "common")]
[Log(Title = "修改头像", BusinessType = BusinessType.UPDATE, IsSaveRequestData = false)] [Log(Title = "修改头像", BusinessType = BusinessType.UPDATE, IsSaveRequestData = false)]
public IActionResult Avatar([FromForm(Name = "picture")] IFormFile formFile) public IActionResult Avatar([FromForm(Name = "picture")] IFormFile formFile)
{ {
@@ -133,7 +133,6 @@ namespace ZR.Admin.WebApi.Controllers.System
string fileExt = Path.GetExtension(formFile.FileName); string fileExt = Path.GetExtension(formFile.FileName);
string savePath = Path.Combine(hostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads")); string savePath = Path.Combine(hostEnvironment.WebRootPath, FileUtil.GetdirPath("uploads"));
Console.WriteLine(savePath);
if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); }
string fileName = FileUtil.HashFileName() + fileExt; string fileName = FileUtil.HashFileName() + fileExt;
@@ -146,7 +145,6 @@ namespace ZR.Admin.WebApi.Controllers.System
string accessUrl = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads")}{fileName}"; string accessUrl = $"{OptionsSetting.Upload.UploadUrl}/{FileUtil.GetdirPath("uploads")}{fileName}";
UserService.UpdatePhoto(new SysUser() { Avatar = accessUrl, UserId = loginUser.UserId }); UserService.UpdatePhoto(new SysUser() { Avatar = accessUrl, UserId = loginUser.UserId });
logger.Info("修改头像:" + accessUrl);
return SUCCESS(new { imgUrl = accessUrl }); return SUCCESS(new { imgUrl = accessUrl });
} }
} }
@@ -150,7 +150,7 @@ namespace ZR.Admin.WebApi.Controllers.System
public IActionResult Remove(int userid = 0) public IActionResult Remove(int userid = 0)
{ {
if (userid <= 0) { return ToResponse(ApiResult.Error(101, "请求参数错误")); } if (userid <= 0) { return ToResponse(ApiResult.Error(101, "请求参数错误")); }
if (userid == 1) return ToResponse(Infrastructure.ResultCode.FAIL, "不能删除管理员账号");
int result = UserService.DeleteUser(userid); int result = UserService.DeleteUser(userid);
return ToResponse(ToJson(result)); return ToResponse(ToJson(result));
@@ -38,11 +38,11 @@ namespace ZR.Admin.WebApi.Controllers.monitor
[HttpGet("list")] [HttpGet("list")]
public IActionResult OperList([FromQuery] SysOperLogDto sysOperLog) public IActionResult OperList([FromQuery] SysOperLogDto sysOperLog)
{ {
PagerInfo pagerInfo = new PagerInfo(sysOperLog.pageNum); PagerInfo pagerInfo = new(sysOperLog.pageNum, sysOperLog.PageSize);
var list = sysOperLogService.SelectOperLogList(sysOperLog, pagerInfo); var list = sysOperLogService.SelectOperLogList(sysOperLog, pagerInfo);
return ToResponse(ToJson(list.TotalNum, list), TIME_FORMAT_FULL_2); return SUCCESS(list, "MM/dd HH:mm");
} }
/// <summary> /// <summary>
+2 -2
View File
@@ -37,12 +37,12 @@ namespace ZR.Admin.WebApi.Extensions
ConfigId = "0", ConfigId = "0",
ConnectionString = connStr, ConnectionString = connStr,
DbType = (IocDbType)dbType, DbType = (IocDbType)dbType,
IsAutoCloseConnection = true//自动释放 IsAutoCloseConnection = true
}, new IocConfig() { }, new IocConfig() {
ConfigId = "1", ConfigId = "1",
ConnectionString = connStrBus, ConnectionString = connStrBus,
DbType = (IocDbType)dbType_bus, DbType = (IocDbType)dbType_bus,
IsAutoCloseConnection = true//自动释放 IsAutoCloseConnection = true
} }
}); });
//每次Sql执行前事件 //每次Sql执行前事件
@@ -34,21 +34,11 @@ namespace ZR.Admin.WebApi.Extensions
if (types.GetProperty("Create_by") != null && context != null) if (types.GetProperty("Create_by") != null && context != null)
{ {
types.GetProperty("Create_by").SetValue(source, context.GetName(), null); types.GetProperty("Create_by").SetValue(source, context.GetName(), null);
// types.GetProperty("CreateName").SetValue(source, userSession.UserName, null);
} }
if (types.GetProperty("UserId") != null && context != null) if (types.GetProperty("UserId") != null && context != null)
{ {
types.GetProperty("UserId").SetValue(source, context.GetUId(), null); types.GetProperty("UserId").SetValue(source, context.GetUId(), null);
} }
//if (types.GetProperty("UpdateID") != null)
//{
// types.GetProperty("UpdateID").SetValue(source, userSession.UserID, null);
// types.GetProperty("UpdateName").SetValue(source, userSession.UserName, null);
//}
return source; return source;
} }
@@ -6,8 +6,10 @@ using Microsoft.AspNetCore.Http;
using Newtonsoft.Json; using Newtonsoft.Json;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Security.Claims; using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using UAParser; using UAParser;
@@ -161,6 +163,32 @@ namespace ZR.Admin.WebApi.Extensions
}); });
}).Wait(); }).Wait();
} }
/// <summary>
/// 设置请求参数
/// </summary>
/// <param name="operLog"></param>
/// <param name="context"></param>
public static void GetRequestValue(this HttpContext context, SysOperLog operLog)
{
string reqMethod = operLog.requestMethod;
string param;
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod))
{
context.Request.Body.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
//需要使用异步方式才能获取
param = reader.ReadToEndAsync().Result;
}
else
{
param = context.Request.QueryString.Value.ToString();
}
operLog.operParam = param;
}
} }
} }
@@ -34,8 +34,6 @@ namespace ZR.Admin.WebApi.Extensions
{ {
var _tasksQzService = (ISysTasksQzService)App.GetRequiredService(typeof(ISysTasksQzService)); var _tasksQzService = (ISysTasksQzService)App.GetRequiredService(typeof(ISysTasksQzService));
//此写法不通过有待研究
//var _tasksQzService2 = (ISysTasksQzService)services.GetRequiredService(typeof(SysTasksQzService));
ITaskSchedulerServer _schedulerServer = App.GetRequiredService<ITaskSchedulerServer>(); ITaskSchedulerServer _schedulerServer = App.GetRequiredService<ITaskSchedulerServer>();
var tasks = _tasksQzService.GetList(m => m.IsStart); var tasks = _tasksQzService.GetList(m => m.IsStart);
@@ -1,4 +1,5 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Model;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using System.Collections.Generic; using System.Collections.Generic;
@@ -57,8 +58,8 @@ namespace ZR.Admin.WebApi.Filters
HasPermi = perms.Exists(f => f.ToLower() == Permission.ToLower()); HasPermi = perms.Exists(f => f.ToLower() == Permission.ToLower());
} }
bool isDemoMode = ConfigUtils.Instance.GetAppConfig("DemoMode", false); bool isDemoMode = AppSettings.GetAppConfig("DemoMode", false);
var url = context.HttpContext.Request.Path;
//演示公开环境屏蔽权限 //演示公开环境屏蔽权限
string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "send", "export", "upload", "common" }; string[] denyPerms = new string[] { "update", "add", "remove", "add", "edit", "delete", "import", "run", "start", "stop", "clear", "send", "export", "upload", "common" };
if (isDemoMode && denyPerms.Any(f => Permission.ToLower().Contains(f))) if (isDemoMode && denyPerms.Any(f => Permission.ToLower().Contains(f)))
@@ -67,8 +68,17 @@ namespace ZR.Admin.WebApi.Filters
} }
if (!HasPermi && !Permission.Equals("common")) if (!HasPermi && !Permission.Equals("common"))
{ {
logger.Info($"用户{info.UserName}没有权限访问{context.HttpContext.Request.Path},当前权限[{Permission}]"); logger.Info($"用户{info.UserName}没有权限访问{url},当前权限[{Permission}]");
context.Result = new JsonResult(new { code = ResultCode.FORBIDDEN, msg = "你没有权限访问" }); JsonResult result = new(new ApiResult()
{
Code = (int)ResultCode.FORBIDDEN,
Msg = $"你当前没有权限[{Permission}]访问,请联系管理员",
Data = url
})
{
ContentType = "application/json",
};
context.Result = result;
} }
} }
+104 -10
View File
@@ -1,27 +1,43 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Attribute;
using Infrastructure.Model; using Infrastructure.Model;
using IPTools.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
using NLog; using NLog;
using System; using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.Admin.WebApi.Extensions;
using ZR.Model.System;
using ZR.Service.System.IService;
namespace ZR.Admin.WebApi.Filters namespace ZR.Admin.WebApi.Filters
{ {
public class GlobalActionMonitor : Attribute, IActionFilter public class GlobalActionMonitor : ActionFilterAttribute
{ {
static readonly Logger logger = LogManager.GetCurrentClassLogger(); static readonly Logger logger = LogManager.GetCurrentClassLogger();
private ISysOperLogService OperLogService;
public GlobalActionMonitor(ISysOperLogService operLogService)
{
OperLogService = operLogService;
}
/// <summary> /// <summary>
/// OnActionExecuting是在Action执行之前运行的方法。 /// Action请求前
/// </summary> /// </summary>
/// <param name="context"></param> /// <param name="context"></param>
public void OnActionExecuting(ActionExecutingContext context) /// <param name="next"></param>
/// <returns></returns>
public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{ {
if (context.ModelState.IsValid) return; ApiResult response = new();
ApiResult response = new ApiResult();
response.Code = (int)ResultCode.PARAM_ERROR; response.Code = (int)ResultCode.PARAM_ERROR;
//var keys = context.ModelState.Keys;
var values = context.ModelState.Values; var values = context.ModelState.Values;
foreach (var item in values) foreach (var item in values)
{ {
@@ -29,7 +45,7 @@ namespace ZR.Admin.WebApi.Filters
{ {
if (err.ErrorMessage.Contains("JSON")) if (err.ErrorMessage.Contains("JSON"))
{ {
return; return next();
} }
if (!string.IsNullOrEmpty(response.Msg)) if (!string.IsNullOrEmpty(response.Msg))
{ {
@@ -39,16 +55,94 @@ namespace ZR.Admin.WebApi.Filters
response.Msg += err.ErrorMessage; response.Msg += err.ErrorMessage;
} }
} }
logger.Info($"请求参数错误,{response.Msg}"); if (!string.IsNullOrEmpty(response.Msg))
context.Result = new JsonResult(response); {
logger.Info($"请求参数错误,{response.Msg}");
context.Result = new JsonResult(response);
}
return base.OnActionExecutionAsync(context, next);
} }
/// <summary> /// <summary>
/// OnActionExecuted是在Action中的代码执行之后运行的方法。 /// OnActionExecuted是在Action中的代码执行之后运行的方法。
/// </summary> /// </summary>
/// <param name="context"></param> /// <param name="context"></param>
public void OnActionExecuted(ActionExecutedContext context) public override void OnResultExecuted(ResultExecutedContext context)
{ {
if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
//获得注解信息
LogAttribute logAttribute = GetLogAttribute(controllerActionDescriptor);
if (logAttribute == null) return;
try
{
string method = context.HttpContext.Request.Method.ToUpper();
// 获取当前的用户
string userName = context.HttpContext.GetName();
string jsonResult = string.Empty;
if (context.Result is ContentResult result && result.ContentType == "application/json")
{
jsonResult = result.Content.Replace("\r\n", "").Trim();
}
if (context.Result is JsonResult result2)
{
jsonResult = result2.Value?.ToString();
}
//获取当前执行方法的类名
//string className = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;
//获取当前成员的名称
//string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
string controller = context.RouteData.Values["Controller"].ToString();
string action = context.RouteData.Values["Action"].ToString();
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
var ip_info = IpTool.Search(ip);
SysOperLog sysOperLog = new()
{
status = 0,
operName = userName,
operIp = ip,
operUrl = HttpContextExtension.GetRequestUrl(context.HttpContext),
requestMethod = method,
jsonResult = jsonResult,
operLocation = ip_info.Province + " " + ip_info.City,
method = controller + "." + action + "()",
//Elapsed = _stopwatch.ElapsedMilliseconds,
operTime = DateTime.Now
};
HttpContextExtension.GetRequestValue(context.HttpContext, sysOperLog);
if (logAttribute != null)
{
sysOperLog.title = logAttribute?.Title;
sysOperLog.businessType = (int)logAttribute?.BusinessType;
sysOperLog.operParam = logAttribute.IsSaveRequestData ? sysOperLog.operParam : "";
sysOperLog.jsonResult = logAttribute.IsSaveResponseData ? sysOperLog.jsonResult : "";
}
LogEventInfo ei = new(LogLevel.Info, "GlobalActionMonitor", "");
ei.Properties["jsonResult"] = !HttpMethods.IsGet(method) ? jsonResult : "";
ei.Properties["requestParam"] = sysOperLog.operParam;
ei.Properties["user"] = userName;
logger.Log(ei);
OperLogService.InsertOperlog(sysOperLog);
}
catch (Exception ex)
{
logger.Error(ex, $"记录操作日志出错了#{ex.Message}");
}
}
private LogAttribute GetLogAttribute(ControllerActionDescriptor controllerActionDescriptor)
{
var attribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
.FirstOrDefault(a => a.GetType().Equals(typeof(LogAttribute)));
return (LogAttribute)attribute;
} }
} }
} }
-133
View File
@@ -1,133 +0,0 @@
using Infrastructure;
using Infrastructure.Attribute;
using IPTools.Core;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using NLog;
using System;
using System.IO;
using System.Linq;
using System.Text;
using ZR.Admin.WebApi.Extensions;
using ZR.Model.System;
using ZR.Service.System.IService;
namespace ZR.Admin.WebApi.Filters
{
/// <summary>
/// 记录请求,输出日志
/// </summary>
public class LogActionFilter : ActionFilterAttribute
{
static readonly Logger logger = LogManager.GetCurrentClassLogger();
/// <summary>
/// OnActionExecuted是在Action中的代码执行之后运行的方法。
/// </summary>
/// <param name="context"></param>
public override void OnResultExecuted(ResultExecutedContext context)
{
if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return;
//获得注解信息
LogAttribute logAttribute = GetLogAttribute(controllerActionDescriptor);
if (logAttribute == null) return;
try
{
string method = context.HttpContext.Request.Method.ToUpper();
// 获取当前的用户
string userName = context.HttpContext.GetName();
string jsonResult = string.Empty;
if (context.Result is ContentResult result && result.ContentType == "application/json")
{
jsonResult = result.Content.Replace("\r\n", "").Trim();
}
//获取当前执行方法的类名
//string className = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name;
//获取当前成员的名称
//string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
string controller = context.RouteData.Values["Controller"].ToString();
string action = context.RouteData.Values["Action"].ToString();
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
var ip_info = IpTool.Search(ip);
SysOperLog sysOperLog = new SysOperLog
{
status = 0,
operName = userName,
operIp = ip,
operUrl = HttpContextExtension.GetRequestUrl(context.HttpContext),
requestMethod = method,
jsonResult = jsonResult,
operLocation = ip_info.Province + " " + ip_info.City,
method = controller + "." + action + "()",
//Elapsed = _stopwatch.ElapsedMilliseconds,
operTime = DateTime.Now
};
GetRequestValue(sysOperLog, context.HttpContext);
if (logAttribute != null)
{
sysOperLog.title = logAttribute?.Title;
sysOperLog.businessType = (int)logAttribute?.BusinessType;
sysOperLog.operParam = logAttribute.IsSaveRequestData ? sysOperLog.operParam : "";
sysOperLog.jsonResult = logAttribute.IsSaveResponseData ? sysOperLog.jsonResult : "";
}
var sysOperLogService = (ISysOperLogService)App.GetRequiredService(typeof(ISysOperLogService));
sysOperLogService.InsertOperlog(sysOperLog);
LogEventInfo ei = new(LogLevel.Info, "GlobalExceptionMiddleware", "");
ei.Properties["status"] = 0;
ei.Properties["jsonResult"] = !HttpMethods.IsGet(method) ? jsonResult : "";
ei.Properties["requestParam"] = sysOperLog.operParam;
ei.Properties["user"] = userName;
logger.Log(ei);
}
catch (Exception ex)
{
logger.Error(ex, $"记录操作日志出错了#{ex.Message}");
}
}
private LogAttribute GetLogAttribute(ControllerActionDescriptor controllerActionDescriptor)
{
var attribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true)
.FirstOrDefault(a => a.GetType().Equals(typeof(LogAttribute)));
return (LogAttribute)attribute;
}
/// <summary>
/// 设置请求参数
/// </summary>
/// <param name="operLog"></param>
/// <param name="context"></param>
public static void GetRequestValue(SysOperLog operLog, HttpContext context)
{
string reqMethod = operLog.requestMethod;
string param;
if (HttpMethods.IsPost(reqMethod) || HttpMethods.IsPut(reqMethod))
{
context.Request.Body.Seek(0, SeekOrigin.Begin);
using var reader = new StreamReader(context.Request.Body, Encoding.UTF8);
//需要使用异步方式才能获取
param = reader.ReadToEndAsync().Result;
}
else
{
param = context.Request.QueryString.Value.ToString();
}
operLog.operParam = param;
}
}
}
+3 -13
View File
@@ -1,8 +1,6 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Model; using Infrastructure.Model;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.Filters;
@@ -22,9 +20,6 @@ namespace ZR.Admin.WebApi.Filters
public class VerifyAttribute : Attribute, IAuthorizationFilter public class VerifyAttribute : Attribute, IAuthorizationFilter
{ {
static readonly Logger logger = LogManager.GetCurrentClassLogger(); static readonly Logger logger = LogManager.GetCurrentClassLogger();
//IWebHostEnvironment webHostEnvironment = (IWebHostEnvironment)App.ServiceProvider.GetService(typeof(IWebHostEnvironment));
//public VerifyAttribute() { }
/// <summary> /// <summary>
/// 只判断token是否正确,不判断权限 /// 只判断token是否正确,不判断权限
@@ -45,19 +40,14 @@ namespace ZR.Admin.WebApi.Filters
string ip = HttpContextExtension.GetClientUserIp(context.HttpContext); string ip = HttpContextExtension.GetClientUserIp(context.HttpContext);
string url = context.HttpContext.Request.Path; string url = context.HttpContext.Request.Path;
var isAuthed = context.HttpContext.User.Identity.IsAuthenticated; var isAuthed = context.HttpContext.User.Identity.IsAuthenticated;
var userName = context.HttpContext.User.Identity.Name;
//使用jwt token校验2020-11-21 //使用jwt token校验2020-11-21
LoginUser info = JwtUtil.GetLoginUser(context.HttpContext); LoginUser info = JwtUtil.GetLoginUser(context.HttpContext);
if (info != null && info.UserId > 0) if (info == null || !isAuthed)
{ {
logger.Info($"[{info.UserId}-{userName}-{ip}]用户登录校验成功"); string msg = $"请求访问[{url}]失败,无法访问系统资源";
} logger.Info($"{msg}");
else
{
string msg = $"请求访问:{url}授权认证失败,无法访问系统资源";
logger.Info($"用户{userName}{msg}");
context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg)); context.Result = new JsonResult(new ApiResult((int)ResultCode.DENY, msg));
} }
-34
View File
@@ -1,34 +0,0 @@
using IPTools.Core;
using Microsoft.AspNetCore.Http;
using UAParser;
using ZR.Admin.WebApi.Extensions;
using ZR.Model.System;
namespace ZR.Admin.WebApi.Framework
{
public class AsyncFactory
{
/// <summary>
/// 记录用户登陆信息
/// </summary>
/// <param name="context"></param>
/// <param name="status"></param>
/// <param name="message"></param>
/// <returns></returns>
public static SysLogininfor RecordLogInfo(HttpContext context, string status, string message)
{
ClientInfo clientInfo = context.GetClientInfo();
SysLogininfor sysLogininfor = new SysLogininfor();
sysLogininfor.browser = clientInfo.Device.Family;
sysLogininfor.os = clientInfo.OS.ToString();
sysLogininfor.ipaddr = context.GetClientUserIp();
sysLogininfor.msg = message;
sysLogininfor.userName = context.GetName();
sysLogininfor.status = status;
var ip_info = IpTool.Search(sysLogininfor.ipaddr);
sysLogininfor.loginLocation = ip_info.Province + "-" + ip_info.City;
return sysLogininfor;
}
}
}
+3 -2
View File
@@ -71,8 +71,9 @@ namespace ZR.Admin.WebApi.Framework
/// <returns></returns> /// <returns></returns>
public static TokenValidationParameters ValidParameters() public static TokenValidationParameters ValidParameters()
{ {
JwtSettings jwtSettings = new JwtSettings(); JwtSettings jwtSettings = new();
ConfigUtils.Instance.Bind("JwtSettings", jwtSettings); AppSettings.Bind("JwtSettings", jwtSettings);
if (jwtSettings == null || jwtSettings.SecretKey.IsEmpty()) if (jwtSettings == null || jwtSettings.SecretKey.IsEmpty())
{ {
throw new Exception("JwtSettings获取失败"); throw new Exception("JwtSettings获取失败");
+75
View File
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Infrastructure.Constant;
using Infrastructure.Model;
using Microsoft.AspNetCore.SignalR;
using ZR.Model;
using ZR.Service.System.IService;
namespace ZR.Admin.WebApi.Hubs
{
public class MessageHub : Hub
{
//创建用户集合,用于存储所有链接的用户数据
private static readonly List<OnlineUsers> clientUsers = new();
private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private ISysNoticeService SysNoticeService;
public MessageHub(ISysNoticeService noticeService)
{
SysNoticeService = noticeService;
}
private ApiResult SendNotice()
{
var result = SysNoticeService.GetSysNotices();
return new ApiResult(200, "success", result);
}
#region 客户端连接
/// <summary>
/// 客户端连接的时候调用
/// </summary>
/// <returns></returns>
public override Task OnConnectedAsync()
{
var name = Context.User.Identity.Name;
var user = clientUsers.Any(u => u.ConnnectionId == Context.ConnectionId);
//判断用户是否存在,否则添加集合
if (!user && Context.User.Identity.IsAuthenticated)
{
clientUsers.Add(new OnlineUsers(Context.ConnectionId, name));
Console.WriteLine($"{DateTime.Now}:{name},{Context.ConnectionId}连接服务端success,当前已连接{clientUsers.Count}个");
//Clients.All.SendAsync("welcome", $"欢迎您:{name},当前时间:{DateTime.Now}");
Clients.All.SendAsync(HubsConstant.MoreNotice, SendNotice());
}
Clients.All.SendAsync(HubsConstant.OnlineNum, clientUsers.Count);
return base.OnConnectedAsync();
}
/// <summary>
/// 连接终止时调用。
/// </summary>
/// <returns></returns>
public override Task OnDisconnectedAsync(Exception exception)
{
var user = clientUsers.Where(p => p.ConnnectionId == Context.ConnectionId).FirstOrDefault();
//判断用户是否存在,否则添加集合
if (user != null)
{
Console.WriteLine($"用户{user?.Name}离开了,当前已连接{clientUsers.Count}个");
clientUsers.Remove(user);
Clients.All.SendAsync(HubsConstant.OnlineNum, clientUsers.Count);
}
return base.OnDisconnectedAsync(exception);
}
#endregion
}
}
+27
View File
@@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ZR.Model
{
public class OnlineUsers
{
/// <summary>
/// 客户端连接Id
/// </summary>
public string ConnnectionId { get; set; }
/// <summary>
/// 用户id
/// </summary>
public int Userid { get; set; }
public string Name { get; set; }
public DateTime LoginTime { get; set; }
public OnlineUsers(string clientid, string name)
{
ConnnectionId = clientid;
Name = name;
LoginTime = DateTime.Now;
}
}
}
@@ -84,7 +84,7 @@ namespace ZR.Admin.WebApi.Middleware
operLocation = ip_info.Province + " " + ip_info.City, operLocation = ip_info.Province + " " + ip_info.City,
operTime = DateTime.Now operTime = DateTime.Now
}; };
LogActionFilter.GetRequestValue(sysOperLog, context); HttpContextExtension.GetRequestValue(context, sysOperLog);
LogEventInfo ei = new(logLevel, "GlobalExceptionMiddleware", error); LogEventInfo ei = new(logLevel, "GlobalExceptionMiddleware", error);
ei.Exception = ex; ei.Exception = ex;
+8 -4
View File
@@ -23,17 +23,21 @@
<!--archiveAboveSize每个日志文件大小的最大值(单位:字节),主日志文件超过大小超过该值时会将文件内容写入滚动日志并清空主日志文件内容--> <!--archiveAboveSize每个日志文件大小的最大值(单位:字节),主日志文件超过大小超过该值时会将文件内容写入滚动日志并清空主日志文件内容-->
<!--${basedir}表示当前应用程序域所在的根目录--> <!--${basedir}表示当前应用程序域所在的根目录-->
<target name="allfile" xsi:type="File" <target name="allfile" xsi:type="File"
fileName="${basedir}/adminlogs/all.log" fileName="${basedir}/adminlogs/all.txt"
archiveFileName="${basedir}/adminlogs/all.{###}.txt" archiveFileName="${basedir}/adminlogs/all.{###}.txt"
archiveEvery="Day"
archiveNumbering="DateAndSequence"
archiveAboveSize="20000000" archiveAboveSize="20000000"
maxArchiveFiles="30" maxArchiveFiles="30"
keepFileOpen="false" keepFileOpen="true"
layout="${longdate} | ${event-properties:item=EventId_Id} | ${uppercase:${level}} | ${logger} | ${aspnet-request-iP} | ${event-properties:item=user} | ${aspnet-request-url} | ${message} | ${event-properties:item=requestParam} | ${event-properties:item=jsonResult} | ${onexception:${exception:format=tostring}"/> layout="${longdate} | ${event-properties:item=EventId_Id} | ${uppercase:${level}} | ${logger} | ${aspnet-request-iP:CheckForwardedForHeader=true} | ${event-properties:item=user} | ${aspnet-request-url} | ${message} | ${event-properties:item=requestParam} | ${event-properties:item=jsonResult} | ${onexception:${exception:format=tostring}"/>
<!--SQL--> <!--SQL-->
<target name="sqlfile" xsi:type="File" <target name="sqlfile" xsi:type="File"
fileName="${basedir}/adminlogs/all-sql.log" fileName="${basedir}/adminlogs/all-sql.txt"
archiveFileName="${basedir}/adminlogs/all.sql{###}.txt" archiveFileName="${basedir}/adminlogs/all.sql{###}.txt"
archiveEvery="Day"
archiveNumbering="DateAndSequence"
archiveAboveSize="20000000" archiveAboveSize="20000000"
maxArchiveFiles="30" maxArchiveFiles="30"
keepFileOpen="false" keepFileOpen="false"
+27 -10
View File
@@ -15,8 +15,8 @@ using System.Threading.Tasks;
using ZR.Admin.WebApi.Extensions; using ZR.Admin.WebApi.Extensions;
using ZR.Admin.WebApi.Filters; using ZR.Admin.WebApi.Filters;
using ZR.Admin.WebApi.Framework; using ZR.Admin.WebApi.Framework;
using ZR.Admin.WebApi.Hubs;
using ZR.Admin.WebApi.Middleware; using ZR.Admin.WebApi.Middleware;
using ZR.Common.Cache;
namespace ZR.Admin.WebApi namespace ZR.Admin.WebApi
{ {
@@ -30,7 +30,7 @@ namespace ZR.Admin.WebApi
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
string corsUrls = Configuration["sysConfig:cors"]; string corsUrls = Configuration["corsUrls"];
//配置跨域 //配置跨域
services.AddCors(c => services.AddCors(c =>
@@ -43,8 +43,17 @@ namespace ZR.Admin.WebApi
.AllowAnyMethod();//允许任意方法 .AllowAnyMethod();//允许任意方法
}); });
}); });
//注入SignalR实时通讯,默认用json传输
services.AddSignalR(options =>
{
//客户端发保持连接请求到服务端最长间隔,默认30秒,改成4分钟,网页需跟着设置connection.keepAliveIntervalInMilliseconds = 12e4;即2分钟
//options.ClientTimeoutInterval = TimeSpan.FromMinutes(4);
//服务端发保持连接请求到客户端间隔,默认15秒,改成2分钟,网页需跟着设置connection.serverTimeoutInMilliseconds = 24e4;即4分钟
//options.KeepAliveInterval = TimeSpan.FromMinutes(2);
});
//消除Error unprotecting the session cookie警告 //消除Error unprotecting the session cookie警告
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection")); services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + "DataProtection"));
//普通验证码 //普通验证码
services.AddHeiCaptcha(); services.AddHeiCaptcha();
services.AddSession(); services.AddSession();
@@ -53,7 +62,7 @@ namespace ZR.Admin.WebApi
//绑定整个对象到Model上 //绑定整个对象到Model上
services.Configure<OptionsSetting>(Configuration); services.Configure<OptionsSetting>(Configuration);
//Cookie 认证 //jwt 认证
services.AddAuthentication(options => services.AddAuthentication(options =>
{ {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
@@ -68,7 +77,7 @@ namespace ZR.Admin.WebApi
services.AddMvc(options => services.AddMvc(options =>
{ {
options.Filters.Add(typeof(GlobalActionMonitor));//全局注册异常 options.Filters.Add(typeof(GlobalActionMonitor));//全局注册
}) })
.AddJsonOptions(options => .AddJsonOptions(options =>
{ {
@@ -91,11 +100,15 @@ namespace ZR.Admin.WebApi
app.Use((context, next) => app.Use((context, next) =>
{ {
context.Request.EnableBuffering(); context.Request.EnableBuffering();
if (context.Request.Query.TryGetValue("access_token", out var token))
{
context.Request.Headers.Add("Authorization", $"Bearer {token}");
}
return next(); return next();
}); });
//开启访问静态文件/wwwroot目录文件,要放在UseRouting前面 //开启访问静态文件/wwwroot目录文件,要放在UseRouting前面
app.UseStaticFiles(); app.UseStaticFiles();
//开启路由访问
app.UseRouting(); app.UseRouting();
app.UseCors("Policy");//要放在app.UseEndpoints前。 app.UseCors("Policy");//要放在app.UseEndpoints前。
@@ -106,16 +119,20 @@ namespace ZR.Admin.WebApi
app.UseAuthentication(); app.UseAuthentication();
//2.再开启授权 //2.再开启授权
app.UseAuthorization(); app.UseAuthorization();
//开启session
app.UseSession(); app.UseSession();
//开启缓存
app.UseResponseCaching(); app.UseResponseCaching();
//恢复/启动任务
// 恢复/启动任务
app.UseAddTaskSchedulers(); app.UseAddTaskSchedulers();
//使用全局异常中间件
app.UseMiddleware<GlobalExceptionMiddleware>(); app.UseMiddleware<GlobalExceptionMiddleware>();
app.UseEndpoints(endpoints => app.UseEndpoints(endpoints =>
{ {
//设置socket连接
endpoints.MapHub<MessageHub>("/msgHub");
endpoints.MapControllerRoute( endpoints.MapControllerRoute(
name: "default", name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}"); pattern: "{controller=Home}/{action=Index}/{id?}");
@@ -130,7 +147,7 @@ namespace ZR.Admin.WebApi
private void InjectServices(IServiceCollection services, IConfiguration configuration) private void InjectServices(IServiceCollection services, IConfiguration configuration)
{ {
services.AddAppService(); services.AddAppService();
services.AddSingleton(new AppSettings(configuration));
//开启计划任务 //开启计划任务
services.AddTaskSchedulers(); services.AddTaskSchedulers();
//初始化db //初始化db
+8 -8
View File
@@ -22,20 +22,20 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="EPPlus" Version="5.8.3" /> <PackageReference Include="EPPlus" Version="5.8.6" />
<PackageReference Include="Hei.Captcha" Version="0.3.0" /> <PackageReference Include="Hei.Captcha" Version="0.3.0" />
<PackageReference Include="IPTools.China" Version="1.6.0" /> <PackageReference Include="IPTools.China" Version="1.6.0" />
<PackageReference Include="CSRedisCore" Version="3.6.5" /> <PackageReference Include="CSRedisCore" Version="3.6.9" />
<PackageReference Include="Mapster" Version="7.0.1" /> <PackageReference Include="Mapster" Version="7.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" NoWarn="NU1605" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.0" NoWarn="NU1605" />
<PackageReference Include="NETCore.Encrypt" Version="2.0.9" /> <PackageReference Include="NETCore.Encrypt" Version="2.1.0" />
<PackageReference Include="NLog" Version="4.7.5" /> <PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.3" /> <PackageReference Include="NLog.Web.AspNetCore" Version="4.14.0" />
<PackageReference Include="Snowflake.Core" Version="2.0.0" /> <PackageReference Include="Snowflake.Core" Version="2.0.0" />
<PackageReference Include="SqlSugar.IOC" Version="1.7.0" /> <PackageReference Include="SqlSugar.IOC" Version="1.7.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.1.4" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
<PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.2" /> <PackageReference Include="Swashbuckle.AspNetCore.Filters" Version="7.0.2" />
<PackageReference Include="UAParser" Version="3.1.46" /> <PackageReference Include="UAParser" Version="3.1.47" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+1 -5
View File
@@ -13,10 +13,7 @@
"conn_zrAdmin_type": 1, //MySql = 0, SqlServer = 1 "conn_zrAdmin_type": 1, //MySql = 0, SqlServer = 1
"conn_bus_type": 1, "conn_bus_type": 1,
"urls": "http://localhost:8888", //项目启动url "urls": "http://localhost:8888", //项目启动url
"sysConfig": { "corsUrls": "http://localhost:8887", //跨域地址(前端启动项目,前后端分离单独部署需要设置),多个用","隔开
"DBCommandTimeout": 10,
"cors": "http://localhost:8887" //跨域地址(前端启动项目,前后端分离单独部署需要设置),多个用","隔开
},
"JwtSettings": { "JwtSettings": {
"Issuer": "ZRAdmin.NET", "Issuer": "ZRAdmin.NET",
"Audience": "ZRAdmin.NET", "Audience": "ZRAdmin.NET",
@@ -26,7 +23,6 @@
"DemoMode": false, //是否演示模式 "DemoMode": false, //是否演示模式
"DbKey": "", //数据库加密key "DbKey": "", //数据库加密key
"Upload": { "Upload": {
"UploadDirectory": "/",
"UploadUrl": "http://localhost:8888" "UploadUrl": "http://localhost:8888"
}, },
//阿里云存储配置 //阿里云存储配置
@@ -21,7 +21,7 @@ $if(column.HtmlType == "customInput" && column.IsPk == false)
</template> </template>
</el-table-column> </el-table-column>
$elseif(column.HtmlType == "imageUpload") $elseif(column.HtmlType == "imageUpload")
<el-table-column prop="${columnName}" align="center" label="${labelName}"> <el-table-column prop="${columnName}" label="${labelName}" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-image class="table-td-thumb" fit="contain" :src="scope.row.${columnName}" :preview-src-list="[scope.row.${columnName}]"> <el-image class="table-td-thumb" fit="contain" :src="scope.row.${columnName}" :preview-src-list="[scope.row.${columnName}]">
<div slot="error"><i class="el-icon-document" /></div> <div slot="error"><i class="el-icon-document" /></div>
@@ -29,7 +29,7 @@ $elseif(column.HtmlType == "imageUpload")
</template> </template>
</el-table-column> </el-table-column>
$elseif(column.HtmlType == "checkbox" || column.HtmlType == "select" || column.HtmlType == "radio") $elseif(column.HtmlType == "checkbox" || column.HtmlType == "select" || column.HtmlType == "radio")
<el-table-column label="${labelName}" align="center" prop="${columnName}"> <el-table-column prop="${columnName}" label="${labelName}" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
$if(column.HtmlType == "checkbox") $if(column.HtmlType == "checkbox")
<dict-tag :options="${columnName}Options" :value="scope.row.${columnName} ? scope.row.${columnName}.split(',') : []" /> <dict-tag :options="${columnName}Options" :value="scope.row.${columnName} ? scope.row.${columnName}.split(',') : []" />
@@ -95,9 +95,9 @@ $if(replaceDto.ShowBtnAdd)
throw new CustomException("请求参数错误"); throw new CustomException("请求参数错误");
} }
//从 Dto 映射到 实体 //从 Dto 映射到 实体
var model = parm.Adapt<${replaceDto.ModelTypeName}>().ToCreate(HttpContext); var modal = parm.Adapt<${replaceDto.ModelTypeName}>().ToCreate(HttpContext);
var response = _${replaceDto.ModelTypeName}Service.Insert(model, it => new var response = _${replaceDto.ModelTypeName}Service.Insert(modal, it => new
{ {
$foreach(item in genTable.Columns) $foreach(item in genTable.Columns)
$if((item.IsInsert)) $if((item.IsInsert))
@@ -124,14 +124,14 @@ $if(replaceDto.ShowBtnEdit)
throw new CustomException("请求实体不能为空"); throw new CustomException("请求实体不能为空");
} }
//从 Dto 映射到 实体 //从 Dto 映射到 实体
var model = parm.Adapt<${replaceDto.ModelTypeName}>().ToUpdate(HttpContext); var modal = parm.Adapt<${replaceDto.ModelTypeName}>().ToUpdate(HttpContext);
var response = _${replaceDto.ModelTypeName}Service.Update(w => w.${replaceDto.PKName} == model.${replaceDto.PKName}, it => new ${replaceDto.ModelTypeName}() var response = _${replaceDto.ModelTypeName}Service.Update(w => w.${replaceDto.PKName} == modal.${replaceDto.PKName}, it => new ${replaceDto.ModelTypeName}()
{ {
//Update 字段映射 //Update 字段映射
$foreach(item in genTable.Columns) $foreach(item in genTable.Columns)
$if((item.IsEdit)) $if((item.IsEdit))
$item.CsharpField = model.$item.CsharpField, $item.CsharpField = modal.$item.CsharpField,
$end $end
${end} ${end}
}); });
@@ -11,15 +11,21 @@
</el-form> </el-form>
<!-- 工具区域 --> <!-- 工具区域 -->
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
$if(replaceDto.ShowBtnAdd)
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" v-hasPermi="['${replaceDto.PermissionPrefix}:add']" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button> <el-button type="primary" v-hasPermi="['${replaceDto.PermissionPrefix}:add']" plain icon="el-icon-plus" size="mini" @click="handleAdd">新增</el-button>
</el-col> </el-col>
$end
$if(replaceDto.ShowBtnEdit)
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="success" :disabled="single" v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" plain icon="el-icon-edit" size="mini" @click="handleUpdate">修改</el-button> <el-button type="success" :disabled="single" v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" plain icon="el-icon-edit" size="mini" @click="handleUpdate">修改</el-button>
</el-col> </el-col>
$end
$if(replaceDto.ShowBtnDelete)
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="danger" :disabled="multiple" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" plain icon="el-icon-delete" size="mini" @click="handleDelete">删除</el-button> <el-button type="danger" :disabled="multiple" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" plain icon="el-icon-delete" size="mini" @click="handleDelete">删除</el-button>
</el-col> </el-col>
$end
$if(replaceDto.ShowBtnExport) $if(replaceDto.ShowBtnExport)
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['${replaceDto.PermissionPrefix}:export']">导出</el-button> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['${replaceDto.PermissionPrefix}:export']">导出</el-button>
@@ -34,10 +40,14 @@ $end
${VueViewListContent} ${VueViewListContent}
<el-table-column label="操作" align="center" width="140"> <el-table-column label="操作" align="center" width="140">
<template slot-scope="scope"> <template slot-scope="scope">
$if(replaceDto.ShowBtnEdit)
<el-button size="mini" v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" type="success" icon="el-icon-edit" title="编辑" <el-button size="mini" v-hasPermi="['${replaceDto.PermissionPrefix}:edit']" type="success" icon="el-icon-edit" title="编辑"
@click="handleUpdate(scope.row)"></el-button> @click="handleUpdate(scope.row)"></el-button>
$end
$if(replaceDto.ShowBtnDelete)
<el-button size="mini" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" type="danger" icon="el-icon-delete" title="删除" <el-button size="mini" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" type="danger" icon="el-icon-delete" title="删除"
@click="handleDelete(scope.row)"></el-button> @click="handleDelete(scope.row)"></el-button>
$end
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@@ -118,7 +128,7 @@ $end
], ],
$foreach(item in genTable.Columns) $foreach(item in genTable.Columns)
$if((item.HtmlType == "radio" || item.HtmlType == "select" || item.HtmlType == "checkbox")) $if((item.HtmlType == "radio" || item.HtmlType == "select" || item.HtmlType == "checkbox"))
// ${item.ColumnComment}选项列表 // ${item.ColumnComment}选项列表 格式 eg:{ dictLabel: '标签', dictValue: '0'}
${item.CsharpFieldFl}Options: [], ${item.CsharpFieldFl}Options: [],
$elseif(item.HtmlType == "datetime" && item.IsQuery == true) $elseif(item.HtmlType == "datetime" && item.IsQuery == true)
//${item.ColumnComment}时间范围 //${item.ColumnComment}时间范围
@@ -11,9 +11,6 @@
</el-form> </el-form>
<!-- 工具区域 --> <!-- 工具区域 -->
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="danger" :disabled="multiple" v-hasPermi="['${replaceDto.PermissionPrefix}:delete']" plain icon="el-icon-delete" size="mini" @click="handleDelete">删除</el-button>
</el-col>
$if(replaceDto.ShowBtnExport) $if(replaceDto.ShowBtnExport)
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['${replaceDto.PermissionPrefix}:export']">导出</el-button> <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport" v-hasPermi="['${replaceDto.PermissionPrefix}:export']">导出</el-button>
+3 -3
View File
@@ -277,8 +277,8 @@ namespace ZR.CodeGenerator
/// <returns></returns> /// <returns></returns>
public static string GetClassName(string tableName) public static string GetClassName(string tableName)
{ {
bool autoRemovePre = ConfigUtils.Instance.GetAppConfig(GenConstants.Gen_autoPre, false); bool autoRemovePre = AppSettings.GetAppConfig(GenConstants.Gen_autoPre, false);
string tablePrefix = ConfigUtils.Instance.GetAppConfig<string>(GenConstants.Gen_tablePrefix); string tablePrefix = AppSettings.GetAppConfig<string>(GenConstants.Gen_tablePrefix);
if (!string.IsNullOrEmpty(tablePrefix) && autoRemovePre) if (!string.IsNullOrEmpty(tablePrefix) && autoRemovePre)
{ {
@@ -364,7 +364,7 @@ namespace ZR.CodeGenerator
ModuleName = "business",//导入默认模块名 ModuleName = "business",//导入默认模块名
ClassName = GetClassName(tableName).FirstUpperCase(), ClassName = GetClassName(tableName).FirstUpperCase(),
BusinessName = tableName.UnderScoreToCamelCase().FirstUpperCase(), BusinessName = tableName.UnderScoreToCamelCase().FirstUpperCase(),
FunctionAuthor = ConfigUtils.Instance.GetConfig(GenConstants.Gen_author), FunctionAuthor = AppSettings.GetConfig(GenConstants.Gen_author),
TableName = tableName, TableName = tableName,
TableComment = desc, TableComment = desc,
FunctionName = desc, FunctionName = desc,
+2 -2
View File
@@ -23,8 +23,8 @@ namespace ZR.CodeGenerator
/// <returns></returns> /// <returns></returns>
public SqlSugarClient GetSugarDbContext(string dbName = "") public SqlSugarClient GetSugarDbContext(string dbName = "")
{ {
string connStr = ConfigUtils.Instance.GetConfig(GenConstants.Gen_conn); string connStr = AppSettings.GetConfig(GenConstants.Gen_conn);
int dbType = ConfigUtils.Instance.GetAppConfig(GenConstants.Gen_conn_dbType, 0); int dbType = AppSettings.GetAppConfig(GenConstants.Gen_conn_dbType, 0);
if (!string.IsNullOrEmpty(dbName)) if (!string.IsNullOrEmpty(dbName))
{ {
+1 -1
View File
@@ -11,7 +11,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JinianNet.JNTemplate" Version="2.2.4" /> <PackageReference Include="JinianNet.JNTemplate" Version="2.2.5" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" /> <PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+5 -5
View File
@@ -8,10 +8,10 @@ namespace ZR.Common
{ {
public class AliyunOssHelper public class AliyunOssHelper
{ {
static string accessKeyId = ConfigUtils.Instance.GetConfig("ALIYUN_OSS:KEY"); static string accessKeyId = AppSettings.GetConfig("ALIYUN_OSS:KEY");
static string accessKeySecret = ConfigUtils.Instance.GetConfig("ALIYUN_OSS:SECRET"); static string accessKeySecret = AppSettings.GetConfig("ALIYUN_OSS:SECRET");
static string endpoint = ConfigUtils.Instance.GetConfig("ALIYUN_OSS:REGIONID"); static string endpoint = AppSettings.GetConfig("ALIYUN_OSS:REGIONID");
static string bucketName1 = ConfigUtils.Instance.GetConfig("ALIYUN_OSS:bucketName"); static string bucketName1 = AppSettings.GetConfig("ALIYUN_OSS:bucketName");
/// <summary> /// <summary>
/// 上传到阿里云 /// 上传到阿里云
@@ -21,7 +21,7 @@ namespace ZR.Common
/// <param name="bucketName">存储桶 如果为空默认取配置文件</param> /// <param name="bucketName">存储桶 如果为空默认取配置文件</param>
public static System.Net.HttpStatusCode PutObjectFromFile(Stream filestreams, string dirPath, string bucketName = "") public static System.Net.HttpStatusCode PutObjectFromFile(Stream filestreams, string dirPath, string bucketName = "")
{ {
OssClient client = new OssClient(endpoint, accessKeyId, accessKeySecret); OssClient client = new(endpoint, accessKeyId, accessKeySecret);
if (string.IsNullOrEmpty(bucketName)) { bucketName = bucketName1; } if (string.IsNullOrEmpty(bucketName)) { bucketName = bucketName1; }
try try
{ {
+2 -2
View File
@@ -10,8 +10,8 @@ namespace ZR.Common.Cache
public static void Initalize() public static void Initalize()
{ {
Cache = new CSRedisClient(ConfigUtils.Instance.GetConfig("RedisServer:Cache")); Cache = new CSRedisClient(AppSettings.GetConfig("RedisServer:Cache"));
Session = new CSRedisClient(ConfigUtils.Instance.GetConfig("RedisServer:Session")); Session = new CSRedisClient(AppSettings.GetConfig("RedisServer:Session"));
} }
} }
} }
+1 -1
View File
@@ -35,7 +35,7 @@ namespace ZR.Common
public MailHelper() public MailHelper()
{ {
ConfigUtils.Instance.Bind("MailOptions", mailOptions); AppSettings.Bind("MailOptions", mailOptions);
FromEmail = mailOptions.From; FromEmail = mailOptions.From;
Smtp = mailOptions.Smtp; Smtp = mailOptions.Smtp;
FromPwd = mailOptions.Password; FromPwd = mailOptions.Password;
+3 -3
View File
@@ -6,9 +6,9 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" /> <PackageReference Include="Aliyun.OSS.SDK.NetCore" Version="2.13.0" />
<PackageReference Include="CSRedisCore" Version="3.6.5" /> <PackageReference Include="CSRedisCore" Version="3.6.9" />
<PackageReference Include="EPPlus" Version="5.8.3" /> <PackageReference Include="EPPlus" Version="5.8.6" />
<PackageReference Include="MailKit" Version="3.0.0" /> <PackageReference Include="MailKit" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="5.0.0" />
</ItemGroup> </ItemGroup>
+2 -2
View File
@@ -9,7 +9,7 @@ namespace ZR.Model.System.Dto
/// </summary> /// </summary>
public class SysFileDto public class SysFileDto
{ {
public int Id { get; set; } public long Id { get; set; }
public string FileName { get; set; } public string FileName { get; set; }
public string FileUrl { get; set; } public string FileUrl { get; set; }
public string StorePath { get; set; } public string StorePath { get; set; }
@@ -25,6 +25,6 @@ namespace ZR.Model.System.Dto
public DateTime? BeginCreate_time { get; set; } public DateTime? BeginCreate_time { get; set; }
public DateTime? EndCreate_time { get; set; } public DateTime? EndCreate_time { get; set; }
public int? StoreType { get; set; } public int? StoreType { get; set; }
public int? FileId { get; set; } public long? FileId { get; set; }
} }
} }
+1
View File
@@ -28,5 +28,6 @@ namespace ZR.Model.Dto
public string NoticeTitle { get; set; } public string NoticeTitle { get; set; }
public string NoticeType { get; set; } public string NoticeType { get; set; }
public string CreateBy { get; set; } public string CreateBy { get; set; }
public string Status { get; set; }
} }
} }
+1
View File
@@ -11,6 +11,7 @@ namespace ZR.Model.System.Dto
/// 页码 /// 页码
/// </summary> /// </summary>
public int pageNum { get; set; } public int pageNum { get; set; }
public int PageSize { get; set; }
/// <summary> /// <summary>
/// 操作人员 /// 操作人员
/// </summary> /// </summary>
+4 -2
View File
@@ -1,4 +1,5 @@
using SqlSugar; using Newtonsoft.Json;
using SqlSugar;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
@@ -13,7 +14,8 @@ namespace ZR.Model.System
/// 描述 : 自增id /// 描述 : 自增id
/// 空值 : false /// 空值 : false
/// </summary> /// </summary>
[SugarColumn(IsPrimaryKey = true, IsIdentity = true)] [JsonConverter(typeof(ValueToStringConverter))]
[SugarColumn(IsPrimaryKey = true)]
public long Id { get; set; } public long Id { get; set; }
/// <summary> /// <summary>
/// 文件真实名 /// 文件真实名
+8 -8
View File
@@ -69,16 +69,16 @@ namespace ZR.Model.System
//@Excel(name = "状态", readConverterExp = "0=正常,1=异常") //@Excel(name = "状态", readConverterExp = "0=正常,1=异常")
public int status { get; set; } public int status { get; set; }
/** 错误消息 */ /// <summary>
//@Excel(name = "错误消息") /// 错误消息
/// </summary>
[EpplusTableColumn(Header = "错误消息")]
public string errorMsg { get; set; } public string errorMsg { get; set; }
/** 操作时间 */ /// <summary>
//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") /// 操作时间
//@Excel(name = "操作时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss") /// </summary>
//[DataType] [EpplusTableColumn(Header = "操作时间", NumberFormat = "yyyy-MM-dd HH:mm:ss")]
[JsonConverter(typeof(JsonDateConverter))]
[EpplusTableColumn(NumberFormat = "yyyy-MM-dd HH:mm:ss")]
public DateTime? operTime { get; set; } public DateTime? operTime { get; set; }
/// <summary> /// <summary>
/// 操作用时 /// 操作用时
+34 -6
View File
@@ -21,9 +21,7 @@ namespace ZR.Model.System
public long UserId { get; set; } public long UserId { get; set; }
//[Duplication]//校验模板类该列数据是否重复 //[Duplication]//校验模板类该列数据是否重复
public string UserName { get; set; } public string UserName { get; set; }
public string NickName { get; set; } public string NickName { get; set; }
/// <summary> /// <summary>
/// '用户类型(00系统用户)', /// '用户类型(00系统用户)',
/// </summary> /// </summary>
@@ -32,16 +30,15 @@ namespace ZR.Model.System
[SugarColumn(IsOnlyIgnoreInsert = true)] [SugarColumn(IsOnlyIgnoreInsert = true)]
[EpplusIgnore] [EpplusIgnore]
public string Avatar { get; set; } public string Avatar { get; set; }
public string Email { get; set; } public string Email { get; set; }
[JsonIgnore] [JsonIgnore]
[EpplusIgnore] [EpplusIgnore]
public string Password { get; set; } public string Password { get; set; }
/// <summary>
//[ColName("手机号")] /// 手机号
/// </summary>
public string Phonenumber { get; set; } public string Phonenumber { get; set; }
/// <summary> /// <summary>
/// 用户性别(0男 1女 2未知) /// 用户性别(0男 1女 2未知)
/// </summary> /// </summary>
@@ -110,6 +107,37 @@ namespace ZR.Model.System
[SugarColumn(IsIgnore = true)] [SugarColumn(IsIgnore = true)]
[EpplusIgnore] [EpplusIgnore]
public List<SysRole> Roles { get; set; } public List<SysRole> Roles { get; set; }
[SugarColumn(IsIgnore = true)]
public string WelcomeMessage
{
get
{
int now = DateTime.Now.Hour;
if (now > 0 && now <= 6)
{
return "午夜好";
}
else if (now > 6 && now <= 11)
{
return "早上好";
}
else if (now > 11 && now <= 14)
{
return "中午好";
}
else if (now > 14 && now <= 18)
{
return "下午好";
}
else
{
return "晚上好";
}
}
}
[SugarColumn(IsIgnore = true)]
public string WelcomeContent { get; set; }
#endregion #endregion
} }
+2 -2
View File
@@ -5,8 +5,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="EPPlus" Version="5.8.3" /> <PackageReference Include="EPPlus" Version="5.8.6" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" /> <PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" /> <PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
</ItemGroup> </ItemGroup>
+7 -6
View File
@@ -107,12 +107,13 @@ namespace ZR.Repository.System
public List<SysMenu> SelectMenuTreeByRoleIds(List<long> roleIds) public List<SysMenu> SelectMenuTreeByRoleIds(List<long> roleIds)
{ {
var menuTypes = new string[] { "M", "C" }; var menuTypes = new string[] { "M", "C" };
return Context.Queryable<SysMenu, SysRoleMenu>((menu, roleMenu) => new JoinQueryInfos( return Context.Queryable<SysMenu>()
JoinType.Left, menu.menuId == roleMenu.Menu_id .Where((menu) =>
)) menuTypes.Contains(menu.menuType)
.Where((menu, roleMenu) => roleIds.Contains(roleMenu.Role_id) && menuTypes.Contains(menu.menuType) && menu.status == "0") && menu.status == "0"
.OrderBy((menu, roleMenu) => new { menu.parentId, menu.orderNum }) && SqlFunc.Subqueryable<SysRoleMenu>().Where( s => roleIds.Contains(s.Role_id) && s.Menu_id == menu.menuId).Any())
.Select((menu, roleMenu) => menu).ToList(); .OrderBy((menu) => new { menu.parentId, menu.orderNum })
.Select((menu) => menu).ToList();
} }
#endregion #endregion
+15 -16
View File
@@ -111,7 +111,7 @@ namespace ZR.Repository.System
} }
/// <summary> /// <summary>
/// 删除用户 /// 删除用户(软删除)
/// </summary> /// </summary>
/// <param name="userid">用户id</param> /// <param name="userid">用户id</param>
/// <returns></returns> /// <returns></returns>
@@ -125,26 +125,25 @@ namespace ZR.Repository.System
/// <summary> /// <summary>
/// 修改用户信息 /// 修改用户信息
/// </summary> /// </summary>
/// <param name="sysUser"></param> /// <param name="user"></param>
/// <returns></returns> /// <returns></returns>
public int UpdateUser(SysUser user) public int UpdateUser(SysUser user)
{ {
return Context.Updateable(user) return Context.Updateable(user)
//.SetColumns(t => new SysUser() .UpdateColumns(t => new
//{ {
// UserName = user.UserName, t.NickName,
// Status = user.Status, t.Email,
// NickName = user.NickName, t.Phonenumber,
// Remark = user.Remark, t.DeptId,
// Email = user.Email, t.Status,
// Update_by = user.Update_by, t.Sex,
// Phonenumber = user.Phonenumber, t.PostIds,
// Update_time = DateTime.Now, t.Remark,
// Sex = user.Sex, t.Update_by,
// DeptId = user.DeptId t.Update_time
//}) })
.IgnoreColumns(ignoreAllNullColumns: true)//忽略所有为null .IgnoreColumns(ignoreAllNullColumns: true)//忽略所有为null
.IgnoreColumns(it => new { it.Password, it.Avatar })
.Where(f => f.UserId == user.UserId).ExecuteCommand(); .Where(f => f.UserId == user.UserId).ExecuteCommand();
} }
+1 -1
View File
@@ -12,7 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" /> <PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
<PackageReference Include="MySql.Data" Version="8.0.25" /> <PackageReference Include="MySql.Data" Version="8.0.25" />
<PackageReference Include="NETCore.Encrypt" Version="2.0.9" /> <PackageReference Include="NETCore.Encrypt" Version="2.1.0" />
<PackageReference Include="SqlSugar.IOC" Version="1.7.0" /> <PackageReference Include="SqlSugar.IOC" Version="1.7.0" />
<PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" /> <PackageReference Include="SqlSugarCoreNoDrive" Version="5.0.5.4" />
</ItemGroup> </ItemGroup>
@@ -16,7 +16,7 @@ namespace ZR.Service.System.IService
/// <param name="formFile"></param> /// <param name="formFile"></param>
/// <returns>结果、地址、文件名</returns> /// <returns>结果、地址、文件名</returns>
(bool, string, string) SaveFile(string picdir, IFormFile formFile); (bool, string, string) SaveFile(string picdir, IFormFile formFile);
(bool, string, string) SaveFile(string picdir, IFormFile formFile, string customFileName); (bool, string, string) SaveFile(string picdir, IFormFile formFile, string customFileName, string bucketName);
/// <summary> /// <summary>
/// 按时间来创建文件夹 /// 按时间来创建文件夹
/// </summary> /// </summary>
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using ZR.Model.Models; using ZR.Model.Models;
namespace ZR.Service.System.IService namespace ZR.Service.System.IService
@@ -11,5 +12,6 @@ namespace ZR.Service.System.IService
/// </summary> /// </summary>
public interface ISysNoticeService: IBaseService<SysNotice> public interface ISysNoticeService: IBaseService<SysNotice>
{ {
List<SysNotice> GetSysNotices();
} }
} }
+1 -1
View File
@@ -63,7 +63,7 @@ namespace ZR.Service.System
foreach (var dictId in dictIds) foreach (var dictId in dictIds)
{ {
SysDictType dictType = DictRepository.GetFirst(x => x.DictId == dictId); SysDictType dictType = DictRepository.GetFirst(x => x.DictId == dictId);
if (DictRepository.Count(f => f.DictType == dictType.DictType) > 0) if (DictDataRepository.Count(f => f.DictType == dictType.DictType) > 0)
{ {
throw new CustomException($"{dictType.DictName}已分配,不能删除"); throw new CustomException($"{dictType.DictName}已分配,不能删除");
} }
+20 -9
View File
@@ -11,6 +11,7 @@ using System.Net;
using ZR.Model.System; using ZR.Model.System;
using ZR.Repository.System; using ZR.Repository.System;
using Infrastructure.Extensions; using Infrastructure.Extensions;
using SqlSugar.DistributedSystem.Snowflake;
namespace ZR.Service.System namespace ZR.Service.System
{ {
@@ -20,7 +21,7 @@ namespace ZR.Service.System
[AppService(ServiceType = typeof(ISysFileService), ServiceLifetime = LifeTime.Transient)] [AppService(ServiceType = typeof(ISysFileService), ServiceLifetime = LifeTime.Transient)]
public class SysFileService : BaseService<SysFile>, ISysFileService public class SysFileService : BaseService<SysFile>, ISysFileService
{ {
private string domainUrl = ConfigUtils.Instance.GetConfig("ALIYUN_OSS:domainUrl"); private string domainUrl = AppSettings.GetConfig("ALIYUN_OSS:domainUrl");
private readonly SysFileRepository SysFileRepository; private readonly SysFileRepository SysFileRepository;
public SysFileService(SysFileRepository repository) : base(repository) public SysFileService(SysFileRepository repository) : base(repository)
@@ -36,18 +37,28 @@ namespace ZR.Service.System
/// <returns></returns> /// <returns></returns>
public (bool, string, string) SaveFile(string picdir, IFormFile formFile) public (bool, string, string) SaveFile(string picdir, IFormFile formFile)
{ {
return SaveFile(picdir, formFile, ""); return SaveFile(picdir, formFile, "", "");
} }
public (bool, string, string) SaveFile(string picdir, IFormFile formFile, string customFileName)
/// <summary>
/// 存储文件
/// </summary>
/// <param name="picdir">文件夹</param>
/// <param name="formFile"></param>
/// <param name="customFileName">自定义文件名</param>
/// <param name="bucketName">存储桶</param>
/// <returns></returns>
public (bool, string, string) SaveFile(string picdir, IFormFile formFile, string customFileName, string bucketName)
{ {
// eg: uploads/2020/08/18 // eg: uploads/2020/08/18
string dir = GetdirPath(picdir.ToString()); //string dir = GetdirPath(picdir.ToString());
string tempName = customFileName.IsEmpty() ? HashFileName() : customFileName; string tempName = customFileName.IsEmpty() ? HashFileName() : customFileName;
string fileExt = Path.GetExtension(formFile.FileName); string fileExt = Path.GetExtension(formFile.FileName);
string fileName = $"{tempName}{fileExt}"; string fileName = tempName + fileExt;
string webUrl = $"{domainUrl}/{dir}/{fileName}"; string webUrl = string.Concat(domainUrl, "/", picdir, "/", fileName);
HttpStatusCode statusCode = AliyunOssHelper.PutObjectFromFile(formFile.OpenReadStream(), Path.Combine(dir, fileName)); HttpStatusCode statusCode = AliyunOssHelper.PutObjectFromFile(formFile.OpenReadStream(), Path.Combine(picdir, fileName), bucketName);
return (statusCode == HttpStatusCode.OK, webUrl, fileName); return (statusCode == HttpStatusCode.OK, webUrl, fileName);
} }
@@ -81,13 +92,13 @@ namespace ZR.Service.System
{ {
try try
{ {
return InsertReturnBigIdentity(file); return Insertable(file).ExecuteReturnSnowflakeId();//单条插入返回雪花ID;
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine("存储图片失败" + ex.Message); Console.WriteLine("存储图片失败" + ex.Message);
throw new Exception(ex.Message);
} }
return 1;
} }
} }
} }
+16
View File
@@ -1,5 +1,7 @@
using Infrastructure; using Infrastructure;
using Infrastructure.Attribute; using Infrastructure.Attribute;
using SqlSugar;
using System.Collections.Generic;
using ZR.Model.Models; using ZR.Model.Models;
using ZR.Repository; using ZR.Repository;
using ZR.Repository.System; using ZR.Repository.System;
@@ -24,6 +26,20 @@ namespace ZR.Service.System
#region 业务逻辑代码 #region 业务逻辑代码
/// <summary>
/// 查询系统通知
/// </summary>
/// <returns></returns>
public List<SysNotice> GetSysNotices()
{
//开始拼装查询条件
var predicate = Expressionable.Create<SysNotice>();
//搜索条件查询语法参考Sqlsugar
predicate = predicate.And(m => m.Status == "0");
return _SysNoticerepository.GetList(predicate.ToExpression());
}
#endregion #endregion
} }
} }
+5
View File
@@ -43,6 +43,11 @@ namespace ZR.Service.System
operLog.BeginTime = DateTimeHelper.GetBeginTime(operLog.BeginTime, -1); operLog.BeginTime = DateTimeHelper.GetBeginTime(operLog.BeginTime, -1);
operLog.EndTime = DateTimeHelper.GetBeginTime(operLog.EndTime, 1); operLog.EndTime = DateTimeHelper.GetBeginTime(operLog.EndTime, 1);
bool isDemoMode = AppSettings.GetAppConfig("DemoMode", false);
if (isDemoMode)
{
return new PagedInfo<SysOperLog>();
}
var list = sysOperLogRepository.GetSysOperLog(operLog, pager); var list = sysOperLogRepository.GetSysOperLog(operLog, pager);
return list; return list;
+5 -3
View File
@@ -2,13 +2,13 @@
using Quartz; using Quartz;
using Quartz.Spi; using Quartz.Spi;
using System; using System;
using System.Collections.Generic;
using System.Text;
namespace ZR.Tasks namespace ZR.Tasks
{ {
public class JobFactory : IJobFactory public class JobFactory : IJobFactory
{ {
private NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
/// <summary> /// <summary>
/// 注入反射获取依赖对象 /// 注入反射获取依赖对象
/// </summary> /// </summary>
@@ -32,8 +32,10 @@ namespace ZR.Tasks
return job; return job;
} }
catch (Exception) catch (Exception ex)
{ {
Console.WriteLine(ex.Message);
logger.Error(ex, ex.Message);
throw; throw;
} }
} }
+3 -3
View File
@@ -5,9 +5,9 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NLog" Version="4.7.5" /> <PackageReference Include="NLog" Version="4.7.14" />
<PackageReference Include="Quartz" Version="3.3.2" /> <PackageReference Include="Quartz" Version="3.3.3" />
<PackageReference Include="Quartz.Serialization.Json" Version="3.3.2" /> <PackageReference Include="Quartz.Serialization.Json" Version="3.3.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+3
View File
@@ -7,6 +7,9 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
# 开发环境 # 开发环境
VUE_APP_BASE_API = '/dev-api' VUE_APP_BASE_API = '/dev-api'
#socket API
VUE_APP_SOCKET_API = '/msgHub'
# 路由前缀 # 路由前缀
VUE_APP_ROUTER_PREFIX = '/' VUE_APP_ROUTER_PREFIX = '/'
+3
View File
@@ -7,6 +7,9 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
# 生产环境 # 生产环境
VUE_APP_BASE_API = '/prod-api' VUE_APP_BASE_API = '/prod-api'
#socket API
VUE_APP_SOCKET_API = '/msgHub'
# 路由前缀 # 路由前缀
VUE_APP_ROUTER_PREFIX = '/' VUE_APP_ROUTER_PREFIX = '/'
+3
View File
@@ -7,6 +7,9 @@ VUE_APP_TITLE = 'ZrAdmin.NET后台管理'
# 测试环境 # 测试环境
VUE_APP_BASE_API = '/stage-api' VUE_APP_BASE_API = '/stage-api'
#socket API
VUE_APP_SOCKET_API = '/msgHub'
# 路由前缀 # 路由前缀
VUE_APP_ROUTER_PREFIX = '/' VUE_APP_ROUTER_PREFIX = '/'
+2
View File
@@ -19,6 +19,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@microsoft/signalr": "^6.0.2",
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "^0.21.4", "axios": "^0.21.4",
"clipboard": "2.0.8", "clipboard": "2.0.8",
@@ -45,6 +46,7 @@
"vue-count-to": "1.0.13", "vue-count-to": "1.0.13",
"vue-cropper": "0.4.9", "vue-cropper": "0.4.9",
"vue-router": "3.4.9", "vue-router": "3.4.9",
"vue-seamless-scroll": "^1.1.23",
"vuedraggable": "2.20.0", "vuedraggable": "2.20.0",
"vuex": "3.6.0" "vuex": "3.6.0"
}, },
+16
View File
@@ -5,7 +5,23 @@
</template> </template>
<script> <script>
import { mapGetters } from "vuex";
export default { export default {
name: "App", name: "App",
computed: {
...mapGetters(["token"]),
},
watch: {
token: {
handler: function (val) {
if (val) {
this.signalr.start();
}
},
deep: true,
immediate: true,
},
},
}; };
</script> </script>
+8
View File
@@ -8,6 +8,14 @@ export function listArticle(query) {
params: query params: query
}) })
} }
// 查询最新列表
export function listNewArticle(query) {
return request({
url: '/Article/newList',
method: 'get',
params: query
})
}
// 查询详细 // 查询详细
export function getArticle(Id) { export function getArticle(Id) {
+17
View File
@@ -1,5 +1,14 @@
import request from '@/utils/request' import request from '@/utils/request'
// 导航栏查询公告列表
export function queryNotice(query) {
return request({
url: '/system/notice/queryNotice',
method: 'get',
params: query
})
}
// 查询公告列表 // 查询公告列表
export function listNotice(query) { export function listNotice(query) {
return request({ return request({
@@ -42,3 +51,11 @@ export function delNotice(noticeId) {
method: 'delete' method: 'delete'
}) })
} }
// 发送通知公告
export function sendNotice(noticeId) {
return request({
url: '/system/notice/send/' + noticeId,
method: 'PUT'
})
}
-107
View File
@@ -1,107 +0,0 @@
.head-container {
padding-bottom: 10px;
.filter-item {
display: inline-block;
vertical-align: middle;
margin: 0 3px 10px 0;
input {
height: 30.5px;
line-height: 30.5px;
}
}
.el-button+.el-button {
margin-left: 0 !important;
}
.el-select__caret.el-input__icon.el-icon-arrow-up{
line-height: 30.5px;
}
.date-item {
display: inline-block;
vertical-align: middle;
margin-bottom: 10px;
height: 30.5px !important;
width: 230px !important;
}
}
.el-avatar {
display: inline-block;
text-align: center;
background: #ccc;
color: #fff;
white-space: nowrap;
position: relative;
overflow: hidden;
vertical-align: middle;
width: 32px;
height: 32px;
line-height: 32px;
border-radius: 16px;
}
.logo-con{
height: 60px;
padding: 13px 0 0;
img{
height: 32px;
width: 135px;
display: block;
//margin: 0 auto;
}
}
#el-login-footer {
height: 40px;
line-height: 40px;
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
color: #fff;
font-family: Arial, serif;
font-size: 12px;
letter-spacing: 1px;
}
#el-main-footer {
background: none repeat scroll 0 0 white;
border-top: 1px solid #e7eaec;
overflow: hidden;
padding: 10px 6px 0 6px;
height: 33px;
font-size: 0.7rem !important;
color: #7a8b9a;
letter-spacing: 0.8px;
font-family: Arial, sans-serif !important;
position: fixed;
bottom: 0;
z-index: 99;
width: 100%;
}
.eladmin-upload {
border: 1px dashed #c0ccda;
border-radius: 5px;
height: 45px;
line-height: 45px;
width: 368px;
}
.my-blockquote{
margin: 0 0 10px;
padding: 15px;
line-height: 22px;
border-left: 5px solid #00437B;
border-radius: 0 2px 2px 0;
background-color: #f2f2f2;
}
.my-code{
position: relative;
padding: 15px;
line-height: 20px;
border-left: 5px solid #ddd;
color: #333;
font-family: Courier New, serif;
font-size: 12px
}
.el-tabs{
margin-bottom: 25px;
}
+68
View File
@@ -82,3 +82,71 @@
.el-range-separator { .el-range-separator {
box-sizing: content-box; box-sizing: content-box;
} }
/* 解决element-ui的table表格控件表头与内容列不对齐问题 */
.el-table th.gutter {
display: table-cell !important;
}
.el-checkbox.mini .el-checkbox__label {
font-size: 12px !important;
}
.el-checkbox.small .el-checkbox__label {
font-size: 12px !important;
}
.el-checkbox.medium .el-checkbox__label {
font-size: 14px !important;
}
.el-table .fixed-width .el-button--mini {
color: #409EFF;
padding-left: 0;
padding-right: 0;
width: inherit;
}
.el-tree-node__content>.el-checkbox {
margin-right: 8px;
}
// element ui 移动端组件适配
@media screen and (max-width: 500px) {
.el-message {
min-width: 300px !important;
}
}
@media screen and (max-width: 500px) {
.el-message-box {
width: 300px !important;
}
.el-pagination__jump{
display: none !important;
}
.el-pagination__sizes{
display: none !important;
}
}
// dialog
@media screen and (max-width: 500px) {
.el-dialog__wrapper .el-dialog {
width: 95% !important;
}
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #409EFF;
margin-left: 5px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
//适配完毕
+1 -67
View File
@@ -4,7 +4,6 @@
@import 'element-ui'; @import 'element-ui';
@import 'sidebar'; @import 'sidebar';
@import 'btn'; @import 'btn';
@import 'eladmin';
body { body {
height: 100%; height: 100%;
@@ -342,24 +341,6 @@ aside {
height: 120px; height: 120px;
} }
/* 解决element-ui的table表格控件表头与内容列不对齐问题 */
.el-table th.gutter {
display: table-cell !important;
}
.el-checkbox.mini .el-checkbox__label {
font-size: 12px !important;
}
.el-checkbox.small .el-checkbox__label {
font-size: 12px !important;
}
.el-checkbox.medium .el-checkbox__label {
font-size: 14px !important;
}
.vue-treeselect.mini { .vue-treeselect.mini {
font-size: 12px !important; font-size: 12px !important;
} }
@@ -397,17 +378,6 @@ aside {
} }
.el-table .fixed-width .el-button--mini {
color: #409EFF;
padding-left: 0;
padding-right: 0;
width: inherit;
}
.el-tree-node__content>.el-checkbox {
margin-right: 8px;
}
.list-group-striped>.list-group-item { .list-group-striped>.list-group-item {
border-left: 0; border-left: 0;
border-right: 0; border-right: 0;
@@ -475,6 +445,7 @@ aside {
height: 120px; height: 120px;
} }
// 导航栏头像
.avatar-upload-preview { .avatar-upload-preview {
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -505,40 +476,3 @@ aside {
.table-td-thumb { .table-td-thumb {
width: 56px; width: 56px;
} }
// 移动端组件适配
@media screen and (max-width: 500px) {
.el-message {
min-width: 300px !important;
}
}
@media screen and (max-width: 500px) {
.el-message-box {
width: 300px !important;
}
.el-pagination__jump{
display: none !important;
}
.el-pagination__sizes{
display: none !important;
}
}
// dialog
@media screen and (max-width: 500px) {
.el-dialog__wrapper .el-dialog {
width: 95% !important;
}
}
/** 表格更多操作下拉样式 */
.el-table .el-dropdown-link {
cursor: pointer;
color: #409EFF;
margin-left: 5px;
}
.el-table .el-dropdown, .el-icon-arrow-down {
font-size: 12px;
}
+88 -67
View File
@@ -1,9 +1,12 @@
<template> <template>
<div class="upload-file"> <div class="upload-file">
<el-upload :action="uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList" :limit="limit" :on-error="handleUploadError" <el-upload :action="uploadFileUrl" :before-upload="handleBeforeUpload" :file-list="fileList" :limit="limit" :on-error="handleUploadError"
:on-exceed="handleExceed" :on-success="handleUploadSuccess" :on-progress="uploadProcess" :show-file-list="false" :data="data" :headers="headers" ref="upload"> :on-exceed="handleExceed" :on-success="handleUploadSuccess" :on-progress="uploadProcess" :show-file-list="true" :data="data" :headers="headers"
:drag="drag" ref="upload">
<i class="el-icon-upload" v-if="drag"></i>
<div class="el-upload__text" v-if="drag">将文件拖到此处,或<em>点击上传</em></div>
<!-- 上传按钮 --> <!-- 上传按钮 -->
<el-button size="mini" type="primary" icon="el-icon-upload">选取文件</el-button> <el-button size="mini" icon="el-icon-upload" v-if="!drag">选取文件</el-button>
<!-- 上传提示 --> <!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip"> <div class="el-upload__tip" slot="tip" v-if="showTip">
请上传 请上传
@@ -28,141 +31,155 @@
</template> </template>
<script> <script>
import { getToken } from "@/utils/auth"; import { getToken } from '@/utils/auth'
export default { export default {
name: "FileUpload", name: 'FileUpload',
props: { props: {
// 值 // 值
value: [String, Object, Array], value: [String, Object, Array],
// 数量限制 // 数量限制
limit: { limit: {
type: Number, type: Number,
default: 1, default: 1
}, },
// 大小限制(MB) // 大小限制(MB)
fileSize: { fileSize: {
type: Number, type: Number,
default: 5, default: 5
}, },
// 文件类型, 例如['png', 'jpg', 'jpeg'] // 文件类型, 例如['png', 'jpg', 'jpeg']
fileType: { fileType: {
type: Array, type: Array,
default: () => ["doc", "xls", "ppt", "txt", "pdf", "svga", "json"], default: () => ['doc', 'xls', 'ppt', 'txt', 'pdf', 'svga', 'json']
}, },
// 是否显示提示 // 是否显示提示
isShowTip: { isShowTip: {
type: Boolean, type: Boolean,
default: true, default: true
}, },
// 上传地址 // 上传地址
uploadUrl: { uploadUrl: {
type: String, type: String,
default: process.env.VUE_APP_UPLOAD_URL, default: process.env.VUE_APP_UPLOAD_URL
}, },
// form 列名 // form 列名
column: [String], column: [String],
// 上传携带的参数 // 上传携带的参数
data: { data: {
type: Object, type: Object
}, },
// 是否拖拽
drag: {
type: Boolean,
default: false
}
}, },
data() { data() {
return { return {
baseUrl: process.env.VUE_APP_BASE_API, baseUrl: process.env.VUE_APP_BASE_API,
uploadFileUrl: process.env.VUE_APP_BASE_API + this.uploadUrl, // 上传的图片服务器地址 uploadFileUrl: process.env.VUE_APP_BASE_API + this.uploadUrl, // 上传的图片服务器地址
headers: { headers: {
Authorization: "Bearer " + getToken(), Authorization: 'Bearer ' + getToken()
}, },
fileList: [], fileList: []
}; }
}, },
watch: { watch: {
value: { value: {
handler(val) { handler(val) {
if (val) { if (val) {
let temp = 1; let temp = 1
// 首先将值转为数组 // 首先将值转为数组
const list = Array.isArray(val) ? val : this.value.split(","); const list = Array.isArray(val) ? val : this.value.split(',')
// 然后将数组转为对象数组 // 然后将数组转为对象数组
this.fileList = list.map((item) => { this.fileList = list.map((item) => {
if (typeof item === "string") { if (typeof item === 'string') {
item = { name: item, url: item }; item = { name: item, url: item }
} }
item.uid = item.uid || new Date().getTime() + temp++; item.uid = item.uid || new Date().getTime() + temp++
return item; return item
}); })
} else { } else {
this.fileList = []; this.fileList = []
return []; return []
} }
}, },
deep: true, deep: true,
immediate: true, immediate: true
}, },
uploadUrl: { uploadUrl: {
handler(val){ handler(val) {
this.uploadFileUrl = process.env.VUE_APP_BASE_API + val; this.uploadFileUrl = process.env.VUE_APP_BASE_API + val
}, },
immediate: true immediate: true
} }
}, },
computed: { computed: {
// 是否显示提示 // 是否显示提示
showTip() { showTip() {
return this.isShowTip && (this.fileType || this.fileSize); return this.isShowTip && (this.fileType || this.fileSize)
}, }
}, },
methods: { methods: {
// 上传前校检格式和大小 // 上传前校检格式和大小
handleBeforeUpload(file) { handleBeforeUpload(file) {
// 校检文件类型 // 校检文件类型
if (this.fileType && this.fileType.length > 0) { if (this.fileType && this.fileType.length > 0) {
let fileExtension = ""; let fileExtension = ''
if (file.name.lastIndexOf(".") > -1) { if (file.name.lastIndexOf('.') > -1) {
fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)
} }
const isTypeOk = this.fileType.some((type) => { const isTypeOk = this.fileType.some((type) => {
if (file.type.indexOf(type) > -1) return true; if (file.type.indexOf(type) > -1) return true
if (fileExtension && fileExtension.indexOf(type) > -1) return true; if (fileExtension && fileExtension.indexOf(type) > -1) return true
return false; return false
}); })
if (!isTypeOk) { if (!isTypeOk) {
this.msgError( this.msgError(
`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!` `文件格式不正确, 请上传${this.fileType.join('/')}格式文件!`
); )
return false; return false
} }
} }
// 校检文件大小 // 校检文件大小
if (this.fileSize) { if (this.fileSize) {
const isLt = file.size / 1024 / 1024 < this.fileSize; const isLt = file.size / 1024 / 1024 < this.fileSize
if (!isLt) { if (!isLt) {
this.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`); this.msgError(`上传文件大小不能超过 ${this.fileSize} MB!`)
return false; return false
} }
} }
return true; return true
}, },
// 文件个数超出 // 文件个数超出
handleExceed() { handleExceed() {
this.msgError(`上传文件数量不能超过 ${this.limit} 个!`); this.msgError(`上传文件数量不能超过 ${this.limit} 个!`)
}, },
// 上传失败 // 上传失败
handleUploadError(err) { handleUploadError(err) {
this.msgError("上传失败, 请重试"); this.msgError('上传失败, 请重试')
this.fileList = []; this.fileList = []
}, },
// 上传成功回调 // 上传成功回调
handleUploadSuccess(res, file) { handleUploadSuccess(res, file) {
if (res.code != 200) { if (res.code != 200) {
this.fileList = []; this.fileList = []
this.msgError(`上传失败,原因:${res.msg}!`); this.msgError(`上传失败,原因:${res.msg}!`)
return; return
} }
this.msgSuccess("上传成功"); this.msgSuccess('上传成功')
this.fileList.push({ name: res.data.fileName, url: res.data.url, path: res.data.path }); this.fileList.push({
this.$emit("input", this.column, this.listToString(this.fileList), res.data); name: res.data.fileName,
url: res.data.url,
path: res.data.path
})
this.$emit(
'input',
this.column,
this.listToString(this.fileList),
res.data
)
}, },
// 上传进度 // 上传进度
uploadProcess(event, file, fileList) { uploadProcess(event, file, fileList) {
@@ -170,28 +187,28 @@ export default {
}, },
// 删除文件 // 删除文件
handleDelete(index) { handleDelete(index) {
this.fileList.splice(index, 1); this.fileList.splice(index, 1)
this.$emit("input", this.column, this.listToString(this.fileList)); this.$emit('input', this.column, this.listToString(this.fileList))
}, },
// 获取文件名称 // 获取文件名称
getFileName(name) { getFileName(name) {
if (name.lastIndexOf("/") > -1) { if (name.lastIndexOf('/') > -1) {
return name.slice(name.lastIndexOf("/") + 1).toLowerCase(); return name.slice(name.lastIndexOf('/') + 1).toLowerCase()
} else { } else {
return name; return name
} }
}, },
// 对象转成指定字符串分隔 // 对象转成指定字符串分隔
listToString(list, separator) { listToString(list, separator) {
let strs = ""; let strs = ''
separator = separator || ","; separator = separator || ','
for (let i in list) { for (const i in list) {
strs += list[i].url + separator; strs += list[i].url + separator
} }
return strs != "" ? strs.substr(0, strs.length - 1) : ""; return strs != '' ? strs.substr(0, strs.length - 1) : ''
}, }
}, }
}; }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@@ -210,4 +227,8 @@ export default {
.ele-upload-list__item-content-action .el-link { .ele-upload-list__item-content-action .el-link {
margin-right: 10px; margin-right: 10px;
} }
::v-deep .el-upload-dragger {
width: 270px;
height: 150px;
}
</style> </style>
+123
View File
@@ -0,0 +1,123 @@
<template>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">通知</div>
<!-- <div class="head-box-btn" v-if="noticeList.length > 0" @click="onAllReadClick">全部已读</div> -->
</div>
<div class="content-box">
<template v-if="noticeList.length > 0">
<div class="content-box-item" v-for="(v, k) in noticeList" :key="k">
<div>{{ v.noticeTitle }}</div>
<div class="content-box-msg" v-html="v.noticeContent"></div>
<div class="content-box-time">{{ v.updateTime }}</div>
</div>
</template>
<div class="content-box-empty" v-else>
<div class="content-box-empty-margin">
<i class="el-icon-s-promotion"></i>
<div class="mt15">全部已读</div>
</div>
</div>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="noticeList.length > 0">前往通知中心</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "noticeIndex",
data() {
return {
dataList: [],
};
},
computed: {
...mapGetters(['noticeList'])
},
mounted() {
},
methods: {
// 全部已读点击
onAllReadClick() {
},
// 前往通知中心点击
onGoToGiteeClick() {
window.open("https://gitee.com/izory/ZrAdminNetCore");
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
color: #333333;
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: #1890ff;
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
font-size: 13px;
.content-box-item {
padding-top: 12px;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: #999999;
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: #999999;
}
}
.content-box-empty {
height: 260px;
display: flex;
.content-box-empty-margin {
margin: auto;
text-align: center;
i {
font-size: 60px;
}
}
}
}
.foot-box {
height: 35px;
color: #1890ff;
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid #ebeef5;
&:hover {
opacity: 1;
}
}
::v-deep(.el-empty__description p) {
font-size: 13px;
}
::v-deep .el-badge__content .is-fixed {
top: 12px !important;
}
}
</style>
+18 -18
View File
@@ -5,54 +5,54 @@
</template> </template>
<script> <script>
import screenfull from 'screenfull' import screenfull from "screenfull";
export default { export default {
name: 'Screenfull', name: "Screenfull",
data() { data() {
return { return {
isFullscreen: false isFullscreen: false,
} };
}, },
mounted() { mounted() {
this.init() this.init();
}, },
beforeDestroy() { beforeDestroy() {
this.destroy() this.destroy();
}, },
methods: { methods: {
click() { click() {
if (!screenfull.enabled) { if (!screenfull.enabled) {
this.$message({ this.$message({
message: 'you browser can not work', message: "you browser can not work",
type: 'warning' type: "warning",
}) });
return false return false;
} }
screenfull.toggle() screenfull.toggle();
}, },
change() { change() {
this.isFullscreen = screenfull.isFullscreen this.isFullscreen = screenfull.isFullscreen;
}, },
init() { init() {
if (screenfull.enabled) { if (screenfull.enabled) {
screenfull.on('change', this.change) screenfull.on("change", this.change);
} }
}, },
destroy() { destroy() {
if (screenfull.enabled) { if (screenfull.enabled) {
screenfull.off('change', this.change) screenfull.off("change", this.change);
} }
} },
} },
} };
</script> </script>
<style scoped> <style scoped>
.screenfull-svg { .screenfull-svg {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
fill: #5a5e66;; fill: #5a5e66;
width: 20px; width: 20px;
height: 20px; height: 20px;
vertical-align: 10px; vertical-align: 10px;
+30 -14
View File
@@ -4,8 +4,8 @@
<hamburger id="hamburger-container" class="hamburger-container" :is-active="sidebar.opened" @toggleClick="toggleSideBar" /> <hamburger id="hamburger-container" class="hamburger-container" :is-active="sidebar.opened" @toggleClick="toggleSideBar" />
<!-- 面包屑导航 --> <!-- 面包屑导航 -->
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/> <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav" />
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/> <top-nav id="topmenu-container" class="topmenu-container" v-if="topNav" />
<div class="right-menu"> <div class="right-menu">
<template v-if="device!=='mobile'"> <template v-if="device!=='mobile'">
@@ -15,12 +15,21 @@
<size-select id="size-select" class="right-menu-item hover-effect" /> <size-select id="size-select" class="right-menu-item hover-effect" />
<!-- </el-tooltip> --> <!-- </el-tooltip> -->
<el-tooltip content="源码地址" effect="dark" placement="bottom"> <el-tooltip content="源码地址" effect="dark" placement="bottom">
<zr-git id="zr-git" class="right-menu-item hover-effect" /> <zr-git class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
<el-tooltip content="文档地址" effect="dark" placement="bottom"> <el-tooltip content="文档地址" effect="dark" placement="bottom">
<zr-doc id="zr-doc" class="right-menu-item hover-effect" /> <zr-doc class="right-menu-item hover-effect" />
</el-tooltip> </el-tooltip>
</template> </template>
<!-- 通知 -->
<div class="right-menu-item">
<el-popover placement="bottom" trigger="click" v-model="isShowUserNewsPopover" width="300" popper-class="el-popover-pupop-user-news">
<el-badge @click.stop="isShowUserNewsPopover = !isShowUserNewsPopover" :is-dot="true" slot="reference">
<i class="el-icon-bell" title="通知"></i>
</el-badge>
<Notice v-show="isShowUserNewsPopover" />
</el-popover>
</div>
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click"> <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
@@ -46,13 +55,14 @@
<script> <script>
import { mapGetters } from "vuex"; import { mapGetters } from "vuex";
import Breadcrumb from "@/components/Breadcrumb"; import Breadcrumb from "@/components/Breadcrumb";
import TopNav from '@/components/TopNav' import TopNav from "@/components/TopNav";
import Hamburger from "@/components/Hamburger"; import Hamburger from "@/components/Hamburger";
import Screenfull from "@/components/Screenfull"; import Screenfull from "@/components/Screenfull";
import SizeSelect from "@/components/SizeSelect"; import SizeSelect from "@/components/SizeSelect";
import Search from "@/components/HeaderSearch"; import Search from "@/components/HeaderSearch";
import ZrGit from "@/components/Zr/Git"; import ZrGit from "@/components/Zr/Git";
import ZrDoc from '@/components/Zr/Doc' import ZrDoc from "@/components/Zr/Doc";
import Notice from "@/components/Notice/Index.vue";
export default { export default {
components: { components: {
@@ -63,7 +73,13 @@ export default {
SizeSelect, SizeSelect,
Search, Search,
ZrGit, ZrGit,
ZrDoc ZrDoc,
Notice,
},
data() {
return {
isShowUserNewsPopover: false,
};
}, },
computed: { computed: {
...mapGetters(["sidebar", "avatar", "device"]), ...mapGetters(["sidebar", "avatar", "device"]),
@@ -80,9 +96,9 @@ export default {
}, },
topNav: { topNav: {
get() { get() {
return this.$store.state.settings.topNav return this.$store.state.settings.topNav;
} },
} },
}, },
methods: { methods: {
toggleSideBar() { toggleSideBar() {
@@ -135,7 +151,7 @@ export default {
float: left; float: left;
} }
.topmenu-container { .topmenu-container {
position: absolute; position: absolute;
left: 50px; left: 50px;
} }
@@ -146,9 +162,9 @@ export default {
} }
.right-menu { .right-menu {
float: right; display: flex;
height: 100%; align-items: center;
line-height: 50px; justify-content: flex-end;
&:focus { &:focus {
outline: none; outline: none;
+10 -2
View File
@@ -17,11 +17,19 @@ export default {
const vnodes = [] const vnodes = []
if (icon) { if (icon) {
vnodes.push(<svg-icon icon-class={icon}/>) vnodes.push(<svg-icon icon-class={icon} />)
} }
if (title) { if (title) {
vnodes.push(<span slot='title'>{(title)}</span>) if (title.length > 5) {
vnodes.push(
<span slot='title' title={title}>
{title}
</span>
)
} else {
vnodes.push(<span slot='title'>{title}</span>)
}
} }
return vnodes return vnodes
} }
+7 -3
View File
@@ -12,12 +12,13 @@ import store from './store'
import router from './router' import router from './router'
import permission from './directive/permission' import permission from './directive/permission'
import plugins from './plugins' // plugins import plugins from './plugins' // plugins
import signalR from '@/utils/signalR'
import './assets/icons' // icon import './assets/icons' // icon
import './permission' // permission control import './permission' // permission control
import { getDicts} from "@/api/system/dict/data"; import { getDicts } from "@/api/system/dict/data";
import { getConfigKey } from "@/api/system/config"; import { getConfigKey } from "@/api/system/config";
import { parseTime, resetForm, addDateRange, addDateRange2, selectDictLabel, selectDictLabels, download, handleTree } from "@/utils/ruoyi"; import { parseTime, resetForm, addDateRange, selectDictLabel, selectDictLabels, download, handleTree, handleDict } from "@/utils/ruoyi";
//分页组件 //分页组件
import Pagination from "@/components/Pagination"; import Pagination from "@/components/Pagination";
//自定义表格工具扩展 //自定义表格工具扩展
@@ -37,11 +38,11 @@ Vue.prototype.getConfigKey = getConfigKey
Vue.prototype.parseTime = parseTime Vue.prototype.parseTime = parseTime
Vue.prototype.resetForm = resetForm Vue.prototype.resetForm = resetForm
Vue.prototype.addDateRange = addDateRange Vue.prototype.addDateRange = addDateRange
Vue.prototype.addDateRange2 = addDateRange2
Vue.prototype.selectDictLabel = selectDictLabel Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download Vue.prototype.download = download
Vue.prototype.handleTree = handleTree Vue.prototype.handleTree = handleTree
Vue.prototype.handleDict = handleDict
Vue.prototype.msgSuccess = function (msg) { Vue.prototype.msgSuccess = function (msg) {
this.$message({ showClose: true, message: msg, type: "success" }); this.$message({ showClose: true, message: msg, type: "success" });
@@ -71,6 +72,9 @@ Vue.use(Element, {
Vue.config.productionTip = false Vue.config.productionTip = false
signalR.init(process.env.VUE_APP_SOCKET_API);
Vue.prototype.signalr = signalR
new Vue({ new Vue({
el: '#app', el: '#app',
router, router,
+77
View File
@@ -0,0 +1,77 @@
const sessionCache = {
set(key, value) {
if (!sessionStorage) {
return
}
if (key != null && value != null) {
sessionStorage.setItem(key, value)
}
},
get(key) {
if (!sessionStorage) {
return null
}
if (key == null) {
return null
}
return sessionStorage.getItem(key)
},
setJSON(key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON(key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove(key) {
sessionStorage.removeItem(key);
}
}
const localCache = {
set(key, value) {
if (!localStorage) {
return
}
if (key != null && value != null) {
localStorage.setItem(key, value)
}
},
get(key) {
if (!localStorage) {
return null
}
if (key == null) {
return null
}
return localStorage.getItem(key)
},
setJSON(key, jsonValue) {
if (jsonValue != null) {
this.set(key, JSON.stringify(jsonValue))
}
},
getJSON(key) {
const value = this.get(key)
if (value != null) {
return JSON.parse(value)
}
},
remove(key) {
localStorage.removeItem(key);
}
}
export default {
/**
* 会话级缓存
*/
session: sessionCache,
/**
* 本地缓存
*/
local: localCache
}
+4 -4
View File
@@ -1,7 +1,7 @@
import tab from './tab' import tab from './tab'
// import auth from './auth' // import auth from './auth'
// import cache from './cache' import cache from './cache'
// import modal from './modal' import modal from './modal'
// import download from './download' // import download from './download'
export default { export default {
@@ -11,9 +11,9 @@ export default {
// 认证对象 // 认证对象
// Vue.prototype.$auth = auth // Vue.prototype.$auth = auth
// 缓存对象 // 缓存对象
// Vue.prototype.$cache = cache Vue.prototype.$cache = cache
// 模态框对象 // 模态框对象
// Vue.prototype.$modal = modal Vue.prototype.$modal = modal
// 下载文件 // 下载文件
// Vue.prototype.$download = download // Vue.prototype.$download = download
} }
+83
View File
@@ -0,0 +1,83 @@
import { Message, MessageBox, Notification, Loading } from 'element-ui'
let loadingInstance;
export default {
// 消息提示
msg(content) {
Message.info(content)
},
// 错误消息
msgError(content) {
Message.error(content)
},
// 成功消息
msgSuccess(content) {
Message.success(content)
},
// 警告消息
msgWarning(content) {
Message.warning(content)
},
// 弹出提示
alert(content) {
MessageBox.alert(content, "系统提示")
},
// 错误提示
alertError(content) {
MessageBox.alert(content, "系统提示", { type: 'error' })
},
// 成功提示
alertSuccess(content) {
MessageBox.alert(content, "系统提示", { type: 'success' })
},
// 警告提示
alertWarning(content) {
MessageBox.alert(content, "系统提示", { type: 'warning' })
},
// 通知提示
notify(content) {
Notification.info(content)
},
// 错误通知
notifyError(content) {
Notification.error(content);
},
// 成功通知
notifySuccess(content) {
Notification.success(content)
},
// 警告通知
notifyWarning(content) {
Notification.warning(content)
},
// 确认窗体
confirm(content) {
return MessageBox.confirm(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 提交内容
prompt(content) {
return MessageBox.prompt(content, "系统提示", {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: "warning",
})
},
// 打开遮罩层
loading(content) {
loadingInstance = Loading.service({
lock: true,
text: content,
spinner: "el-icon-loading",
background: "rgba(0, 0, 0, 0.7)",
})
},
// 关闭遮罩层
closeLoading() {
loadingInstance.close();
}
}
+5 -4
View File
@@ -4,20 +4,21 @@ import router from '@/router';
export default { export default {
// 刷新当前tab页签 // 刷新当前tab页签
refreshPage(obj) { refreshPage(obj) {
const { path, matched } = router.currentRoute; const { path, query, matched } = router.currentRoute;
if (obj === undefined) { if (obj === undefined) {
matched.forEach((m) => { matched.forEach((m) => {
if (m.components && m.components.default && m.components.default.name) { if (m.components && m.components.default && m.components.default.name) {
if (!['Layout', 'ParentView'].includes(m.components.default.name)) { if (!['Layout', 'ParentView'].includes(m.components.default.name)) {
obj = { name: m.components.default.name, path: path }; obj = { name: m.components.default.name, path: path, query: query };
} }
} }
}); });
} }
return store.dispatch('tagsView/delCachedView', obj).then(() => { return store.dispatch('tagsView/delCachedView', obj).then(() => {
const { path } = obj const { path, query } = obj
router.replace({ router.replace({
path: '/redirect' + path path: '/redirect' + path,
query: query
}) })
}) })
}, },
+1 -1
View File
@@ -2,7 +2,7 @@ module.exports = {
/** /**
* 框架版本号 * 框架版本号
*/ */
version: '3.7.7', version: '3.7.8',
title: 'ZrAdmin.NET-后台管理', title: 'ZrAdmin.NET-后台管理',
/** /**
* 主题颜色 * 主题颜色

Some files were not shown because too many files have changed in this diff Show More