diff --git a/Bootstrap.Admin/Bootstrap.Admin.csproj b/Bootstrap.Admin/Bootstrap.Admin.csproj
index ccc212e5..71a006b2 100644
--- a/Bootstrap.Admin/Bootstrap.Admin.csproj
+++ b/Bootstrap.Admin/Bootstrap.Admin.csproj
@@ -158,6 +158,7 @@
+
@@ -187,6 +188,7 @@
+
@@ -196,6 +198,7 @@
+
@@ -233,6 +236,7 @@
+
diff --git a/Bootstrap.Admin/Controllers/AdminController.cs b/Bootstrap.Admin/Controllers/AdminController.cs
index 02417673..8efb76ac 100644
--- a/Bootstrap.Admin/Controllers/AdminController.cs
+++ b/Bootstrap.Admin/Controllers/AdminController.cs
@@ -72,6 +72,14 @@ namespace Bootstrap.Admin.Controllers
v.HomeUrl = "~/Admin";
return View(v);
}
+ public ActionResult Logs()
+ {
+ var v = new NavigatorBarModel();
+ v.ShowMenu = "hide";
+ v.Menus[6].Active = "active";
+ v.HomeUrl = "~/Admin";
+ return View(v);
+ }
///
///
///
diff --git a/Bootstrap.Admin/Controllers/LogsController.cs b/Bootstrap.Admin/Controllers/LogsController.cs
new file mode 100644
index 00000000..394ad632
--- /dev/null
+++ b/Bootstrap.Admin/Controllers/LogsController.cs
@@ -0,0 +1,31 @@
+using Bootstrap.Admin.Models;
+using Bootstrap.DataAccess;
+using System.Linq;
+using System.Web.Http;
+
+namespace Bootstrap.Admin.Controllers
+{
+ public class LogsController : ApiController
+ {
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public QueryData Get([FromUri]QueryLogOption value)
+ {
+ return value.RetrieveData();
+ }
+ ///
+ ///
+ ///
+ ///
+ ///
+ [HttpGet]
+ public Log Get(int id)
+ {
+ return LogHelper.RetrieveLogs().FirstOrDefault(t => t.ID == id);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bootstrap.Admin/Models/QueryLogOption.cs b/Bootstrap.Admin/Models/QueryLogOption.cs
new file mode 100644
index 00000000..e6427680
--- /dev/null
+++ b/Bootstrap.Admin/Models/QueryLogOption.cs
@@ -0,0 +1,72 @@
+using Bootstrap.DataAccess;
+using Longbow.Web.Mvc;
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace Bootstrap.Admin.Models
+{
+ public class QueryLogOption : PaginationOption
+ {
+ ///
+ ///
+ ///
+ public string OperateType { get; set; }
+ ///
+ ///
+ ///
+ public string OperateTimeStart { get; set; }
+ ///
+ ///
+ ///
+ public string OperateTimeEnd { get; set; }
+ public QueryData RetrieveData()
+ {
+ var data = LogHelper.RetrieveLogs(string.Empty);
+ if (!string.IsNullOrEmpty(OperateType))
+ {
+ data = data.Where(t => t.OperationType.ToString().Contains(OperateType));
+ }
+
+ if (!string.IsNullOrEmpty(OperateTimeStart))
+ {
+ DateTime opTimeStart = StringToDateTime(OperateTimeStart);
+ if (opTimeStart != null)
+ data = data.Where(t => IsSmallThen(opTimeStart, t.OperationTime));
+ }
+ if (!string.IsNullOrEmpty(OperateTimeEnd))
+ {
+ DateTime opTimeEnd = StringToDateTime(OperateTimeEnd);
+ if (opTimeEnd != null)
+ data = data.Where(t => IsSmallThen(t.OperationTime, opTimeEnd));
+ }
+
+ var ret = new QueryData();
+ ret.total = data.Count();
+ // TODO: 通过option.Sort属性判断对那列进行排序,现在统一对名称列排序
+ data = Order == "asc" ? data.OrderBy(t => t.OperationType) : data.OrderByDescending(t => t.OperationType);
+ ret.rows = data.Skip(Offset).Take(Limit);
+ return ret;
+ }
+ private static DateTime StringToDateTime(string dt_str)
+ {
+ DateTime dt ;
+ DateTimeFormatInfo dtFormat = new DateTimeFormatInfo();
+ dtFormat.ShortDatePattern = "yyyy-MM-dd HH:mm:ss";
+ dt = Convert.ToDateTime(dt_str, dtFormat);
+ return dt;
+ }
+ ///
+ /// 比较两个DateTime
+ /// (去掉了毫秒)
+ ///
+ ///
+ ///
+ ///
+ private static bool IsSmallThen(DateTime d1, DateTime d2)
+ {
+ return new DateTime(d1.Year, d1.Month, d1.Day, d1.Hour, d1.Minute, d1.Second) <=
+ new DateTime(d2.Year, d2.Month, d2.Day, d2.Hour, d2.Minute, d2.Second);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bootstrap.Admin/Scripts/Logs.js b/Bootstrap.Admin/Scripts/Logs.js
new file mode 100644
index 00000000..4f2f03c7
--- /dev/null
+++ b/Bootstrap.Admin/Scripts/Logs.js
@@ -0,0 +1,35 @@
+$(function () {
+ //隐藏掉操作按钮
+ $("#toolbar").hide();
+
+ var bsa = new BootstrapAdmin({
+ url: '../api/Logs',
+ dataEntity: new DataEntity({
+ map: {
+ ID: "logID",
+ OperationType: "operateType",
+ UserID: "userId",
+ OperationTime: "operateTime",
+ operateIp: "OperationIp"
+ }
+ })
+ });
+ $('table').smartTable({
+ url: '../api/Logs', //请求后台的URL(*)
+ sortName: 'OperationType',
+ queryParams: function (params) { return $.extend(params, { operateType: $("#txt_operate_type").val(), OperateTimeStart: $("#txt_operate_start").val(), OperateTimeEnd: $("#txt_operate_end").val() }); }, //传递参数(*)
+ columns: [{ checkbox: true },
+ { title: "Id", field: "ID", events: bsa.idEvents(), formatter: BootstrapAdmin.idFormatter, },
+ { title: "操作类型", field: "OperationType", sortable: true },
+ { title: "用户名称", field: "UserName", sortable: false },
+ {
+ title: "操作时间", field: "OperationTime", sortable: false,
+ formatter: function (value, row, index) {
+ return value.substring(0,19).replace("T", " ");
+ }
+ },
+ { title: "操作IP", field: "OperationIp", sortable: false },
+ { title: "备注", field: "Remark", sortable: false }
+ ]
+ });
+});
\ No newline at end of file
diff --git a/Bootstrap.Admin/Views/Admin/Logs.cshtml b/Bootstrap.Admin/Views/Admin/Logs.cshtml
new file mode 100644
index 00000000..6581f163
--- /dev/null
+++ b/Bootstrap.Admin/Views/Admin/Logs.cshtml
@@ -0,0 +1,34 @@
+@model NavigatorBarModel
+@{
+ ViewBag.Title = "系统日志";
+ Layout = "~/Views/Shared/_Default.cshtml";
+}
+@section Javascript {
+
+}
+@section header {
+ @Html.Partial("Header", Model)
+}
+@section navigator {
+ @Html.Partial("Navigator", Model)
+}
+@section query {
+
+}
diff --git a/Bootstrap.DataAccess/Log.cs b/Bootstrap.DataAccess/Log.cs
index e3c29f88..9dc3c528 100644
--- a/Bootstrap.DataAccess/Log.cs
+++ b/Bootstrap.DataAccess/Log.cs
@@ -14,38 +14,23 @@ namespace Bootstrap.DataAccess
public int OperationType { get; set; }
///
- /// 获得/设置 用户ID
+ /// 获得/设置 用户名称
///
- public int UserID { get; set; }
+ public string UserName { get; set; }
///
/// 获得/设置 操作时间
///
public DateTime OperationTime { get; set; }
- ///
- /// 获得/设置 操作表表名
- ///
- public string TableName { get; set; }
-
- ///
- /// 获得/设置 操作内容
- ///
- public string BusinessName { get; set; }
-
- ///
- /// 获得/设置 操作表的主键
- ///
- public string PrimaryKey { get; set; }
-
- ///
- /// 获得/设置 sql语句
- ///
- public string SqlText { get; set; }
-
///
/// 获得/设置 操作者Ip
///
public string OperationIp { get; set; }
+
+ ///
+ /// 获取/设置 备注
+ ///
+ public string Remark { get; set; }
}
}
diff --git a/Bootstrap.DataAccess/LogHelper.cs b/Bootstrap.DataAccess/LogHelper.cs
index 0226b135..a987b8aa 100644
--- a/Bootstrap.DataAccess/LogHelper.cs
+++ b/Bootstrap.DataAccess/LogHelper.cs
@@ -1,4 +1,5 @@
-using Longbow.Caching;
+using Longbow;
+using Longbow.Caching;
using Longbow.Caching.Configuration;
using Longbow.ExceptionManagement;
using System;
@@ -35,13 +36,10 @@ namespace Bootstrap.DataAccess
{
ID = (int)reader[0],
OperationType = (int)reader[1],
- UserID = (int)reader[2],
+ UserName = (string)reader[2],
OperationTime = (DateTime)reader[3],
- TableName = (string)reader[4],
- BusinessName = (string)reader[5],
- PrimaryKey = (string)reader[6],
- SqlText = (string)reader[7],
- OperationIp = (string)reader[8],
+ OperationIp = LgbConvert.ReadValue((string)reader[4],string.Empty),
+ Remark=LgbConvert.ReadValue((string)reader[5],string.Empty)
});
}
}
@@ -85,19 +83,16 @@ namespace Bootstrap.DataAccess
{
if (p == null) throw new ArgumentNullException("p");
bool ret = false;
- string sql = "Insert Into Logs (OperationType, UserID,OperationTime,TableName,BusinessName,PrimaryKey,SqlText,OperationIp) Values (@OperationType, @UserID,@OperationTime,@TableName,@BusinessName,@PrimaryKey,@SqlText,@OperationIp)";
+ string sql = "Insert Into Logs (OperationType, UserName,OperationTime,OperationIp,Remark) Values (@OperationType, @UserName,@OperationTime,@OperationIp,@Remark)";
try
{
using (DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, sql))
{
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@OperationType", p.OperationType, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@UserID", p.UserID, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@OperationTime", p.OperationTime, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@TableName", p.TableName, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@BusinessName", p.BusinessName, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@PrimaryKey", p.PrimaryKey, ParameterDirection.Input));
- cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@SqlText", p.SqlText, ParameterDirection.Input));
+ cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@UserName", p.UserName, ParameterDirection.Input));
+ cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@OperationTime", System.DateTime.Now, ParameterDirection.Input));
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@OperationIp", p.OperationIp, ParameterDirection.Input));
+ cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@Remark", p.Remark, ParameterDirection.Input));
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
}
ret = true;
diff --git a/Bootstrap.DataAccessTests/LogHelperTests.cs b/Bootstrap.DataAccessTests/LogHelperTests.cs
index ed60a475..5275b7b1 100644
--- a/Bootstrap.DataAccessTests/LogHelperTests.cs
+++ b/Bootstrap.DataAccessTests/LogHelperTests.cs
@@ -1,7 +1,7 @@
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-using System.Data;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Data.Common;
-using System.Linq;
+using System.Data;
namespace Bootstrap.DataAccess.Tests
{
@@ -12,12 +12,12 @@ namespace Bootstrap.DataAccess.Tests
[TestInitialize]
public void Initialized()
{
- Log = new Log() { OperationType = 1, UserID = 1, OperationTime = System.DateTime.Now, TableName = "_测试日志_", BusinessName = "新增测试日志信息", PrimaryKey = "ID", SqlText = "Insert Into Logs", OperationIp = "0.0.0.0" };
+ Log = new Log() { OperationType = 1, UserName = "_测试用户名称_", OperationTime = System.DateTime.Now, OperationIp = "0.0.0.0",Remark="" };
}
[TestCleanup]
public void CleanUp()
{
- using (DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, "delete from Logs where OperationIp='0'"))
+ using (DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, "delete from Logs where UserName='_测试用户名称_'"))
{
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
}
@@ -30,17 +30,17 @@ namespace Bootstrap.DataAccess.Tests
[TestMethod]
public void SaveLogTest()
{
- Assert.IsTrue(LogHelper.SaveLog(Log), "新增日志信息出错,请检查LogHelper的saveLog 方法");
+ Assert.IsTrue(LogHelper.SaveLog(Log), "新增日志信息出错,请检查LogHelper的SaveLog 方法");
var logs = LogHelper.RetrieveLogs();
- Assert.IsTrue(logs.Count() > 0, "新增日志信息出错,请检查LogHelper的saveLog 方法");
+ Assert.IsTrue(logs.Count() > 0, "新增日志信息出错,请检查LogHelper的SaveLog 方法");
}
[TestMethod]
public void DeleteLogTest()
{
// 先判断数据环境是否可以删除,没有数据先伪造数据
- var log = LogHelper.RetrieveLogs().FirstOrDefault(m => m.OperationType == Log.OperationType);
+ var log = LogHelper.RetrieveLogs().FirstOrDefault(l => l.UserName == Log.UserName);
if (log == null) LogHelper.SaveLog(Log);
- log = LogHelper.RetrieveLogs().FirstOrDefault(m => m.OperationType == Log.OperationType);
+ log = LogHelper.RetrieveLogs().FirstOrDefault(l => l.UserName == Log.UserName);
Assert.IsTrue(LogHelper.DeleteLog(log.ID.ToString()), "删除日志信息出错");
}
}
diff --git a/DatabaseScripts/Install.sql b/DatabaseScripts/Install.sql
index 9ceabfe4..6be0c4f6 100644
--- a/DatabaseScripts/Install.sql
+++ b/DatabaseScripts/Install.sql
@@ -180,27 +180,29 @@ EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'字典名称'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'字典代码' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Dicts', @level2type=N'COLUMN',@level2name=N'Code'
GO
-/****** Object: Table [dbo].[Logs] Script Date: 10/28/2016 16:39:11 ******/
+GO
+/****** Object: Table [dbo].[Logs] Script Date: 11/02/2016 15:33:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
+SET ANSI_PADDING ON
+GO
CREATE TABLE [dbo].[Logs](
- [ID] [int] IDENTITY(1,1) NOT NULL,
- [OperationType] [int] NULL,
- [UserID] [int] NULL,
- [OperationTime] [datetime] NULL,
- [TableName] [nvarchar](50) NULL,
- [BusinessName] [nvarchar](50) NULL,
- [PrimaryKey] [nvarchar](50) NULL,
- [SqlText] [nvarchar](max) NULL,
- [OperationIp] [nvarchar](50) NULL,
+ [ID] [int] IDENTITY(1,1) NOT NULL,
+ [OperationType] [int] NOT NULL,
+ [UserName] [varchar](50) NOT NULL,
+ [OperationTime] [datetime] NOT NULL,
+ [OperationIp] [nvarchar](50) NULL,
+ [Remark] [nvarchar](500) NULL,
CONSTRAINT [PK_Logs] PRIMARY KEY CLUSTERED
(
- [ID] ASC
+ [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
+SET ANSI_PADDING OFF
+GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Logs', @level2type=N'COLUMN',@level2name=N'ID'
GO
EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'Logs', @level2type=N'COLUMN',@level2name=N'OperationType'