完成Web控制台,各页面访问可用

This commit is contained in:
大石头 2019-03-31 17:56:11 +08:00
parent 67c9e92ddd
commit 55059fcb12
37 changed files with 2238 additions and 635 deletions

3
.gitignore vendored
View File

@ -22,3 +22,6 @@ bld/
*.nuspec
*.nupkg
/Avatars
/AntJob.Web/Config
/AntJob.Web/Content
/AntJob.Web/Plugins

View File

@ -1,24 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using NewLife.Serialization;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
@ -30,8 +17,12 @@ namespace AntJob.Data.Entity
static Job()
{
// 累加字段
//var df = Meta.Factory.AdditionalFields;
//df.Add(__.AppID);
var df = Meta.Factory.AdditionalFields;
df.Add(__.Total);
df.Add(__.Success);
df.Add(__.Error);
df.Add(__.Times);
//df.Add(__.MessageCount);
// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<UserModule>();
@ -46,103 +37,66 @@ namespace AntJob.Data.Entity
// 如果没有脏数据,则不需要进行任何处理
if (!HasDirty) return;
// 在新插入数据或者修改了指定字段时进行修正
// 处理当前已登录用户信息可以由UserModule过滤器代劳
/*var user = ManageProvider.User;
if (user != null)
{
if (isNew && !Dirtys[nameof(CreateUserID)) nameof(CreateUserID) = user.ID;
if (!Dirtys[nameof(UpdateUserID)]) nameof(UpdateUserID) = user.ID;
}*/
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
//if (isNew && !Dirtys[nameof(CreateIP)]) nameof(CreateIP) = ManageProvider.UserHost;
//if (!Dirtys[nameof(UpdateIP)]) nameof(UpdateIP) = ManageProvider.UserHost;
// 参数默认值
if (Step == 0) Step = 5;
if (MaxRetain == 0) MaxRetain = 3;
if (MaxIdle == 0) MaxIdle = GetDefaultIdle();
// 检查唯一索引
// CheckExist(isNew, __.AppID, __.Name);
if (isNew)
{
if (!Dirtys[nameof(MaxRetry)]) MaxRetry = 10;
if (!Dirtys[nameof(MaxTime)]) MaxTime = 600;
if (!Dirtys[nameof(ErrorDelay)]) ErrorDelay = 60;
if (!Dirtys[nameof(MaxIdle)]) MaxIdle = GetDefaultIdle();
}
// 截断错误信息,避免过长
var len = _.Description.Length;
if (!Description.IsNullOrEmpty() && len > 0 && Description.Length > len) Description = Description.Substring(0, len);
var app = App;
if (isNew && app != null)
{
app.JobCount = FindCountByAppID(app.ID);
app.SaveAsync();
}
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
private Int32 GetDefaultIdle()
{
// 定时调度,取步进加一分钟
if (Mode == JobModes.Alarm) return Step + 600;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化Job[作业]数据……");
return 3600;
}
// var entity = new Job();
// entity.ID = 0;
// entity.AppID = 0;
// entity.Name = "abc";
// entity.DisplayName = "abc";
// entity.Mode = 0;
// entity.Topic = "abc";
// entity.MessageCount = 0;
// entity.Start = DateTime.Now;
// entity.End = DateTime.Now;
// entity.Step = 0;
// entity.MinStep = 0;
// entity.MaxStep = 0;
// entity.StepRate = 0;
// entity.BatchSize = 0;
// entity.Offset = 0;
// entity.MaxTask = 0;
// entity.MaxError = 0;
// entity.MaxRetry = 0;
// entity.MaxTime = 0;
// entity.MaxRetain = 0;
// entity.MaxIdle = 0;
// entity.ErrorDelay = 0;
// entity.Total = 0;
// entity.Success = 0;
// entity.Error = 0;
// entity.Times = 0;
// entity.Speed = 0;
// entity.FetchSpeed = 0;
// entity.Enable = true;
// entity.Description = "abc";
// entity.CreateUserID = 0;
// entity.CreateUser = "abc";
// entity.CreateTime = DateTime.Now;
// entity.CreateIP = "abc";
// entity.UpdateUserID = 0;
// entity.UpdateUser = "abc";
// entity.UpdateTime = DateTime.Now;
// entity.UpdateIP = "abc";
// entity.Insert();
protected override Int32 OnDelete()
{
var rs = base.OnDelete();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化Job[作业]数据!");
//}
var app = App;
if (app != null)
{
app.JobCount = FindCountByAppID(app.ID);
app.SaveAsync();
}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
return rs;
}
#endregion
#region
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
public App App { get { return Extends.Get(nameof(App), k => App.FindByID(AppID)); } }
public App App => Extends.Get(nameof(App), k => App.FindByID(AppID));
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID, typeof(App), "ID")]
public String AppName { get { return App?.Name; } }
[Map(__.AppID)]
public String AppName => App?.Name;
#endregion
#region
@ -158,8 +112,6 @@ namespace AntJob.Data.Entity
// 单对象缓存
return Meta.SingleCache[id];
//return Find(_.ID == id);
}
/// <summary>根据应用、名称查找</summary>
@ -173,12 +125,360 @@ namespace AntJob.Data.Entity
return Find(_.AppID == appid & _.Name == name);
}
public static IList<Job> FindAllByAppID(Int32 appid)
{
if (appid == 0) return new List<Job>();
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.AppID == appid);
return FindAll(_.AppID == appid);
}
/// <summary>
/// 直接查库,不查缓存
/// </summary>
/// <param name="appid"></param>
/// <returns></returns>
public static IList<Job> FindAllByAppID2(Int32 appid)
{
if (appid == 0) return new List<Job>();
return FindAll(_.AppID == appid);
}
/// <summary>
/// 查询当前应用的作业数
/// </summary>
/// <param name="appid"></param>
/// <returns></returns>
public static Int32 FindCountByAppID(Int32 appid)
{
if (appid == 0) return 0;
return (Int32)FindCount(_.AppID == appid);
}
#endregion
#region
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <param name="p"></param>
/// <returns></returns>
public static IEnumerable<Job> Search(Int32 id, Int32 appid, DateTime start, DateTime end, Int32 mode, String key, PageParameter p)
{
var exp = new WhereExpression();
if (id > 0) exp &= _.ID == id;
if (appid > 0) exp &= _.AppID == appid;
if (mode > 0) exp &= _.Mode == mode;
if (!key.IsNullOrEmpty()) exp &= _.Name.Contains(key);
exp &= _.CreateTime.Between(start, end);
return FindAll(exp, p);
}
#endregion
#region
/// <summary>重置任务,让它从新开始工作</summary>
/// <param name="days">重置到多少天之前</param>
/// <param name="stime">开始时间优先级低于days</param>
/// <param name="etime">结束时间优先级低于days</param>
public void ResetTime(Int32 days, DateTime stime, DateTime etime)
{
if (days < 0)
{
Start = DateTime.MinValue;
if (stime > DateTime.MinValue)
Start = stime;
End = etime;
}
else
Start = DateTime.Now.Date.AddDays(-days);
Save();
}
/// <summary>重置任务,让它从新开始工作</summary>
public void ResetOther()
{
Total = 0;
Success = 0;
Times = 0;
Speed = 0;
FetchSpeed = 0;
Error = 0;
Save();
}
/// <summary>删除过期</summary>
/// <returns></returns>
public Int32 DeleteItems()
{
// 每个作业保留1000行
var count = JobLog.FindCountByJobId(ID);
if (count <= 1000) return 0;
var days = MaxRetain;
if (days <= 0) days = 3;
var last = JobLog.FindLastByJobId(ID, DateTime.Now.AddDays(-days));
if (last == null) return 0;
return JobLog.DeleteByID(ID, last.ID);
}
#endregion
#region
/// <summary>申请任务分片</summary>
/// <param name="server">申请任务的服务端</param>
/// <param name="ip">申请任务的IP</param>
/// <param name="pid">申请任务的服务端进程ID</param>
/// <param name="count">要申请的任务个数</param>
/// <returns></returns>
public IList<JobLog> Acquire(String server, String ip, Int32 pid, Int32 count)
{
var list = new List<JobLog>();
if (!Enable) return list;
var step = Step;
if (step <= 0) step = 30;
lock (this)
{
using (var ts = Meta.CreateTrans())
{
var start = Start;
for (var i = 0; i < count; i++)
{
if (!TrySplit(start, step, out var end)) break;
// 创建新的分片
var ti = new JobLog
{
AppID = AppID,
JobID = ID,
Start = start,
End = end,
Step = step,
BatchSize = BatchSize,
};
ti.Server = server;
ti.ProcessID = pid;
ti.Client = $"{ip}@{pid}";
ti.Status = JobStatus.;
//根据数据任务设置的偏移量来计算任务项的偏移量
ti.Offset = Offset;
ti.CreateTime = DateTime.Now;
ti.UpdateTime = DateTime.Now;
ti.Insert();
// 更新任务
Start = end;
start = end;
list.Add(ti);
}
if (list.Count > 0)
{
// 任务需要ID不能批量插入优化
//list.Insert(null);
UpdateTime = DateTime.Now;
Save();
ts.Commit();
}
return list;
}
}
}
/// <summary>尝试分割时间片</summary>
/// <param name="start"></param>
/// <param name="step"></param>
/// <param name="end"></param>
/// <returns></returns>
public Boolean TrySplit(DateTime start, Int32 step, out DateTime end)
{
// 当前时间减去偏移量,作为当前时间。数据抽取不许超过该时间
var now = DateTime.Now.AddSeconds(-Offset);
// 每毫秒有10000个滴答
var sec = now.Ticks / 1_000_0000;
now = new DateTime(sec * 1_000_0000);
end = DateTime.MinValue;
// 开始时间和结束时间是否越界
if (start >= now) return false;
if (step <= 0) step = 30;
// 必须严格要求按照步进大小分片除非有合适的End
end = start.AddSeconds(step);
// 任务结束时间超过作业结束时间时,取后者
if (End.Year > 2000 && end > End) end = End;
// 时间片必须严格要求按照步进大小分片除非有合适的End
if (Mode != JobModes.Alarm)
{
if (end > now) return false;
}
// 时间区间判断
if (start >= end) return false;
return true;
}
/// <summary>申请历史错误或中断的任务</summary>
/// <param name="server">申请任务的服务端</param>
/// <param name="ip">申请任务的IP</param>
/// <param name="pid">申请任务的服务端进程ID</param>
/// <param name="count">要申请的任务个数</param>
/// <returns></returns>
public IList<JobLog> AcquireOld(String server, String ip, Int32 pid, Int32 count)
{
lock (this)
{
using (var ts = Meta.CreateTrans())
{
var list = new List<JobLog>();
// 查找历史错误任务
if (ErrorDelay > 0)
{
var dt = DateTime.Now.AddSeconds(-ErrorDelay);
var list2 = JobLog.Search(ID, dt, MaxRetry, new[] { JobStatus., JobStatus. }, count);
if (list2.Count > 0) list.AddRange(list2);
}
// 查找历史中断任务持续10分钟仍然未完成
if (MaxTime > 0 && list.Count < count)
{
var dt = DateTime.Now.AddSeconds(-MaxTime);
var list2 = JobLog.Search(ID, dt, MaxRetry, new[] { JobStatus., JobStatus., JobStatus. }, count - list.Count);
if (list2.Count > 0) list.AddRange(list2);
}
if (list.Count > 0)
{
foreach (var ti in list)
{
ti.Server = server;
ti.ProcessID = pid;
ti.Client = $"{ip}@{pid}";
//ti.Status = JobStatus.就绪;
ti.CreateTime = DateTime.Now;
ti.UpdateTime = DateTime.Now;
}
list.Save();
}
ts.Commit();
return list;
}
}
}
/// <summary>申请任务分片</summary>
/// <param name="topic">主题</param>
/// <param name="server">申请任务的服务端</param>
/// <param name="ip">申请任务的IP</param>
/// <param name="pid">申请任务的服务端进程ID</param>
/// <param name="count">要申请的任务个数</param>
/// <returns></returns>
public IList<JobLog> AcquireMessage(String topic, String server, String ip, Int32 pid, Int32 count)
{
// 消费消息时,保存主题
if (Topic != topic)
{
Topic = topic;
SaveAsync();
}
var list = new List<JobLog>();
if (!Enable) return list;
// 验证消息数
var now = DateTime.Now;
if (MessageCount == 0 && UpdateTime.AddMinutes(2) > now) return list;
lock (this)
{
using (var ts = Meta.CreateTrans())
{
var size = BatchSize;
if (size == 0) size = 1;
// 消费消息。请求任务数量=空闲线程*批大小
var msgs = AppMessage.GetTopic(AppID, topic, now, count * size);
if (msgs.Count > 0)
{
for (var i = 0; i < msgs.Count;)
{
var msgList = msgs.Skip(i).Take(size).ToList();
if (msgList.Count == 0) break;
i += msgList.Count;
// 创建新的分片
var ti = new JobLog
{
AppID = AppID,
JobID = ID,
Data = msgList.Select(e => e.Data).ToJson(),
MsgCount = msgList.Count,
BatchSize = size,
};
ti.Server = server;
ti.ProcessID = pid;
ti.Client = $"{ip}@{pid}";
ti.Status = JobStatus.;
ti.CreateTime = DateTime.Now;
ti.UpdateTime = DateTime.Now;
ti.Insert();
list.Add(ti);
}
// 批量删除消息
msgs.Delete();
}
// 更新作业下的消息数
MessageCount = AppMessage.FindCountByAppIDAndTopic(AppID, topic);
UpdateTime = now;
Save();
// 消费完成后,更新应用的消息数
if (MessageCount == 0)
{
var app = App;
if (app != null)
{
app.MessageCount = AppMessage.FindCountByAppID(ID);
app.SaveAsync();
}
}
ts.Commit();
return list;
}
}
}
#endregion
}
}

View File

@ -1,25 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
{
@ -30,11 +15,9 @@ namespace AntJob.Data.Entity
static JobLog()
{
// 累加字段
//var df = Meta.Factory.AdditionalFields;
//df.Add(__.AppID);
// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<TimeModule>();
var df = Meta.Factory.AdditionalFields;
df.Add(__.Error);
df.Add(__.Times);
}
/// <summary>验证数据,通过抛出异常的方式提示验证失败。</summary>
@ -44,93 +27,39 @@ namespace AntJob.Data.Entity
// 如果没有脏数据,则不需要进行任何处理
if (!HasDirty) return;
// 在新插入数据或者修改了指定字段时进行修正
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
var len = _.Data.Length;
if (len > 0 && !Data.IsNullOrEmpty() && Data.Length > len) throw new InvalidOperationException($"字段[{__.Data}]超长");
// 截断错误信息,避免过长
len = _.Message.Length;
if (!Message.IsNullOrEmpty() && len > 0 && Message.Length > len) Message = Message.Substring(0, len);
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化JobLog[作业日志]数据……");
// var entity = new JobLog();
// entity.ID = 0;
// entity.AppID = 0;
// entity.JobID = 0;
// entity.LinkID = 0;
// entity.Client = "abc";
// entity.Start = DateTime.Now;
// entity.End = DateTime.Now;
// entity.Row = 0;
// entity.Step = 0;
// entity.BatchSize = 0;
// entity.Offset = 0;
// entity.Total = 0;
// entity.Success = 0;
// entity.Error = 0;
// entity.Times = 0;
// entity.Speed = 0;
// entity.FetchSpeed = 0;
// entity.Cost = 0;
// entity.FullCost = 0;
// entity.Status = 0;
// entity.MsgCount = 0;
// entity.Server = "abc";
// entity.ProcessID = 0;
// entity.ThreadID = 0;
// entity.Key = "abc";
// entity.Data = "abc";
// entity.Message = "abc";
// entity.CreateTime = DateTime.Now;
// entity.UpdateTime = DateTime.Now;
// entity.Insert();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化JobLog[作业日志]数据!");
//}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
#endregion
#region
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
public App App { get { return Extends.Get(nameof(App), k => App.FindByID(AppID)); } }
public App App => Extends.Get(nameof(App), k => App.FindByID(AppID));
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID, typeof(App), "ID")]
public String AppName { get { return App?.Name; } }
[Map(__.AppID)]
public String AppName => App?.Name;
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
public Job Job { get { return Extends.Get(nameof(Job), k => Job.FindByID(JobID)); } }
public Job Job => Extends.Get(nameof(Job), k => Job.FindByID(JobID));
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("作业")]
[Map(__.JobID, typeof(Job), "ID")]
public String JobName { get { return Job?.Name; } }
[Map(__.JobID)]
public String JobName => Job?.Name;
#endregion
#region
@ -141,33 +70,122 @@ namespace AntJob.Data.Entity
{
if (id <= 0) return null;
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id);
// 单对象缓存
return Meta.SingleCache[id];
//return Find(_.ID == id);
}
/// <summary>根据应用、客户端、状态查找</summary>
/// <param name="appid">应用</param>
/// <param name="client">客户端</param>
/// <summary>根据编号、作业、状态查找</summary>
/// <param name="id">编号</param>
/// <param name="jobid">作业</param>
/// <param name="status">状态</param>
/// <returns>实体列表</returns>
public static IList<JobLog> FindAllByAppIDAndClientAndStatus(Int32 appid, String client, Int32 status)
public static IList<JobLog> FindAllByIDAndJobIDAndStatus(Int32 id, Int32 jobid, JobStatus status)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.AppID == appid && e.Client == client && e.Status == status);
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.ID == id && e.JobID == jobid && e.Status == status);
return FindAll(_.AppID == appid & _.Client == client & _.Status == status);
return FindAll(_.ID == id & _.JobID == jobid & _.Status == status);
}
/// <summary>根据编号、状态查找</summary>
/// <param name="id">编号</param>
/// <param name="status">状态</param>
/// <returns>实体列表</returns>
public static IList<JobLog> FindAllByIDAndStatus(Int32 id, JobStatus status)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.ID == id && e.Status == status);
return FindAll(_.ID == id & _.Status == status);
}
public static IList<JobLog> FindAllByAppID(Int32 appid)
{
if (appid == 0) return new List<JobLog>();
return FindAll(_.AppID == appid);
}
public static IList<JobLog> FindAllByJobId(Int32 jobid)
{
if (jobid == 0) return new List<JobLog>();
return FindAll(_.JobID == jobid);
}
public static Int32 FindCountByJobId(Int32 jobid) => (Int32)FindCount(_.JobID == jobid);
/// <summary>查找作业下小于指定创建时间的最后一个任务</summary>
/// <param name="jobid"></param>
/// <param name="createTime"></param>
/// <returns></returns>
public static JobLog FindLastByJobId(Int32 jobid, DateTime createTime)
{
return FindAll(_.JobID == jobid & _.CreateTime < createTime, _.CreateTime.Desc(), null, 0, 1).FirstOrDefault();
}
#endregion
#region
public static IEnumerable<JobLog> Search(Int32 id, Int32 appid, Int32 jobid, JobStatus status, DateTime start, DateTime end, String client, String key, PageParameter p)
{
var exp = new WhereExpression();
if (id > 0) exp &= _.ID == id;
if (appid > 0) exp &= _.AppID == appid;
if (jobid > 0) exp &= _.JobID == jobid;
if (status >= JobStatus.) exp &= _.Status == status;
if (!client.IsNullOrEmpty()) exp &= _.Client == client;
if (!key.IsNullOrEmpty()) exp &= _.Data.Contains(key) | _.Message.Contains(key) | _.Key == key;
exp &= _.Start.Between(start, end);
return FindAll(exp, p);
}
/// <summary>获取该任务下特定状态的任务项</summary>
/// <param name="taskid"></param>
/// <param name="end"></param>
/// <param name="maxRetry"></param>
/// <param name="stats"></param>
/// <param name="count">要申请的任务个数</param>
/// <returns></returns>
public static IList<JobLog> Search(Int32 taskid, DateTime end, Int32 maxRetry, JobStatus[] stats, Int32 count)
{
var exp = new WhereExpression();
if (taskid > 0) exp &= _.JobID == taskid;
if (maxRetry > 0) exp &= _.Times < maxRetry;
exp &= _.Status.In(stats);
exp &= _.UpdateTime >= DateTime.Now.AddDays(-7);
if (end > DateTime.MinValue)
{
exp &= _.UpdateTime < end;
}
// 限制任务的错误次数,避免无限执行
exp &= _.Error < 32;
return FindAll(exp, _.ID.Asc(), null, 0, count);
}
#endregion
#region
/// <summary>重置</summary>
public void Reset()
{
Row = 0;
Total = 0;
Success = 0;
Status = JobStatus.;
Save();
}
/// <summary>删除该ID及以前的作业项</summary>
/// <param name="jobid"></param>
/// <param name="maxid"></param>
/// <returns></returns>
public static Int32 DeleteByID(Int32 jobid, Int32 maxid) => maxid <= 0 ? 0 : Delete(_.JobID == jobid & _.ID <= maxid);
public static Int32 DeleteByAppId(Int32 appid) => Delete(_.AppID == appid);
#endregion
}
}

View File

@ -1,24 +1,9 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
@ -29,10 +14,6 @@ namespace AntJob.Data.Entity
#region
static JobError()
{
// 累加字段
//var df = Meta.Factory.AdditionalFields;
//df.Add(__.AppID);
// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<TimeModule>();
}
@ -44,94 +25,36 @@ namespace AntJob.Data.Entity
// 如果没有脏数据,则不需要进行任何处理
if (!HasDirty) return;
// 在新插入数据或者修改了指定字段时进行修正
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
// 截断错误信息,避免过长
var len = _.Message.Length;
if (!Message.IsNullOrEmpty() && len > 0 && Message.Length > len) Message = Message.Substring(0, len);
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化JobError[作业错误]数据……");
// var entity = new JobError();
// entity.ID = 0;
// entity.AppID = 0;
// entity.JobID = 0;
// entity.JobLogID = 0;
// entity.Client = "abc";
// entity.Start = DateTime.Now;
// entity.End = DateTime.Now;
// entity.Row = 0;
// entity.Step = 0;
// entity.BatchSize = 0;
// entity.Key = "abc";
// entity.Data = "abc";
// entity.Server = "abc";
// entity.ProcessID = 0;
// entity.ThreadID = 0;
// entity.ErrorCode = "abc";
// entity.Message = "abc";
// entity.CreateTime = DateTime.Now;
// entity.UpdateTime = DateTime.Now;
// entity.Insert();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化JobError[作业错误]数据!");
//}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
#endregion
#region
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
public App App { get { return Extends.Get(nameof(App), k => App.FindByID(AppID)); } }
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID, typeof(App), "ID")]
public String AppName { get { return App?.Name; } }
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
public Job Job { get { return Extends.Get(nameof(Job), k => Job.FindByID(JobID)); } }
public Job Job => Extends.Get(nameof(Job), k => Job.FindByID(JobID));
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("作业")]
[Map(__.JobID, typeof(Job), "ID")]
public String JobName { get { return Job?.Name; } }
/// <summary>作业项</summary>
[XmlIgnore]
//[ScriptIgnore]
public JobLog JobLog { get { return Extends.Get(nameof(JobLog), k => JobLog.FindByID(JobLogID)); } }
[Map(__.JobID)]
public String JobName => Job?.Name;
/// <summary>作业项</summary>
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("作业项")]
[Map(__.JobLogID, typeof(JobLog), "ID")]
public Int32 JobLogID { get { return JobLog != null ? JobLog.ID : 0; } }
public App App => Extends.Get(nameof(App), k => App.FindByID(AppID));
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID)]
public String AppName => App?.Name;
#endregion
#region
@ -142,66 +65,41 @@ namespace AntJob.Data.Entity
{
if (id <= 0) return null;
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id);
// 单对象缓存
return Meta.SingleCache[id];
//return Find(_.ID == id);
}
/// <summary>根据编号、应用查找</summary>
/// <param name="id">编号</param>
/// <param name="appid">应用</param>
/// <returns>实体列表</returns>
public static IList<JobError> FindAllByIDAndAppID(Int32 id, Int32 appid)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.ID == id && e.AppID == appid);
return FindAll(_.ID == id & _.AppID == appid);
}
/// <summary>根据编号、作业查找</summary>
/// <param name="id">编号</param>
/// <param name="jobid">作业</param>
/// <returns>实体列表</returns>
public static IList<JobError> FindAllByIDAndJobID(Int32 id, Int32 jobid)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.ID == id && e.JobID == jobid);
return FindAll(_.ID == id & _.JobID == jobid);
}
/// <summary>根据数据键查找</summary>
/// <param name="key">数据键</param>
/// <returns>实体列表</returns>
public static IList<JobError> FindAllByKey(String key)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Key == key);
return FindAll(_.Key == key);
}
/// <summary>根据错误码查找</summary>
/// <param name="errorcode">错误码</param>
/// <returns>实体列表</returns>
public static IList<JobError> FindAllByErrorCode(String errorcode)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.ErrorCode == errorcode);
return FindAll(_.ErrorCode == errorcode);
return Find(_.ID == id);
}
#endregion
#region
public static IEnumerable<JobError> Search(Int32 appid, Int32 jobid, String client, DateTime start, DateTime end, String key, PageParameter p)
{
var exp = new WhereExpression();
if (appid > 0) exp &= _.AppID == appid;
if (jobid > 0) exp &= _.JobID == jobid;
if (!client.IsNullOrEmpty()) exp &= _.Client == client;
if (!key.IsNullOrEmpty()) exp &= _.Message.Contains(key);
exp &= _.Start.Between(start, end);
return FindAll(exp, p);
}
public static IList<JobError> SearchByAppID(Int32 appid, PageParameter p)
{
if (appid == 0) return new List<JobError>();
return FindAll(_.AppID == appid, p);
}
public static IList<JobError> FindAllByJobId(Int32 jobid)
{
if (jobid == 0) return new List<JobError>();
return FindAll(_.JobID == jobid);
}
#endregion
#region
public static Int32 DeleteByAppId(Int32 appid) => Delete(_.AppID == appid);
#endregion
}
}

View File

@ -1,24 +1,9 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
@ -37,84 +22,20 @@ namespace AntJob.Data.Entity
Meta.Modules.Add<TimeModule>();
Meta.Modules.Add<IPModule>();
}
/// <summary>验证数据,通过抛出异常的方式提示验证失败。</summary>
/// <param name="isNew">是否插入</param>
public override void Valid(Boolean isNew)
{
// 如果没有脏数据,则不需要进行任何处理
if (!HasDirty) return;
// 在新插入数据或者修改了指定字段时进行修正
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
//if (isNew && !Dirtys[nameof(CreateIP)]) nameof(CreateIP) = ManageProvider.UserHost;
//if (!Dirtys[nameof(UpdateIP)]) nameof(UpdateIP) = ManageProvider.UserHost;
// 检查唯一索引
// CheckExist(isNew, __.Instance);
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化AppOnline[应用在线]数据……");
// var entity = new AppOnline();
// entity.ID = 0;
// entity.AppID = 0;
// entity.Instance = "abc";
// entity.Client = "abc";
// entity.Name = "abc";
// entity.Version = "abc";
// entity.Server = "abc";
// entity.Logs = 0;
// entity.Total = 0;
// entity.Success = 0;
// entity.Error = 0;
// entity.Cost = 0;
// entity.Speed = 0;
// entity.LastKey = "abc";
// entity.CreateTime = DateTime.Now;
// entity.CreateIP = "abc";
// entity.UpdateTime = DateTime.Now;
// entity.UpdateIP = "abc";
// entity.Insert();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化AppOnline[应用在线]数据!");
//}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
#endregion
#region
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
public App App { get { return Extends.Get(nameof(App), k => App.FindByID(AppID)); } }
public App App => Extends.Get(nameof(App), k => App.FindByID(AppID));
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID, typeof(App), "ID")]
public String AppName { get { return App?.Name; } }
[Map(__.AppID)]
public String AppName => App?.Name;
#endregion
#region
@ -125,13 +46,7 @@ namespace AntJob.Data.Entity
{
if (id <= 0) return null;
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id);
// 单对象缓存
return Meta.SingleCache[id];
//return Find(_.ID == id);
return Find(_.ID == id);
}
/// <summary>根据实例查找</summary>
@ -145,17 +60,6 @@ namespace AntJob.Data.Entity
return Find(_.Instance == instance);
}
/// <summary>根据客户端查找</summary>
/// <param name="client">客户端</param>
/// <returns>实体列表</returns>
public static IList<AppOnline> FindAllByClient(String client)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.Client == client);
return FindAll(_.Client == client);
}
/// <summary>根据应用查找</summary>
/// <param name="appid">应用</param>
/// <returns>实体列表</returns>
@ -169,6 +73,38 @@ namespace AntJob.Data.Entity
#endregion
#region
public static IEnumerable<AppOnline> Search(Int32 appid, DateTime start, DateTime end, String key, PageParameter p)
{
var exp = new WhereExpression();
if (appid > 0) exp &= _.AppID == appid.ToInt();
if (!key.IsNullOrEmpty()) exp &= _.Name.Contains(key) | _.Instance.Contains(key);
exp &= _.CreateTime.Between(start, end);
return FindAll(exp, p);
}
/// <summary>
/// 获取UpdateTime距now减指定参数分钟的数据
/// </summary>
/// <param name="norunMin"></param>
/// <returns></returns>
public static IList<AppOnline> GetOnlines(Int32 norunMin = 10)
{
var now = DateTime.Now;
var exp = new WhereExpression();
exp &= _.UpdateTime <= now.AddMinutes(-norunMin);
return FindAll(exp);
}
public static IList<AppOnline> SearchByAppID(Int32 appid, PageParameter p)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.FindAll(e => e.AppID == appid);
return FindAll(_.AppID == appid, p);
}
#endregion
#region

View File

@ -1,24 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
@ -29,86 +15,35 @@ namespace AntJob.Data.Entity
#region
static AppMessage()
{
// 累加字段
//var df = Meta.Factory.AdditionalFields;
//df.Add(__.AppID);
// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<TimeModule>();
}
/// <summary>验证数据,通过抛出异常的方式提示验证失败。</summary>
/// <param name="isNew">是否插入</param>
public override void Valid(Boolean isNew)
{
// 如果没有脏数据,则不需要进行任何处理
if (!HasDirty) return;
// 在新插入数据或者修改了指定字段时进行修正
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化AppMessage[应用消息]数据……");
// var entity = new AppMessage();
// entity.ID = 0;
// entity.AppID = 0;
// entity.JobID = 0;
// entity.Topic = "abc";
// entity.Data = "abc";
// entity.CreateTime = DateTime.Now;
// entity.UpdateTime = DateTime.Now;
// entity.Insert();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化AppMessage[应用消息]数据!");
//}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
#endregion
#region
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
public App App { get { return Extends.Get(nameof(App), k => App.FindByID(AppID)); } }
public App App => Extends.Get(nameof(App), k => App.FindByID(AppID));
/// <summary>应用</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("应用")]
[Map(__.AppID, typeof(App), "ID")]
public String AppName { get { return App?.Name; } }
[Map(__.AppID)]
public String AppName => App?.Name;
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
public Job Job { get { return Extends.Get(nameof(Job), k => Job.FindByID(JobID)); } }
public Job Job => Extends.Get(nameof(Job), k => Job.FindByID(JobID));
/// <summary>作业</summary>
[XmlIgnore]
//[ScriptIgnore]
[DisplayName("作业")]
[Map(__.JobID, typeof(Job), "ID")]
public String JobName { get { return Job?.Name; } }
[Map(__.JobID)]
public String JobName => Job?.Name;
#endregion
#region
@ -119,20 +54,89 @@ namespace AntJob.Data.Entity
{
if (id <= 0) return null;
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id);
return Find(_.ID == id);
}
// 单对象缓存
return Meta.SingleCache[id];
/// <summary>
/// 查询当前应用的消息数
/// </summary>
/// <param name="jobid"></param>
/// <returns></returns>
public static Int32 FindCountByAppID(Int32 appid)
{
if (appid == 0) return 0;
//return Find(_.ID == id);
return (Int32)FindCount(_.AppID == appid);
}
/// <summary>
/// 查询当前作业的消息数
/// </summary>
/// <param name="appid"></param>
/// <param name="topic"></param>
/// <returns></returns>
public static Int32 FindCountByAppIDAndTopic(Int32 appid, String topic)
{
if (appid == 0) return 0;
return (Int32)FindCount(_.AppID == appid & _.Topic == topic);
}
#endregion
#region
/// <summary>高级查询</summary>
/// <param name="model">模型</param>
/// <param name="page">分页</param>
/// <returns></returns>
public static IEnumerable<AppMessage> Search(Int32 appid, Int32 jobid, DateTime start, DateTime end, String key, PageParameter p)
{
var exp = new WhereExpression();
if (appid > 0) exp &= _.AppID == appid;
if (jobid > 0) exp &= _.JobID == jobid;
if (!key.IsNullOrEmpty()) exp &= _.Topic.Contains(key) | _.Data.Contains(key);
exp &= _.UpdateTime.Between(start, end);
return FindAll(exp, p);
}
#endregion
#region
/// <summary>根据应用、主题、以及总数</summary>
/// <param name="appid"></param>
/// <param name="topic"></param>
/// <param name="count"></param>
/// <returns></returns>
public static IList<AppMessage> GetTopic(Int32 appid, String topic, DateTime time, Int32 count)
{
return FindAll(_.AppID == appid & _.Topic == topic & _.UpdateTime <= time, _.UpdateTime.Asc(), null, 0, count);
}
/// <summary>去重过滤</summary>
/// <param name="appid"></param>
/// <param name="topic"></param>
/// <param name="messages"></param>
/// <returns></returns>
public static String[] Filter(Int32 appid, String topic, String[] messages)
{
var list = new List<String>();
// 分批核查是否存在
for (var i = 0; i < messages.Length; i += 100)
{
var batch = messages.Skip(i).Take(100).ToList();
var ms = FindAll(_.AppID == appid & _.Topic == topic & _.Data.In(batch));
// 去掉找到的项
foreach (var item in ms)
{
batch.Remove(item.Data);
}
// 剩下的加入结果
if (batch.Count > 0) list.AddRange(batch);
}
return list.ToArray();
}
#endregion
}
}

View File

@ -1,25 +1,9 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Xml.Serialization;
using NewLife;
using NewLife.Data;
using NewLife.Log;
using NewLife.Model;
using NewLife.Reflection;
using NewLife.Threading;
using NewLife.Web;
using XCode;
using XCode.Cache;
using XCode.Configuration;
using XCode.DataAccessLayer;
using XCode.Membership;
namespace AntJob.Data.Entity
{
@ -30,13 +14,13 @@ namespace AntJob.Data.Entity
static App()
{
// 累加字段
//var df = Meta.Factory.AdditionalFields;
//df.Add(__.JobCount);
var df = Meta.Factory.AdditionalFields;
//df.Add(__.MessageCount);
// 过滤器 UserModule、TimeModule、IPModule
Meta.Modules.Add<UserModule>();
Meta.Modules.Add<TimeModule>();
Meta.Modules.Add<IPModule>();
//Meta.Modules.Add<UserModule>();
//Meta.Modules.Add<TimeModule>();
//Meta.Modules.Add<IPModule>();
// 单对象缓存
var sc = Meta.SingleCache;
@ -54,72 +38,15 @@ namespace AntJob.Data.Entity
// 这里验证参数范围,建议抛出参数异常,指定参数名,前端用户界面可以捕获参数异常并聚焦到对应的参数输入框
if (Name.IsNullOrEmpty()) throw new ArgumentNullException(nameof(Name), "名称不能为空!");
// 在新插入数据或者修改了指定字段时进行修正
// 处理当前已登录用户信息可以由UserModule过滤器代劳
/*var user = ManageProvider.User;
if (user != null)
{
if (isNew && !Dirtys[nameof(CreateUserID)) nameof(CreateUserID) = user.ID;
if (!Dirtys[nameof(UpdateUserID)]) nameof(UpdateUserID) = user.ID;
}*/
//if (isNew && !Dirtys[nameof(CreateTime)]) nameof(CreateTime) = DateTime.Now;
//if (!Dirtys[nameof(UpdateTime)]) nameof(UpdateTime) = DateTime.Now;
//if (isNew && !Dirtys[nameof(CreateIP)]) nameof(CreateIP) = ManageProvider.UserHost;
//if (!Dirtys[nameof(UpdateIP)]) nameof(UpdateIP) = ManageProvider.UserHost;
// 检查唯一索引
// CheckExist(isNew, __.Name);
if (!isNew && JobCount == 0 && !Dirtys[nameof(JobCount)]) JobCount = Job.FindCountByAppID(ID);
if (!isNew && MessageCount == 0 && !Dirtys[nameof(MessageCount)]) MessageCount = AppMessage.FindCountByAppID(ID);
}
///// <summary>首次连接数据库时初始化数据,仅用于实体类重载,用户不应该调用该方法</summary>
//[EditorBrowsable(EditorBrowsableState.Never)]
//protected override void InitData()
//{
// // InitData一般用于当数据表没有数据时添加一些默认数据该实体类的任何第一次数据库操作都会触发该方法默认异步调用
// if (Meta.Session.Count > 0) return;
// if (XTrace.Debug) XTrace.WriteLine("开始初始化App[应用系统]数据……");
// var entity = new App();
// entity.ID = 0;
// entity.Name = "abc";
// entity.DisplayName = "abc";
// entity.Secret = "abc";
// entity.Category = "abc";
// entity.Version = "abc";
// entity.Enable = true;
// entity.JobCount = 0;
// entity.MessageCount = 0;
// entity.Remark = "abc";
// entity.CreateUserID = 0;
// entity.CreateUser = "abc";
// entity.CreateTime = DateTime.Now;
// entity.CreateIP = "abc";
// entity.UpdateUserID = 0;
// entity.UpdateUser = "abc";
// entity.UpdateTime = DateTime.Now;
// entity.UpdateIP = "abc";
// entity.Insert();
// if (XTrace.Debug) XTrace.WriteLine("完成初始化App[应用系统]数据!");
//}
///// <summary>已重载。基类先调用Valid(true)验证数据然后在事务保护内调用OnInsert</summary>
///// <returns></returns>
//public override Int32 Insert()
//{
// return base.Insert();
//}
///// <summary>已重载。在事务保护范围内处理业务位于Valid之后</summary>
///// <returns></returns>
//protected override Int32 OnDelete()
//{
// return base.OnDelete();
//}
#endregion
#region
/// <summary>作业集合</summary>
[XmlIgnore]
public IList<Job> Jobs => Extends.Get(nameof(Jobs), k => Job.FindAllByAppID(ID));
#endregion
#region
@ -130,13 +57,8 @@ namespace AntJob.Data.Entity
{
if (id <= 0) return null;
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.ID == id);
// 单对象缓存
return Meta.SingleCache[id];
//return Find(_.ID == id);
}
/// <summary>根据名称查找</summary>
@ -144,20 +66,32 @@ namespace AntJob.Data.Entity
/// <returns>实体对象</returns>
public static App FindByName(String name)
{
// 实体缓存
if (Meta.Session.Count < 1000) return Meta.Cache.Find(e => e.Name == name);
// 单对象缓存
//return Meta.SingleCache.GetItemWithSlaveKey(name) as App;
return Find(_.Name == name);
return Meta.SingleCache.GetItemWithSlaveKey(name) as App;
}
#endregion
#region
public static IEnumerable<App> Search(String category, Boolean? enable, String key, PageParameter p)
{
var exp = new WhereExpression();
if (enable != null) exp &= _.Enable == enable;
if (!category.IsNullOrEmpty()) exp &= _.Category == category;
if (!key.IsNullOrEmpty()) exp &= _.Name.Contains(key) | _.DisplayName.Contains(key);
return FindAll(exp, p);
}
#endregion
#region
/// <summary>分类单对象缓存</summary>
static FieldCache<App> CategoryCache = new FieldCache<App>(_.Category);
/// <summary>查询所有分类缓存</summary>
/// <returns></returns>
public static IDictionary<String, String> FindAllCategoryByCache() => CategoryCache.FindAllName();
#endregion
}
}

View File

@ -1,24 +0,0 @@
namespace AntJob.Data
{
/// <summary>作业状态</summary>
public enum JobStatus
{
/// <summary>就绪</summary>
= 0,
/// <summary>抽取中</summary>
= 1,
/// <summary>处理中</summary>
= 2,
/// <summary>错误</summary>
= 3,
/// <summary>已完成</summary>
= 4,
/// <summary>已取消</summary>
= 5,
}
}

View File

@ -0,0 +1,169 @@
<Project ToolsVersion="15.0" DefaultTargets="Build" 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>
<ProductVersion>
</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{A9E0597C-E818-4B33-8AC3-BE134D68B78E}</ProjectGuid>
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Stardust.Web</RootNamespace>
<AssemblyName>Stardust.Web</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<UseIISExpress>true</UseIISExpress>
<Use64BitIISExpress />
<IISExpressSSLPort />
<IISExpressAnonymousAuthentication />
<IISExpressWindowsAuthentication />
<IISExpressUseClassicPipelineMode />
<UseGlobalApplicationHostFile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="NewLife.Core, Version=8.1.7012.14587, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NewLife.Core.8.1.2019.314\lib\net45\NewLife.Core.dll</HintPath>
</Reference>
<Reference Include="NewLife.Cube, Version=2.6.7008.35938, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NewLife.Cube.2.6.7008.35938\lib\net45\NewLife.Cube.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Core" />
<Reference Include="System.Web.Extensions" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.6\lib\net45\System.Web.Helpers.dll</HintPath>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.6\lib\net45\System.Web.Mvc.dll</HintPath>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.6\lib\net45\System.Web.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.6\lib\net45\System.Web.WebPages.dll</HintPath>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.6\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web" />
<Reference Include="System.Xml" />
<Reference Include="System.Configuration" />
<Reference Include="XCode, Version=9.11.7012.14589, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\NewLife.XCode.9.11.2019.314\lib\net45\XCode.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Content Include="Global.asax" />
</ItemGroup>
<ItemGroup>
<Compile Include="Areas\Ant\AntAreaRegistration.cs" />
<Compile Include="Areas\Ant\Controllers\AppController.cs" />
<Compile Include="Areas\Ant\Controllers\AppOnlineController.cs" />
<Compile Include="Areas\Ant\Controllers\JobController.cs" />
<Compile Include="Areas\Ant\Controllers\JobErrorController.cs" />
<Compile Include="Areas\Ant\Controllers\JobLogController.cs" />
<Compile Include="Areas\Ant\Controllers\AppMessageController.cs" />
<Compile Include="Global.asax.cs">
<DependentUpon>Global.asax</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Areas\Ant\Views\AppOnline\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\AppOnline\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\App\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\App\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\App\_List_Toolbar_Batch.cshtml" />
<Content Include="Areas\Ant\Views\JobError\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\JobError\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\JobLog\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\JobLog\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\JobLog\_List_Toolbar_Batch.cshtml" />
<Content Include="Areas\Ant\Views\AppMessage\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\AppMessage\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\Job\_List_Data.cshtml" />
<Content Include="Areas\Ant\Views\Job\_List_Search.cshtml" />
<Content Include="Areas\Ant\Views\Job\_List_Toolbar_Batch.cshtml" />
<Content Include="Areas\Ant\Views\web.config" />
<None Include="packages.config" />
<Content Include="Web.config" />
<None Include="Web.Debug.config">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.Release.config">
<DependentUpon>Web.config</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="Areas\Ant\Views\Shared\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AntJob.Data\AntJob.Data.csproj">
<Project>{01639cc1-1574-4ae1-bbc5-e0538fa5c44c}</Project>
<Name>AntJob.Data</Name>
</ProjectReference>
<ProjectReference Include="..\AntJob\AntJob.csproj">
<Project>{717a3c5a-c4e9-4e85-bb57-916ed6fac936}</Project>
<Name>AntJob</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
<ProjectExtensions>
<VisualStudio>
<FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
<WebProjectProperties>
<UseIIS>True</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>20092</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:20092/</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>
</CustomServerUrl>
<SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
</WebProjectProperties>
</FlavorProperties>
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,11 @@
using System.ComponentModel;
using NewLife.Cube;
namespace AntJob.Web.Areas.Ant
{
/// <summary>蚂蚁调度</summary>
[DisplayName("蚂蚁调度")]
public class AntAreaRegistration : AreaRegistrationBase
{
}
}

View File

@ -0,0 +1,119 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
using XCode.Membership;
using JobX = AntJob.Data.Entity.Job;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>应用系统</summary>
[DisplayName("应用系统")]
public class AppController : EntityController<App>
{
static AppController()
{
MenuOrder = 100;
App.Meta.Modules.Add<UserModule>();
App.Meta.Modules.Add<TimeModule>();
App.Meta.Modules.Add<IPModule>();
}
protected override Int32 OnUpdate(App entity)
{
entity.JobCount = JobX.FindCountByAppID(entity.ID);
return base.OnUpdate(entity);
}
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<App> Search(Pager p)
{
var id = p["id"].ToInt(-1);
if (id > 0)
{
var list = new List<App>();
var entity = App.FindByID(id);
if (entity != null) list.Add(entity);
return list;
}
return App.Search(p["category"], p["Enable"]?.ToBoolean(), p["q"], p);
}
/// <summary>
/// 重置应用
/// 清空作业、作业项、统计、错误,开始时间设为本月一号
/// </summary>
/// <returns></returns>
public ActionResult ResetApp()
{
var ids = Request["keys"].SplitAsInt(",");
if (!ids.Any()) return JsonRefresh("未选中项!");
var now = DateTime.Now;
foreach (var appid in ids)
{
// 清空作业
var jobs = JobX.FindAllByAppID2(appid);
foreach (var job in jobs)
{
job.Start = new DateTime(now.Year, now.Month, 1);
job.ResetOther();
}
// 清空日志
var jobItems = JobLog.FindAllByAppID(appid);
foreach (var jobItem in jobItems)
{
jobItem.Delete();
}
// 清空错误
JobError.DeleteByAppId(appid);
}
return JsonRefresh("操作完毕!");
}
/// <summary>启用禁用任务</summary>
/// <param name="id"></param>
/// <param name="enable"></param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult Set(Int32 id = 0, Boolean enable = true)
{
if (id > 0)
{
var dt = App.FindByID(id);
if (dt == null) throw new ArgumentNullException(nameof(id), "找不到任务 " + id);
dt.Enable = enable;
dt.Save();
}
else
{
var ids = Request["keys"].SplitAsInt(",");
foreach (var item in ids)
{
var dt = App.FindByID(item);
if (dt != null && dt.Enable != enable)
{
dt.Enable = enable;
dt.Save();
}
}
}
return JsonRefresh("操作成功!");
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.Mvc;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>应用消息</summary>
[DisplayName("应用消息")]
public class AppMessageController : EntityController<AppMessage>
{
static AppMessageController() => MenuOrder = 49;
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<AppMessage> Search(Pager p)
{
var appid = p["appid"].ToInt(-1);
var JobID = p["JobID"].ToInt(-1);
var start = p["dtStart"].ToDateTime();
var end = p["dtEnd"].ToDateTime();
var status = p["Status"];
return AppMessage.Search(appid, JobID, start, end, p["q"], p);
}
}
}

View File

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>应用在线</summary>
[DisplayName("应用在线")]
public class AppOnlineController : EntityController<AppOnline>
{
static AppOnlineController()
{
MenuOrder = 90;
AppOnline.Meta.Table.DataTable.InsertOnly = true;
}
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<AppOnline> Search(Pager p)
{
var appid = p["appid"].ToInt(-1);
var start = p["dtStart"].ToDateTime();
var end = p["dtEnd"].ToDateTime();
return AppOnline.Search(appid, start, end, p["q"], p);
}
}
}

View File

@ -0,0 +1,184 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Web.Mvc;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
using XCode;
using XCode.Membership;
using JobX = AntJob.Data.Entity.Job;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>作业</summary>
[DisplayName("作业")]
public class JobController : EntityController<JobX>
{
public JobController()
{
PageSetting.EnableAdd = false;
}
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<JobX> Search(Pager p)
{
var appid = p["appid"].ToInt(-1);
var ID = p["ID"].ToInt(-1);
var start = p["dtStart"].ToDateTime();
var end = p["dtEnd"].ToDateTime();
var mode = p["Mode"].ToInt(-1);
return JobX.Search(ID, appid, start, end, mode, p["q"], p);
}
static JobController()
{
var list = ListFields;
list.RemoveField("Type");
list.RemoveField("CreateUserID");
list.RemoveField("CreateTime");
list.RemoveField("CreateIP");
list.RemoveField("UpdateUserID");
list.RemoveField("UpdateIP");
MenuOrder = 80;
}
/// <summary>启用禁用任务</summary>
/// <param name="id"></param>
/// <param name="enable"></param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult Set(Int32 id = 0, Boolean enable = true)
{
if (id > 0)
{
var dt = JobX.FindByID(id);
if (dt == null) throw new ArgumentNullException(nameof(id), "找不到任务 " + id);
dt.Enable = enable;
dt.Save();
}
else
{
var ids = Request["keys"].SplitAsInt(",");
foreach (var item in ids)
{
var dt = JobX.FindByID(item);
if (dt != null && dt.Enable != enable)
{
dt.Enable = enable;
dt.Save();
}
}
}
return JsonRefresh("操作成功!");
}
/// <summary>
/// 重置时间
/// </summary>
/// <param name="days"></param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult ResetTime(Int32 days = 0)
{
var ids = Request["keys"].SplitAsInt(",");
var st = Request["sday"].ToDateTime();
var et = Request["eday"].ToDateTime();
Parallel.ForEach(ids, k =>
{
var dt = JobX.FindByID(k);
dt?.ResetTime(days, st, et);
});
return JsonRefresh("操作成功!");
}
/// <summary>完全重置</summary>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult AllReset()
{
var ids = Request["keys"].SplitAsInt(",");
Parallel.ForEach(ids, k =>
{
var dt = JobX.FindByID(k);
dt?.ResetOther();
});
return JsonRefresh("操作成功!");
}
/// <summary>设置偏移</summary>
/// <param name="offset">偏移</param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult SetOffset(Int32 offset)
{
if (offset < 0) offset = 15;
var ids = Request["keys"].SplitAsInt(",");
Parallel.ForEach(ids, k =>
{
var dt = JobX.FindByID(k);
if (dt != null)
{
dt.Offset = offset;
dt.Save();
}
});
return JsonRefresh("操作成功!");
}
/// <summary>清空错误数</summary>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult ClearError()
{
var ids = Request["keys"].SplitAsInt(",");
Parallel.ForEach(ids, k =>
{
var dt = JobX.FindByID(k);
if (dt != null)
{
dt.Error = 0;
dt.Save();
}
});
return JsonRefresh("操作成功!");
}
/// <summary>清空错误项</summary>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult ClearErrorItem()
{
var ids = Request["keys"].SplitAsInt(",");
Parallel.ForEach(ids, k =>
{
var dt = JobError.FindAllByJobId(k);
if (dt.Count < 20000)
{
dt.Delete(true);
}
var dtt = JobX.FindByID(k);
if (dtt != null)
{
dtt.Error = 0;
dtt.Save();
}
});
return JsonRefresh("操作成功!");
}
}
}

View File

@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>作业错误</summary>
[DisplayName("作业错误")]
public class JobErrorController : EntityController<JobError>
{
static JobErrorController() => MenuOrder = 60;
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<JobError> Search(Pager p)
{
var appid = p["appid"].ToInt(-1);
var jobid = p["JobID"].ToInt(-1);
var start = p["dtStart"].ToDateTime();
var end = p["dtEnd"].ToDateTime();
var client = p["Client"];
return JobError.Search(appid, jobid, client, start, end, p["q"], p);
}
}
}

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.Mvc;
using AntJob.Data.Entity;
using NewLife.Cube;
using NewLife.Web;
using XCode.Membership;
namespace AntJob.Web.Areas.Ant.Controllers
{
/// <summary>作业日志</summary>
[DisplayName("作业日志")]
public class JobLogController : EntityController<JobLog>
{
static JobLogController()
{
MenuOrder = 70;
JobLog.Meta.Modules.Add<TimeModule>();
}
/// <summary>搜索数据集</summary>
/// <param name="p"></param>
/// <returns></returns>
protected override IEnumerable<JobLog> Search(Pager p)
{
var id = p["id"].ToInt(-1);
var jobid = p["JobID"].ToInt(-1);
var appid = p["AppID"].ToInt(-1);
var status = (JobStatus)p["Status"].ToInt(-1);
var start = p["dtStart"].ToDateTime();
var end = p["dtEnd"].ToDateTime();
var client = p["Client"];
return JobLog.Search(id, appid, jobid, status, start, end, client, p["q"], p);
}
/// <summary>修改状态</summary>
/// <param name="id"></param>
/// <returns></returns>
[EntityAuthorize(PermissionFlags.Update)]
public ActionResult Set(Int32 id = 0)
{
if (id > 0)
{
var dt = JobLog.FindByID(id);
if (dt == null) throw new ArgumentNullException(nameof(id), "找不到任务 " + id);
dt.Status = JobStatus.;
dt.Row = 0;
if (dt.Times >= 10)
{
dt.Times = 0;
}
dt.Save();
}
else
{
var ids = Request["keys"].SplitAsInt(",");
foreach (var item in ids)
{
var dt = JobLog.FindByID(item);
if (dt != null)
{
dt.Status = JobStatus.;
dt.Row = 0;
if (dt.Times >= 10)
{
dt.Times = 0;
}
dt.Save();
}
}
}
return JsonRefresh("操作成功!");
}
}
}

View File

@ -0,0 +1,71 @@
@model IList<AntJob.Data.Entity.App>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as IList<FieldItem>;
var enableSelect = this.EnableSelect();
var provider = ManageProvider.Provider;
}
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
@if (enableSelect)
{
<th class="text-center" style="width:10px;"><input type="checkbox" id="chkAll" title="全选" /></th>
}
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Name"))">名称</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("DisplayName"))">显示名</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("MessageCount"))">消息数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("JobCount"))">作业数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Enable"))">启用</a></th>
<th class="text-center">消息</th>
<th class="text-center">在线</th>
<th class="text-center">任务</th>
<th class="text-center">错误</th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center" style="min-width:100px;">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
<tr>
@if (enableSelect)
{
<td class="text-center"><input type="checkbox" name="keys" value="@entity.ID" /></td>
}
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td class="text-center"><a href="@Url.Action("Index","Job",new {appid=entity.ID})">@entity.Name</a></td>
<td>@entity.DisplayName</td>
<td>@entity.MessageCount.ToString("n0")</td>
<td class="text-center"><a href="@Url.Action("Index","Job",new {appid=entity.ID})">@entity.JobCount</a></td>
<td class="text-center">
<a href="App/Set/@entity.ID?enable=@(entity.Enable?"false":"true")" data-action="action"><i class="glyphicon glyphicon-@(entity.Enable ? "ok" : "remove")" style="color: @(entity.Enable ? "green" : "red");"></i></a>
</td>
<td class="text-center"><a href="@Url.Action("Index","JobMessage",new {appid=entity.ID})">消息</a></td>
<td class="text-center"><a href="@Url.Action("Index","AppOnline",new {appid=entity.ID})">在线</a></td>
<td class="text-center"><a href="@Url.Action("Index","JobItem",new {appid=entity.ID})">任务</a></td>
<td class="text-center"><a href="@Url.Action("Index","JobError",new {appid=entity.ID})">错误</a></td>
<td>@entity.UpdateTime.ToFullString("")</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,13 @@
@using AntJob.Data.Entity;
@{
var page = ViewBag.Page as Pager;
var dic = new Dictionary<Int32, String>();
dic.Add(1, "启用");
dic.Add(0, "禁用");
}
<div class="form-group">
<label for="enable" class="control-label">状态:</label>
@Html.ForDropDownList("enable", dic, Request["enable"], "全部", true)
<label for="category" class="control-label">分类:</label>
@Html.ForDropDownList("category", AntJob.Data.Entity.App.FindAllCategoryByCache(), Request["category"], "全部", true)
</div>

View File

@ -0,0 +1,20 @@
@using NewLife.Common;
@using System.Collections.Generic;
@{
var user = ViewBag.User as IUser ?? User.Identity as IUser;
var fact = ViewBag.Factory as IEntityOperate;
var enableSelect = this.EnableSelect();
}
@if (enableSelect)
{
<button type="button" class="btn btn-warning btn-sm" data-action="action" data-url="@Url.Action("ResetApp")" data-fields="keys" disabled>
<span title="清空作业、作业项、统计、错误,开始时间设为本月一号">重置</span>
</button>
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("Set")?enable=true" data-fields="keys" disabled>
批量启用
</button>
<button type="button" class="btn btn-error btn-sm" data-action="action" data-url="@Url.Action("Set")?enable=false" data-fields="keys" disabled>
批量禁用
</button>
}

View File

@ -0,0 +1,59 @@
@model IList<AntJob.Data.Entity.AppMessage>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as IList<FieldItem>;
var enableSelect = this.EnableSelect();
//var provider = ManageProvider.Provider;
}
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
@if (enableSelect)
{
<th class="text-center" style="width:10px;"><input type="checkbox" id="chkAll" title="全选" /></th>
}
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("AppID"))">应用</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("JobID"))">作业</a></th>
<th class="text-center" title="主题。区分作业下多种资源"><a href="@Html.Raw(page.GetSortUrl("Topic"))">主题</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("CreateTime"))">创建时间</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center" style="min-width:100px;">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
<tr>
@if (enableSelect)
{
<td class="text-center"><input type="checkbox" name="keys" value="@entity.ID" /></td>
}
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td><a href="App?ID=@entity.AppID">@entity.AppName</a></td>
<td><a href="Job?ID=@entity.JobID">@entity.JobName</a></td>
<td>@entity.Topic</td>
<td>@entity.CreateTime.ToFullString("")</td>
<td>@entity.UpdateTime.ToFullString("")</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,11 @@
@using AntJob.Data.Entity;
@using AntJob.Data;
@{
var page = ViewBag.Page as Pager;
var apps = AntJob.Data.Entity.App.FindAllWithCache().Cast<IEntity>().ToList();
}
<div class="form-group">
<label for="status" class="control-label">应用:</label>
@Html.ForDropDownList("appid", apps, "全部", true)
</div>
@Html.Partial("_DateRange")

View File

@ -0,0 +1,73 @@
@model IList<AntJob.Data.Entity.AppOnline>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as IList<FieldItem>;
var enableSelect = this.EnableSelect();
//var provider = ManageProvider.Provider;
}
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
@if (enableSelect)
{
<th class="text-center" style="width:10px;"><input type="checkbox" id="chkAll" title="全选" /></th>
}
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("AppID"))">应用</a></th>
<th class="text-center" title="客户端。IP加进程"><a href="@Html.Raw(page.GetSortUrl("Client"))">客户端</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Version"))">版本</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Server"))">服务端</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Items"))">任务数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Total"))">总数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Success"))">成功</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Error"))">错误</a></th>
<th class="text-center" title="耗时。总耗时,秒"><a href="@Html.Raw(page.GetSortUrl("Cost"))">耗时</a></th>
<th class="text-center" title="速度。每秒处理数"><a href="@Html.Raw(page.GetSortUrl("Speed"))">速度</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("CreateTime"))">创建时间</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center" style="min-width:100px;">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
<tr>
@if (enableSelect)
{
<td class="text-center"><input type="checkbox" name="keys" value="@entity.ID" /></td>
}
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td><a href="App?ID=@entity.AppID">@entity.AppName</a></td>
<td title="@entity.Name">@entity.Client</td>
<td>@entity.Version</td>
<td>@entity.Server</td>
<td class="text-right"><a href="@Url.Action("Index","JobItem",new {appid=entity.AppID,client=entity.Client})">@entity.Logs.ToString("n0")</a></td>
<td class="text-right">@entity.Total.ToString("n0")</td>
<td class="text-right">@entity.Success.ToString("n0")</td>
<td class="text-right"><a href="@Url.Action("Index","JobError",new {appid=entity.AppID,client=entity.Client})">@entity.Error.ToString("n0")</a></td>
<td class="text-right">@TimeSpan.FromSeconds(entity.Cost)</td>
<td class="text-right">@entity.Speed.ToString("n0")</td>
<td>@entity.CreateTime.ToFullString("")</td>
<td>@entity.UpdateTime.ToFullString("")</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,4 @@
@{
var page = ViewBag.Page as Pager;
}
@Html.Partial("_DateRange")

View File

@ -0,0 +1,135 @@
@model IList<AntJob.Data.Entity.Job>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@using AntJob.Data.Entity;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as List<FieldItem>;
var fk = fact.Unique;
var enableSelect = this.EnableSelect();
var appid = page["appid"].ToInt();
}
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
@if (enableSelect)
{
<th class="text-center" style="width:10px;"><input type="checkbox" id="chkAll" title="全选" /></th>
}
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Name"))">名称</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("DisplayName"))">显示名</a></th>
@if (appid == 0)
{
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("AppName"))">应用</a></th>
}
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Start"))" title="@Job._.Start.Description">开始时间</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("End"))" title="@Job._.End.Description">结束</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Step"))" title="@Job._.Step.Description">步进</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("BatchSize"))" title="@Job._.BatchSize.Description">批大小</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Offset"))" title="@Job._.Offset.Description">偏移</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("MaxTask"))" title="@Job._.MaxTask.Description">并行</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Total"))">总数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Success"))">成功</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Error"))">错误</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Times"))">次数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Speed"))">速度</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Enable"))">启用</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
<th class="text-center">消息</th>
<th class="text-center">任务</th>
<th class="text-center">统计</th>
<th class="text-center">错误</th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
var st = entity.Start.ToFullString("");
if (entity.Start.Date == DateTime.Now.Date) { st = entity.Start.ToString("HH:mm:ss"); }
if (entity.Mode == AntJob.JobModes.Message) { st = "{0}/{1}".F(entity.Topic, entity.MessageCount); }
var ut = entity.UpdateTime.ToFullString("");
if (entity.UpdateTime.Date == DateTime.Now.Date) { ut = entity.UpdateTime.ToString("HH:mm:ss"); }
<tr>
@if (enableSelect)
{
<td class="text-center"><input type="checkbox" name="keys" value="@entity[fk.Name]" /></td>
}
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td><a href="JobItem?JobID=@entity.ID">@entity.Name</a></td>
<td title="@entity.Description">@entity.DisplayName</td>
@if (appid == 0)
{
<td>@entity.AppName</td>
}
<td class="text-center" title="@entity.Mode.GetDescription()">
@if (entity.Mode == AntJob.JobModes.Alarm)
{
<b>@st</b>
}
else
{
@st
}
</td>
<td class="text-center">@entity.End.ToFullString("")</td>
<td class="text-right">
@if (entity.Mode != AntJob.JobModes.Message)
{
if (entity.StepRate > 0)
{
<span style="color:lightseagreen">
@TimeSpan.FromSeconds(entity.Step)
</span>
}
else
{
@TimeSpan.FromSeconds(entity.Step)
}
}
</td>
<td class="text-right">@entity.BatchSize.ToString("n0")</td>
<td class="text-right">
@if (entity.Mode != AntJob.JobModes.Message)
{
@TimeSpan.FromSeconds(entity.Offset)
}
</td>
<td class="text-right">@entity.MaxTask.ToString("n0")</td>
<td class="text-right">@entity.Total.ToString("n0")</td>
<td class="text-right">@entity.Success.ToString("n0")</td>
<td class="text-right" title="@entity.MaxError">@entity.Error.ToString("n0")</td>
<td class="text-right">@entity.Times.ToString("n0")</td>
<td class="text-right">@entity.Speed.ToString("n0")</td>
<td class="text-center">
<a href="Job/Set/@entity.ID?enable=@(entity.Enable?"false":"true")" data-action="action"><i class="glyphicon glyphicon-@(entity.Enable ? "ok" : "remove")" style="color: @(entity.Enable ? "green" : "red");"></i></a>
</td>
<td class="text-center">@ut</td>
<td class="text-center"><a href="JobMessage?JobID=@entity.ID">消息</a></td>
<td class="text-center"><a href="JobItem?JobID=@entity.ID">任务</a></td>
<td class="text-center"><a href="JobStat?JobID=@entity.ID">统计</a></td>
<td class="text-center"><a href="JobError?JobID=@entity.ID">错误</a></td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,12 @@
@{
var page = ViewBag.Page as Pager;
var Mode = new Dictionary<Int32, String>();
Mode.Add(1, "时间片调度");
Mode.Add(2, "定时调度");
Mode.Add(3, "消息调度");
}
<div class="form-group">
<label for="Mode" class="control-label">调度模式:</label>
@Html.ForDropDownList("Mode", Mode, Request["Mode"], "全部", true)
</div>

View File

@ -0,0 +1,43 @@
@using NewLife.Common;
@using System.Collections.Generic;
@{
var user = ViewBag.User as IUser ?? User.Identity as IUser;
var fact = ViewBag.Factory as IEntityOperate;
var enableSelect = this.EnableSelect();
var sdic = new Dictionary<String, String>();
sdic["strFormat"] = "yyyy-MM-dd HH:mm:ss";
sdic["dname"] = "sday";
sdic["title"] = "开始";
var edic = new Dictionary<String, String>();
edic["strFormat"] = "yyyy-MM-dd HH:mm:ss";
edic["dname"] = "eday";
edic["title"] = "结束";
}
@if (enableSelect)
{
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("Set")?enable=true" data-fields="keys" disabled>
批量启用
</button>
<button type="button" class="btn btn-error btn-sm" data-action="action" data-url="@Url.Action("Set")?enable=false" data-fields="keys" disabled>
批量禁用
</button>
<input type="number" name="days" value="-1" title="重置到多少天之前(-1表示直接清空开始时间" style="width:40px" />
<button type="button" class="btn btn-warning btn-sm" data-action="action" data-url="@Url.Action("ResetTime")" data-fields="keys,days" disabled>
重置时间
</button>
<button type="button" class="btn btn-danger btn-sm" data-action="action" data-url="@Url.Action("AllReset")" data-fi data-fields="keys" disabled>
重置其它
</button>
<input type="number" name="offset" value="15" title="距离实际时间秒数" style="width:40px" />
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("SetOffset")" data-fields="keys,offset" disabled>
设置偏移
</button>
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("ClearError")" data-fields="keys" disabled>
清空错误数
</button>
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("ClearStepRate")" data-fields="keys" disabled title="将步进率置为0">
清空步进率
</button>
}

View File

@ -0,0 +1,66 @@
@model IList<AntJob.Data.Entity.JobError>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc;
@using System.Web.Mvc.Ajax;
@using System.Web.Mvc.Html;
@using System.Web.Routing;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as List<FieldItem>;
}
<style>
.OverFlow {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 400px;
}
</style>
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("AppID"))">应用</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("TaskItemID"))">任务项</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Row"))">行</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Step"))">步进</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("BatchSize"))">批大小</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Key"))">数据键</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("ErrorCode"))">错误码</a></th>
<th class="text-center">内容</th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center" style="min-width:100px;">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
<tr>
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td><a href="Job?AppID=@entity.AppID">@entity.AppName</a></td>
<td><a href="JobLog?JobID=@entity.JobID">@entity.JobName</a></td>
<td class="text-right">@entity.Row.ToString("n0")</td>
<td class="text-right">@entity.Step.ToString("n0")</td>
<td class="text-right">@entity.BatchSize.ToString("n0")</td>
<td>@entity.Key</td>
<td>@entity.ErrorCode</td>
<td class="OverFlow" title="@entity.Message">@entity.Message</td>
<td>@entity.UpdateTime.ToFullString("")</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,10 @@
@using AntJob.Data.Entity;
@{
var page = ViewBag.Page as Pager;
var apps = AntJob.Data.Entity.App.FindAllWithCache().Cast<IEntity>().ToList();
}
<div class="form-group">
<label for="status" class="control-label">应用:</label>
@Html.ForDropDownList("appid", apps, "全部", true)
</div>
@Html.Partial("_DateRange")

View File

@ -0,0 +1,105 @@
@model IList<AntJob.Data.Entity.JobLog>
@using NewLife;
@using NewLife.Web;
@using XCode;
@using XCode.Configuration;
@using System.Web.Mvc.Html;
@using AntJob.Data.Entity;
@using AntJob;
@{
var fact = ViewBag.Factory as IEntityOperate;
var page = ViewBag.Page as Pager;
var fields = ViewBag.Fields as List<FieldItem>;
var fk = fact.Unique;
var enableSelect = this.EnableSelect();
}
<table class="table table-bordered table-hover table-striped table-condensed">
<thead>
<tr>
@if (enableSelect)
{
<th class="text-center" style="width:10px;"><input type="checkbox" id="chkAll" title="全选" /></th>
}
<th class="text-center hidden-md hidden-sm hidden-xs"><a href="@Html.Raw(page.GetSortUrl("ID"))">编号</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("TaskID"))">任务</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Start"))">开始</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Client"))">客户端</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Row"))">行</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Step"))">步进</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("BatchSize"))">批大小</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Total"))">总数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Success"))">成功</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Error"))">错误</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Times"))">次数</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Speed"))">速度</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("FetchSpeed"))">抽取速度</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Cost"))">耗时</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("FullCost"))">全耗时</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Status"))">状态</a></th>
<th class="text-center"><a href="@Html.Raw(page.GetSortUrl("Key"))">最后键</a></th>
<th class="text-center" style="min-width:134px;"><a href="@Html.Raw(page.GetSortUrl("UpdateTime"))">更新时间</a></th>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<th class="text-center">操作</th>
}
</tr>
</thead>
<tbody>
@foreach (var entity in Model)
{
var cls = "";
switch (entity.Status)
{
case JobStatus.就绪:
break;
case JobStatus.抽取中:
cls = "warning";
break;
case JobStatus.处理中:
cls = "info";
break;
case JobStatus.错误:
cls = "danger";
break;
case JobStatus.完成:
cls = "success";
break;
case JobStatus.取消:
cls = "active";
break;
default:
break;
}
<tr>
@if (enableSelect)
{
<td class="text-center"><input type="checkbox" name="keys" value="@entity[fk.Name]" /></td>
}
<td class="text-center hidden-md hidden-sm hidden-xs">@entity.ID</td>
<td class="text-center"><a href="Job?ID=@entity.JobID">@entity.JobName</a></td>
<td>@entity.Start.ToFullString("")</td>
<td>@entity.Client</td>
<td class="text-right">@entity.Row.ToString("n0")</td>
<td class="text-right">@entity.Step.ToString("n0")</td>
<td class="text-right">@entity.BatchSize.ToString("n0")</td>
<td class="text-right">@entity.Total.ToString("n0")</td>
<td class="text-right" style="color:forestgreen"><b>@entity.Success.ToString("n0")</b></td>
<td class="text-right" style="color:red">@entity.Error.ToString("n0")</td>
<td class="text-right">@entity.Times.ToString("n0")</td>
<td class="text-right">@entity.Speed.ToString("n0")</td>
<td class="text-right">@entity.FetchSpeed.ToString("n0")</td>
<td class="text-right">@TimeSpan.FromSeconds(entity.Cost)</td>
<td class="text-right">@TimeSpan.FromSeconds(entity.FullCost)</td>
<td class="text-center @cls">@entity.Status</td>
<td>@entity.Key</td>
<td>@entity.UpdateTime.ToFullString("")</td>
@if (this.Has(PermissionFlags.Detail, PermissionFlags.Update, PermissionFlags.Delete))
{
<td class="text-center">
@Html.Partial("_List_Data_Action", (Object)entity)
</td>
}
</tr>
}
</tbody>
</table>

View File

@ -0,0 +1,9 @@
@using AntJob;
@{
var page = ViewBag.Page as Pager;
}
<div class="form-group">
<label for="status" class="control-label">状态:</label>
@Html.ForDropDownList("status", System.EnumHelper.GetDescriptions(typeof(JobStatus)), Request["status"], "全部", true)
</div>
@Html.Partial("_DateRange")

View File

@ -0,0 +1,11 @@
@using NewLife.Common;
@using System.Collections.Generic;
@{
var enableSelect = this.EnableSelect();
}
@if (enableSelect)
{
<button type="button" class="btn btn-success btn-sm" data-action="action" data-url="@Url.Action("Set")" data-fields="keys" disabled>
重置
</button>
}

View File

@ -0,0 +1,41 @@
<?xml version="1.0"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="AntJob.Web" />
<add namespace="NewLife" />
<add namespace="NewLife.Cube" />
<add namespace="NewLife.Reflection" />
<add namespace="NewLife.Web" />
<add namespace="XCode" />
<add namespace="XCode.Membership" />
</namespaces>
</pages>
</system.web.webPages.razor>
<appSettings>
<add key="webpages:Enabled" value="false" />
</appSettings>
<system.webServer>
<handlers>
<remove name="BlockViewHandler"/>
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
</handlers>
</system.webServer>
</configuration>

1
AntJob.Web/Global.asax Normal file
View File

@ -0,0 +1 @@
<%@ Application Codebehind="Global.asax.cs" Inherits="AntJob.Web.MvcApplication" Language="C#" %>

35
AntJob.Web/Global.asax.cs Normal file
View File

@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace AntJob.Web
{
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
filters.Add(new HandleErrorAttribute());
}
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "CubeHome", action = "Index", id = UrlParameter.Optional }
);
}
}
}

View File

@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过下列特性集
// 控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("蚂蚁调度管理平台")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AntJob.Web")]
[assembly: AssemblyCopyright("Copyright © 新生命开发团队 2019")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 会使此程序集中的类型
// 对 COM 组件不可见。如果需要
// 从 COM 访问此程序集中的某个类型,请针对该类型将 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于 typelib 的 ID
[assembly: Guid("a9e0597c-e818-4b33-8ac3-be134d68b78e")]
// 程序集的版本信息由下列四个值组成:
//
// 主版本
// 次版本
// 内部版本号
// 修订版本
//
// 可以指定所有值,也可以使用“修订号”和“内部版本号”的默认值,
// 方法是按如下所示使用 "*":
[assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyFileVersion("1.0.2019.0331")]

109
AntJob.Web/Web.config Normal file
View File

@ -0,0 +1,109 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
</sectionGroup>
</configSections>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="RouteDebugger:Enabled" value="true" />
</appSettings>
<connectionStrings>
<!--<add name="Membership" connectionString="Data Source=..\Data\Membership.db;TablePrefix=school_;" providerName="Sqlite"/>-->
<!--<add name="Membership" connectionString="Server=.;Integrated Security=SSPI;Database=Membership" providerName="System.Data.SqlClient" />-->
<!--<add name="Membership" connectionString="Server=.;user id=sa;password=sa;Database=Membership" providerName="System.Data.SqlClient" />-->
<!--<add name="Membership" connectionString="Server=localhost;Port=3306;Database=Membership;Uid=root;Pwd=root" providerName="MySql.Data.MySqlClient"/>-->
<!--<add name="Membership" connectionString="Data Source=tcp://10.10.20.104/ORCL;User Id=scott;Password=tiger;" providerName="System.Data.OracleClient"/>-->
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5" />
<pages>
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
</namespaces>
</pages>
<httpRuntime executionTimeout="15" />
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<!--<handlers>
<add name="json" verb="GET,HEAD" path="*.json" type="System.Web.StaticFileHandler"/>
<add name="all" path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
</handlers>-->
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
<add name="X-Powered-By" value="NewLife.Cube http://www.NewLifeX.com" />
</customHeaders>
</httpProtocol>
<staticContent>
<remove fileExtension=".woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
<mimeMap fileExtension=".woff2" mimeType="application/x-font-woff" />
<remove fileExtension=".ttf" />
<mimeMap fileExtension=".ttf" mimeType="application/x-font-truetype" />
<remove fileExtension=".svg" />
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
<remove fileExtension=".otf" />
<mimeMap fileExtension=".otf" mimeType="application/x-font-opentype" />
<remove fileExtension=".eot" />
<mimeMap fileExtension=".eot" mimeType="application/vnd.ms-fontobject" />
<!--静态缓存使用浏览器缓存超时时间之内不发出Http请求F5除外-->
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="240:00:00" />
</staticContent>
</system.webServer>
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.6.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="NewLife" />
<add namespace="NewLife.Cube" />
<add namespace="NewLife.Reflection" />
<add namespace="NewLife.Web" />
<add namespace="XCode" />
<add namespace="XCode.Membership" />
</namespaces>
</pages>
</system.web.webPages.razor>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="1.0.0.0-5.2.6.0" newVersion="5.2.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.AspNet.Mvc" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.Mvc.zh-Hans" version="5.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.Razor" version="3.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.Razor.zh-Hans" version="3.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.WebPages" version="3.2.6" targetFramework="net461" />
<package id="Microsoft.AspNet.WebPages.zh-Hans" version="3.2.6" targetFramework="net461" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net461" />
<package id="NewLife.Core" version="8.1.2019.314" targetFramework="net461" />
<package id="NewLife.Cube" version="2.6.7008.35938" targetFramework="net461" />
<package id="NewLife.XCode" version="9.11.2019.314" targetFramework="net461" />
</packages>