1. 加入Quartz
2. 地圖總覽
This commit is contained in:
parent
f7e2e9c123
commit
18e4fa4b57
25
SolarPower/Controllers/MapOverviewController.cs
Normal file
25
SolarPower/Controllers/MapOverviewController.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using SolarPower.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Controllers
|
||||||
|
{
|
||||||
|
public class MapOverviewController : Controller
|
||||||
|
{
|
||||||
|
public IActionResult Index()
|
||||||
|
{
|
||||||
|
return View();
|
||||||
|
}
|
||||||
|
|
||||||
|
//public async Task<ApiResult<MapOverview>> GetAllDate()
|
||||||
|
//{
|
||||||
|
// ApiResult<MapOverview> apiResult = new ApiResult<MapOverview>();
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
11
SolarPower/Models/MapOverview.cs
Normal file
11
SolarPower/Models/MapOverview.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Models
|
||||||
|
{
|
||||||
|
public class MapOverview
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
46
SolarPower/Quartz/JobSchedule.cs
Normal file
46
SolarPower/Quartz/JobSchedule.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Quartz
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Job調度中間對象
|
||||||
|
/// </summary>
|
||||||
|
public class JobSchedule
|
||||||
|
{
|
||||||
|
public JobSchedule(Type jobType, string cronExpression)
|
||||||
|
{
|
||||||
|
this.JobType = jobType ?? throw new ArgumentNullException(nameof(jobType));
|
||||||
|
CronExpression = cronExpression ?? throw new ArgumentNullException(nameof(cronExpression));
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Job類型
|
||||||
|
/// </summary>
|
||||||
|
public Type JobType { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Cron表達式
|
||||||
|
/// </summary>
|
||||||
|
public string CronExpression { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Job狀態
|
||||||
|
/// </summary>
|
||||||
|
public JobStatus JobStatu { get; set; } = JobStatus.Init;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Job運行狀態
|
||||||
|
/// </summary>
|
||||||
|
public enum JobStatus : byte
|
||||||
|
{
|
||||||
|
[Description("初始化")]
|
||||||
|
Init = 0,
|
||||||
|
[Description("運行中")]
|
||||||
|
Running = 1,
|
||||||
|
[Description("調度中")]
|
||||||
|
Scheduling = 2,
|
||||||
|
[Description("已停止")]
|
||||||
|
Stopped = 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
148
SolarPower/Quartz/Jobs/OperationScheduleJob.cs
Normal file
148
SolarPower/Quartz/Jobs/OperationScheduleJob.cs
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Quartz;
|
||||||
|
using SolarPower.Models;
|
||||||
|
using SolarPower.Repository.Interface;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Quartz.Jobs
|
||||||
|
{
|
||||||
|
[DisallowConcurrentExecution]
|
||||||
|
public class OperationScheduleJob : IJob
|
||||||
|
{
|
||||||
|
private readonly ILogger<OperationScheduleJob> logger;
|
||||||
|
private IOperationRepository operationRepository;
|
||||||
|
|
||||||
|
public OperationScheduleJob(ILogger<OperationScheduleJob> logger, IOperationRepository operationRepository)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.operationRepository = operationRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Execute(IJobExecutionContext context)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var getTime = await operationRepository.GetOperationSchedules();
|
||||||
|
foreach (var a in getTime)
|
||||||
|
{
|
||||||
|
DateTime Updatedtime;
|
||||||
|
if (a.ScheduleType == 0)//日
|
||||||
|
{
|
||||||
|
Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum);
|
||||||
|
}
|
||||||
|
else if (a.ScheduleType == 1)//周
|
||||||
|
{
|
||||||
|
Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum * 7);
|
||||||
|
}
|
||||||
|
else if (a.ScheduleType == 2)//月
|
||||||
|
{
|
||||||
|
Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum);
|
||||||
|
}
|
||||||
|
else if (a.ScheduleType == 3)//季
|
||||||
|
{
|
||||||
|
Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum * 3);
|
||||||
|
}
|
||||||
|
else // 年
|
||||||
|
{
|
||||||
|
Updatedtime = Convert.ToDateTime(a.StartTime).AddYears(a.ScheduleNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Updatedtime < DateTime.Now)
|
||||||
|
{
|
||||||
|
var now = DateTime.Now.ToString("yyyy-MM-dd");
|
||||||
|
var finalid = await operationRepository.GetCurrentSerialNumber("operation_plan_create", $"PowerStationId = {a.PowerStationId} AND CreatedAt LIKE '%{now}%'");
|
||||||
|
var newSerialNumber = GetLastSerialNumber(finalid);
|
||||||
|
var OperationPlan = new OperationCreatePlan()
|
||||||
|
{
|
||||||
|
EmailType = a.EmailType,
|
||||||
|
ScheduleNum = a.ScheduleNum,
|
||||||
|
Description = a.Description,
|
||||||
|
WorkDay = a.WorkDay,
|
||||||
|
ScheduleType = a.ScheduleType,
|
||||||
|
SerialNumber = newSerialNumber,
|
||||||
|
StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
|
||||||
|
PowerStationId = a.PowerStationId,
|
||||||
|
Type = a.Type,
|
||||||
|
PlanId = DateTime.Now.ToString("yyyyMMdd") + newSerialNumber,
|
||||||
|
CreatedBy = a.CreatedBy
|
||||||
|
};
|
||||||
|
List<string> properties = new List<string>()
|
||||||
|
{
|
||||||
|
"EmailType",
|
||||||
|
"ScheduleNum",
|
||||||
|
"Description",
|
||||||
|
"WorkDay",
|
||||||
|
"ScheduleType",
|
||||||
|
"SerialNumber",
|
||||||
|
"StartTime",
|
||||||
|
"PowerStationId",
|
||||||
|
"Type",
|
||||||
|
"PlanId",
|
||||||
|
"CreatedBy"
|
||||||
|
};
|
||||||
|
await operationRepository.AddOperationPlan(OperationPlan, properties);
|
||||||
|
|
||||||
|
var record = new PlanToRecord()
|
||||||
|
{
|
||||||
|
WorkType = a.Type,
|
||||||
|
PowerStationId = a.PowerStationId,
|
||||||
|
StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
|
||||||
|
CreatedBy = a.CreatedBy,
|
||||||
|
EndTime = Updatedtime.AddDays(a.WorkDay).ToString("yyyy-MM-dd hh:mm:ss")
|
||||||
|
};
|
||||||
|
List<string> properties2 = new List<string>()
|
||||||
|
{
|
||||||
|
"WorkType",
|
||||||
|
"PowerStationId",
|
||||||
|
"StartTime",
|
||||||
|
"CreatedBy",
|
||||||
|
"EndTime"
|
||||||
|
};
|
||||||
|
await operationRepository.AddToRecord(record, properties2);
|
||||||
|
var operation = await operationRepository.GetOneOperation(a.Id);
|
||||||
|
await operationRepository.DeleteOneByIdWithCustomTable(a.Id, "operation_plan_create");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception exception)
|
||||||
|
{
|
||||||
|
logger.LogError("【{0}】{1}", nameof(logger), exception.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 取得最新的流水號
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="current">當前的</param>
|
||||||
|
/// <param name="pad"></param>
|
||||||
|
/// <param name="direction">0: PadLeft;1: PadRight</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string GetLastSerialNumber(string current = "", int pad = 4, byte direction = 0)
|
||||||
|
{
|
||||||
|
var tempSerialNumber = 0;
|
||||||
|
if (!string.IsNullOrEmpty(current))
|
||||||
|
{
|
||||||
|
tempSerialNumber = Convert.ToInt32(current) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tempSerialNumber = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (direction == 0)
|
||||||
|
{
|
||||||
|
return tempSerialNumber.ToString().Trim().PadLeft(pad, '0');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return tempSerialNumber.ToString().Trim().PadRight(pad, '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
SolarPower/Quartz/SingletonJobFactory.cs
Normal file
27
SolarPower/Quartz/SingletonJobFactory.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Spi;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Quartz
|
||||||
|
{
|
||||||
|
public class SingletonJobFactory: IJobFactory
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
public SingletonJobFactory(IServiceProvider serviceProvider)
|
||||||
|
{
|
||||||
|
_serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
|
||||||
|
}
|
||||||
|
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
|
||||||
|
{
|
||||||
|
return _serviceProvider.GetRequiredService(bundle.JobDetail.JobType) as IJob;
|
||||||
|
}
|
||||||
|
public void ReturnJob(IJob job)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,179 +0,0 @@
|
|||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using SolarPower.Models;
|
|
||||||
using SolarPower.Repository.Interface;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace SolarPower.Services.Implement
|
|
||||||
{
|
|
||||||
public class OperationScheduleBackgroundService : IHostedService, IDisposable
|
|
||||||
{
|
|
||||||
static Timer _timer;
|
|
||||||
private int time_interval = 30; //查詢間隔(秒)
|
|
||||||
private readonly ILogger<OperationScheduleBackgroundService> _log;
|
|
||||||
private int execCount = 0;
|
|
||||||
private readonly IOperationRepository operationRepository;
|
|
||||||
|
|
||||||
public OperationScheduleBackgroundService(ILogger<OperationScheduleBackgroundService> log,
|
|
||||||
IOperationRepository operationRepository
|
|
||||||
)
|
|
||||||
{
|
|
||||||
this.operationRepository = operationRepository;
|
|
||||||
this._log = log;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
_timer?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
_timer = new Timer(DoWork, null,
|
|
||||||
TimeSpan.Zero,
|
|
||||||
TimeSpan.FromSeconds(time_interval));
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async void DoWork(object state)
|
|
||||||
{
|
|
||||||
//利用 Interlocked 計數防止重複執行
|
|
||||||
if (execCount <= 0)
|
|
||||||
{
|
|
||||||
Interlocked.Increment(ref execCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (execCount == 1)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var getTime = await operationRepository.GetOperationSchedules();
|
|
||||||
foreach (OperationCreatePlanModal a in getTime)
|
|
||||||
{
|
|
||||||
DateTime Updatedtime;
|
|
||||||
if (a.ScheduleType == 0)//日
|
|
||||||
{
|
|
||||||
Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum);
|
|
||||||
}
|
|
||||||
else if (a.ScheduleType == 1)//周
|
|
||||||
{
|
|
||||||
Updatedtime = Convert.ToDateTime(a.StartTime).AddDays(a.ScheduleNum * 7);
|
|
||||||
}
|
|
||||||
else if (a.ScheduleType == 2)//月
|
|
||||||
{
|
|
||||||
Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum);
|
|
||||||
}
|
|
||||||
else if (a.ScheduleType == 3)//季
|
|
||||||
{
|
|
||||||
Updatedtime = Convert.ToDateTime(a.StartTime).AddMonths(a.ScheduleNum * 3);
|
|
||||||
}
|
|
||||||
else // 年
|
|
||||||
{
|
|
||||||
Updatedtime = Convert.ToDateTime(a.StartTime).AddYears(a.ScheduleNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Updatedtime < DateTime.Now)
|
|
||||||
{
|
|
||||||
var now = DateTime.Now.ToString("yyyy-MM-dd");
|
|
||||||
var finalid = await operationRepository.GetCurrentSerialNumber("operation_plan_create", $"PowerStationId = {a.PowerStationId} AND CreatedAt LIKE '%{now}%'");
|
|
||||||
var newSerialNumber = GetLastSerialNumber(finalid);
|
|
||||||
var OperationPlan = new OperationCreatePlan()
|
|
||||||
{
|
|
||||||
EmailType = a.EmailType,
|
|
||||||
ScheduleNum = a.ScheduleNum,
|
|
||||||
Description = a.Description,
|
|
||||||
WorkDay = a.WorkDay,
|
|
||||||
ScheduleType = a.ScheduleType,
|
|
||||||
SerialNumber = newSerialNumber,
|
|
||||||
StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
|
|
||||||
PowerStationId = a.PowerStationId,
|
|
||||||
Type = a.Type,
|
|
||||||
PlanId = DateTime.Now.ToString("yyyyMMdd") + newSerialNumber,
|
|
||||||
CreatedBy = a.CreatedBy
|
|
||||||
};
|
|
||||||
List<string> properties = new List<string>()
|
|
||||||
{
|
|
||||||
"EmailType",
|
|
||||||
"ScheduleNum",
|
|
||||||
"Description",
|
|
||||||
"WorkDay",
|
|
||||||
"ScheduleType",
|
|
||||||
"SerialNumber",
|
|
||||||
"StartTime",
|
|
||||||
"PowerStationId",
|
|
||||||
"Type",
|
|
||||||
"PlanId",
|
|
||||||
"CreatedBy"
|
|
||||||
};
|
|
||||||
await operationRepository.AddOperationPlan(OperationPlan, properties);
|
|
||||||
|
|
||||||
var record = new PlanToRecord()
|
|
||||||
{
|
|
||||||
WorkType = a.Type,
|
|
||||||
PowerStationId = a.PowerStationId,
|
|
||||||
StartTime = Updatedtime.ToString("yyyy-MM-dd hh:mm:ss"),
|
|
||||||
CreatedBy = a.CreatedBy,
|
|
||||||
EndTime = Updatedtime.AddDays(a.WorkDay).ToString("yyyy-MM-dd hh:mm:ss")
|
|
||||||
};
|
|
||||||
List<string> properties2 = new List<string>()
|
|
||||||
{
|
|
||||||
"WorkType",
|
|
||||||
"PowerStationId",
|
|
||||||
"StartTime",
|
|
||||||
"CreatedBy",
|
|
||||||
"EndTime"
|
|
||||||
};
|
|
||||||
await operationRepository.AddToRecord(record, properties2);
|
|
||||||
var operation = await operationRepository.GetOneOperation(a.Id);
|
|
||||||
await operationRepository.DeleteOneByIdWithCustomTable(a.Id, "operation_plan_create");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_log.LogError("【OperationScheduleService】 - " + ex.Message);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Interlocked.Decrement(ref execCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetLastSerialNumber(string current = "", int pad = 4, byte direction = 0)
|
|
||||||
{
|
|
||||||
var tempSerialNumber = 0;
|
|
||||||
if (!string.IsNullOrEmpty(current))
|
|
||||||
{
|
|
||||||
tempSerialNumber = Convert.ToInt32(current) + 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
tempSerialNumber = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction == 0)
|
|
||||||
{
|
|
||||||
return tempSerialNumber.ToString().Trim().PadLeft(pad, '0');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return tempSerialNumber.ToString().Trim().PadRight(pad, '0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
//調整Timer為永不觸發,停用定期排程
|
|
||||||
_timer?.Change(Timeout.Infinite, 0);
|
|
||||||
return Task.CompletedTask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
71
SolarPower/Services/Implement/QuartzHostedService.cs
Normal file
71
SolarPower/Services/Implement/QuartzHostedService.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Spi;
|
||||||
|
using SolarPower.Models;
|
||||||
|
using SolarPower.Quartz;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace SolarPower.Services.Implement
|
||||||
|
{
|
||||||
|
public class QuartzHostedService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ISchedulerFactory _schedulerFactory;
|
||||||
|
private readonly IJobFactory _jobFactory;
|
||||||
|
private readonly IEnumerable<JobSchedule> _jobSchedules;
|
||||||
|
public QuartzHostedService(ISchedulerFactory schedulerFactory, IJobFactory jobFactory, IEnumerable<JobSchedule> jobSchedules)
|
||||||
|
{
|
||||||
|
_schedulerFactory = schedulerFactory ?? throw new ArgumentNullException(nameof(schedulerFactory));
|
||||||
|
_jobFactory = jobFactory ?? throw new ArgumentNullException(nameof(jobFactory));
|
||||||
|
_jobSchedules = jobSchedules ?? throw new ArgumentNullException(nameof(jobSchedules));
|
||||||
|
}
|
||||||
|
public IScheduler Scheduler { get; set; }
|
||||||
|
public async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
Scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
|
||||||
|
Scheduler.JobFactory = _jobFactory;
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
var job = CreateJob(jobSchedule);
|
||||||
|
var trigger = CreateTrigger(jobSchedule);
|
||||||
|
await Scheduler.ScheduleJob(job, trigger, cancellationToken);
|
||||||
|
jobSchedule.JobStatu = JobStatus.Scheduling;
|
||||||
|
}
|
||||||
|
await Scheduler.Start(cancellationToken);
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
jobSchedule.JobStatu = JobStatus.Running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
await Scheduler?.Shutdown(cancellationToken);
|
||||||
|
foreach (var jobSchedule in _jobSchedules)
|
||||||
|
{
|
||||||
|
|
||||||
|
jobSchedule.JobStatu = JobStatus.Stopped;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static IJobDetail CreateJob(JobSchedule schedule)
|
||||||
|
{
|
||||||
|
var jobType = schedule.JobType;
|
||||||
|
return JobBuilder
|
||||||
|
.Create(jobType)
|
||||||
|
.WithIdentity(jobType.FullName)
|
||||||
|
.WithDescription(jobType.Name)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
private static ITrigger CreateTrigger(JobSchedule schedule)
|
||||||
|
{
|
||||||
|
return TriggerBuilder
|
||||||
|
.Create()
|
||||||
|
.WithIdentity($"{schedule.JobType.FullName}.trigger")
|
||||||
|
.WithCronSchedule(schedule.CronExpression)
|
||||||
|
.WithDescription(schedule.CronExpression)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -36,7 +37,7 @@ namespace SolarPower.Services.Implement
|
|||||||
Interlocked.Increment(ref execCount);
|
Interlocked.Increment(ref execCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (execCount == 1 && send_complete)
|
if (execCount == 1)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -58,5 +59,10 @@ namespace SolarPower.Services.Implement
|
|||||||
_timer?.Change(Timeout.Infinite, 0);
|
_timer?.Change(Timeout.Infinite, 0);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
<PackageReference Include="Dapper" Version="2.0.78" />
|
<PackageReference Include="Dapper" Version="2.0.78" />
|
||||||
<PackageReference Include="MySql.Data" Version="8.0.24" />
|
<PackageReference Include="MySql.Data" Version="8.0.24" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
<PackageReference Include="Quartz" Version="3.3.2" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" />
|
<PackageReference Include="Serilog.Extensions.Logging.File" Version="2.0.0" />
|
||||||
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
|
<PackageReference Include="System.Data.SqlClient" Version="4.8.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@ -8,9 +8,13 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using MySql.Data.MySqlClient;
|
using MySql.Data.MySqlClient;
|
||||||
|
using Quartz;
|
||||||
|
using Quartz.Impl;
|
||||||
|
using Quartz.Spi;
|
||||||
using SolarPower.Helper;
|
using SolarPower.Helper;
|
||||||
|
|
||||||
using SolarPower.Models;
|
using SolarPower.Models;
|
||||||
|
using SolarPower.Quartz;
|
||||||
|
using SolarPower.Quartz.Jobs;
|
||||||
using SolarPower.Repository.Implement;
|
using SolarPower.Repository.Implement;
|
||||||
using SolarPower.Repository.Interface;
|
using SolarPower.Repository.Interface;
|
||||||
using SolarPower.Services;
|
using SolarPower.Services;
|
||||||
@ -81,6 +85,16 @@ namespace SolarPower
|
|||||||
|
|
||||||
#region 加入背景執行
|
#region 加入背景執行
|
||||||
//services.AddHostedService<OperationScheduleBackgroundService>();
|
//services.AddHostedService<OperationScheduleBackgroundService>();
|
||||||
|
|
||||||
|
//²K¥[QuartzªA°È
|
||||||
|
services.AddSingleton<IJobFactory, SingletonJobFactory>();
|
||||||
|
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
|
||||||
|
//²K¥[§Ú̪ºJob
|
||||||
|
services.AddSingleton<OperationScheduleJob>();
|
||||||
|
services.AddSingleton(
|
||||||
|
new JobSchedule(jobType: typeof(OperationScheduleJob), cronExpression: "0/5 * * * * ?")
|
||||||
|
);
|
||||||
|
services.AddHostedService<QuartzHostedService>();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
177
SolarPower/Views/MapOverview/Index.cshtml
Normal file
177
SolarPower/Views/MapOverview/Index.cshtml
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
@{
|
||||||
|
ViewData["MainNum"] = "1";
|
||||||
|
ViewData["SubNum"] = "1";
|
||||||
|
ViewData["Title"] = "地圖總覽";
|
||||||
|
}
|
||||||
|
<ol class="breadcrumb page-breadcrumb">
|
||||||
|
<li class="breadcrumb-item"><a href="javascript:void(0);">總覽</a></li>
|
||||||
|
<li class="breadcrumb-item active">@ViewData["Title"]</li>
|
||||||
|
<li class="position-absolute pos-top pos-right d-none d-sm-block"><span class="js-get-date"></span></li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-12">
|
||||||
|
<div id="map"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@section Scripts{
|
||||||
|
|
||||||
|
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
|
||||||
|
<script src="https://unpkg.com/@googlemaps/markerclustererplus/dist/index.min.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var companyTable; var companyAuthTable;
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
//#region 公司管理列表 DataTable
|
||||||
|
companyTable = $("#company_table").DataTable({
|
||||||
|
"paging": true,
|
||||||
|
"lengthChange": false,
|
||||||
|
"searching": false,
|
||||||
|
"ordering": true,
|
||||||
|
"info": true,
|
||||||
|
"autoWidth": false,
|
||||||
|
"responsive": true,
|
||||||
|
"order": [[8, "desc"]],
|
||||||
|
"columns": [{
|
||||||
|
"data": "id"
|
||||||
|
}, {
|
||||||
|
"data": "logo"
|
||||||
|
}, {
|
||||||
|
"data": "name"
|
||||||
|
}, {
|
||||||
|
"data": "taxIDNumber"
|
||||||
|
}, {
|
||||||
|
"data": "phone"
|
||||||
|
}, {
|
||||||
|
"data": "address"
|
||||||
|
}, {
|
||||||
|
"data": "registerRatio"
|
||||||
|
}, {
|
||||||
|
"data": "spStationAmount"
|
||||||
|
}, {
|
||||||
|
"data": "createdAt"
|
||||||
|
}, {
|
||||||
|
"data": "function",
|
||||||
|
}],
|
||||||
|
"columnDefs": [{
|
||||||
|
'targets': 1,
|
||||||
|
'searchable': false,
|
||||||
|
'orderable': false,
|
||||||
|
'className': 'dt-body-center',
|
||||||
|
'render': function (data, type, full, meta) {
|
||||||
|
return '<img src="' + data + '?v=' + Date.now() + '" class="img-fluid">';
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"language": {
|
||||||
|
"emptyTable": "無資料...",
|
||||||
|
"processing": "處理中...",
|
||||||
|
"loadingRecords": "載入中...",
|
||||||
|
"lengthMenu": "顯示 _MENU_ 項結果",
|
||||||
|
"zeroRecords": "沒有符合的結果",
|
||||||
|
"info": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項",
|
||||||
|
"infoEmpty": "顯示第 0 至 0 項結果,共 0 項",
|
||||||
|
"infoFiltered": "(從 _MAX_ 項結果中過濾)",
|
||||||
|
"infoPostFix": "",
|
||||||
|
"search": "搜尋:",
|
||||||
|
"paginate": {
|
||||||
|
"first": "第一頁",
|
||||||
|
"previous": "上一頁",
|
||||||
|
"next": "下一頁",
|
||||||
|
"last": "最後一頁"
|
||||||
|
},
|
||||||
|
"aria": {
|
||||||
|
"sortAscending": ": 升冪排列",
|
||||||
|
"sortDescending": ": 降冪排列"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'createdRow': function (row, data, dataIndex) {
|
||||||
|
$(row).attr('data-id', data.id);
|
||||||
|
},
|
||||||
|
"ajax": {
|
||||||
|
"url": "/Company/CompanyList",
|
||||||
|
"type": "POST",
|
||||||
|
"data": function (d) {
|
||||||
|
d.SelectedCompanyId = $('#system_admin_account').val();
|
||||||
|
d.Name = $('#company_name').val();
|
||||||
|
d.Phone = $('#company_phone').val();
|
||||||
|
d.TaxIDNumber = $('#company_taxIDNumber').val();
|
||||||
|
},
|
||||||
|
"dataSrc": function (rel) {
|
||||||
|
if (rel.data.code == "9999") {
|
||||||
|
toast_error(rel.data.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = rel.data.data;
|
||||||
|
|
||||||
|
if (data == null || data.length == 0) {
|
||||||
|
this.data = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
//#region google map
|
||||||
|
initMap();
|
||||||
|
//#endregion
|
||||||
|
});
|
||||||
|
|
||||||
|
function initMap() {
|
||||||
|
const map = new google.maps.Map(document.getElementById("map"), {
|
||||||
|
zoom: 7,
|
||||||
|
center: { lat: 23.5, lng: 123 },
|
||||||
|
});
|
||||||
|
// Create an array of alphabetical characters used to label the markers.
|
||||||
|
const labels = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
// Add some markers to the map.
|
||||||
|
// Note: The code uses the JavaScript Array.prototype.map() method to
|
||||||
|
// create an array of markers based on a given "locations" array.
|
||||||
|
// The map() method here has nothing to do with the Google Maps API.
|
||||||
|
const markers = locations.map((location, i) => {
|
||||||
|
return new google.maps.Marker({
|
||||||
|
position: location,
|
||||||
|
label: labels[i % labels.length],
|
||||||
|
map: map
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Add a marker clusterer to manage the markers.
|
||||||
|
new MarkerClusterer(map, markers, {
|
||||||
|
imagePath:
|
||||||
|
"https://developers.google.com/maps/documentation/javascript/examples/markerclusterer/m",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const locations = [
|
||||||
|
{ lat: -31.56391, lng: 147.154312 },
|
||||||
|
{ lat: -33.718234, lng: 150.363181 },
|
||||||
|
{ lat: -33.727111, lng: 150.371124 },
|
||||||
|
{ lat: -33.848588, lng: 151.209834 },
|
||||||
|
{ lat: -33.851702, lng: 151.216968 },
|
||||||
|
{ lat: -34.671264, lng: 150.863657 },
|
||||||
|
{ lat: -35.304724, lng: 148.662905 },
|
||||||
|
{ lat: -36.817685, lng: 175.699196 },
|
||||||
|
{ lat: -36.828611, lng: 175.790222 },
|
||||||
|
{ lat: -37.75, lng: 145.116667 },
|
||||||
|
{ lat: -37.759859, lng: 145.128708 },
|
||||||
|
{ lat: -37.765015, lng: 145.133858 },
|
||||||
|
{ lat: -37.770104, lng: 145.143299 },
|
||||||
|
{ lat: -37.7737, lng: 145.145187 },
|
||||||
|
{ lat: -37.774785, lng: 145.137978 },
|
||||||
|
{ lat: -37.819616, lng: 144.968119 },
|
||||||
|
{ lat: -38.330766, lng: 144.695692 },
|
||||||
|
{ lat: -39.927193, lng: 175.053218 },
|
||||||
|
{ lat: -41.330162, lng: 174.865694 },
|
||||||
|
{ lat: -42.734358, lng: 147.439506 },
|
||||||
|
{ lat: -42.734358, lng: 147.501315 },
|
||||||
|
{ lat: -42.735258, lng: 147.438 },
|
||||||
|
{ lat: -43.999792, lng: 170.463352 },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
}
|
||||||
@ -89,7 +89,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li class="nav-title">Navigation Title</li>-->
|
<li class="nav-title">Navigation Title</li>-->
|
||||||
<li class="@(ViewData["MainNum"] == "1" ? "active open" : "")">
|
<li class="@(ViewData["MainNum"] == "1" ? "active open" : "")">
|
||||||
<a href="#" title="Category" data-filter-tags="category">
|
<a asp-controller="MapOverview" asp-action="Index" title="Category" data-filter-tags="category">
|
||||||
<i class="fal fa-file"></i>
|
<i class="fal fa-file"></i>
|
||||||
<span class="nav-link-text" data-i18n="nav.category">總覽</span>
|
<span class="nav-link-text" data-i18n="nav.category">總覽</span>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user