1. 加入runtime
2. 背景執行加入sensoravg
This commit is contained in:
parent
2966e27550
commit
933db5000b
@ -382,7 +382,7 @@ namespace SolarPower.Controllers
|
||||
|
||||
#region 新增公司DB及Table,公司DB編號規則 solar_com_(公司編號共四碼),ex:solar_com0001
|
||||
|
||||
var siteDBFormat = "solar_com{0}_test";
|
||||
var siteDBFormat = "solar_com{0}";
|
||||
|
||||
var siteDB = String.Format(siteDBFormat, id.ToString().Trim().PadLeft(4, '0'));
|
||||
//修改
|
||||
|
||||
@ -55,8 +55,18 @@ namespace SolarPower.Controllers
|
||||
ApiResult<List<UserSelectItemList>> apiResult = new ApiResult<List<UserSelectItemList>>();
|
||||
try
|
||||
{
|
||||
var companyId = 0;
|
||||
var powerStation = await powerStationRepository.GetOneAsync(powerStationId);
|
||||
var userSelectItemLists = await userRepository.GetUserSelectOptionListAsync(powerStation.CompanyId);
|
||||
|
||||
if(powerStation == null)
|
||||
{
|
||||
companyId = myUser.CompanyId;
|
||||
}
|
||||
else
|
||||
{
|
||||
companyId = powerStation.CompanyId;
|
||||
}
|
||||
var userSelectItemLists = await userRepository.GetUserSelectOptionListAsync(companyId);
|
||||
|
||||
apiResult.Code = "0000";
|
||||
apiResult.Data = userSelectItemLists;
|
||||
|
||||
@ -826,6 +826,62 @@ namespace SolarPower.Models.PowerStation
|
||||
public double TOTALCARBON { get; set; }
|
||||
}
|
||||
|
||||
public class SensorAvgHistory
|
||||
{
|
||||
public string TIMESTAMP { get; set; }
|
||||
public int PowerStationId { get; set; }
|
||||
public double SENSORAVG01 { get; set; }
|
||||
public double SENSORAVG02 { get; set; }
|
||||
public double SENSORAVG03 { get; set; }
|
||||
public double SENSORAVG04 { get; set; }
|
||||
public double SENSORAVG05 { get; set; }
|
||||
public double SENSORAVG06 { get; set; }
|
||||
public double SENSORAVG07 { get; set; }
|
||||
public double SENSORAVG08 { get; set; }
|
||||
public double SENSORAVG09 { get; set; }
|
||||
public double SENSORAVG10 { get; set; }
|
||||
public double SENSORAVG11 { get; set; }
|
||||
public double SENSORAVG12 { get; set; }
|
||||
public double SENSORAVG13 { get; set; }
|
||||
public double SENSORAVG14 { get; set; }
|
||||
public double SENSORAVG15 { get; set; }
|
||||
public double SENSORAVG16 { get; set; }
|
||||
public double SENSORAVG17 { get; set; }
|
||||
public double SENSORAVG18 { get; set; }
|
||||
public double SENSORAVG19 { get; set; }
|
||||
public double SENSORAVG20 { get; set; }
|
||||
public double SENSORAVG21 { get; set; }
|
||||
public double SENSORAVG22 { get; set; }
|
||||
public double SENSORAVG23 { get; set; }
|
||||
public double SENSORAVG24 { get; set; }
|
||||
public double SENSORAVG25 { get; set; }
|
||||
public double SENSORAVG26 { get; set; }
|
||||
public double SENSORAVG27 { get; set; }
|
||||
public double SENSORAVG28 { get; set; }
|
||||
public double SENSORAVG29 { get; set; }
|
||||
public double SENSORAVG30 { get; set; }
|
||||
public double SENSORAVG31 { get; set; }
|
||||
public double SENSORAVG32 { get; set; }
|
||||
public double SENSORAVG33 { get; set; }
|
||||
public double SENSORAVG34 { get; set; }
|
||||
public double SENSORAVG35 { get; set; }
|
||||
public double SENSORAVG36 { get; set; }
|
||||
public double SENSORAVG37 { get; set; }
|
||||
public double SENSORAVG38 { get; set; }
|
||||
public double SENSORAVG39 { get; set; }
|
||||
public double SENSORAVG40 { get; set; }
|
||||
public double SENSORAVG41 { get; set; }
|
||||
public double SENSORAVG42 { get; set; }
|
||||
public double SENSORAVG43 { get; set; }
|
||||
public double SENSORAVG44 { get; set; }
|
||||
public double SENSORAVG45 { get; set; }
|
||||
public double SENSORAVG46 { get; set; }
|
||||
public double SENSORAVG47 { get; set; }
|
||||
public double SENSORAVG48 { get; set; }
|
||||
public double SENSORAVG49 { get; set; }
|
||||
public double SENSORAVG50 { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -16,7 +16,8 @@
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
"ASPNETCORE_ENVIRONMENT": "Development",
|
||||
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
|
||||
}
|
||||
},
|
||||
"SolarPower": {
|
||||
|
||||
@ -36,8 +36,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
|
||||
List<PowerStation> calcAvgPowerStations = new List<PowerStation>();
|
||||
List<PowerStationHistoryDay> powerStationHistoryDays = new List<PowerStationHistoryDay>();
|
||||
|
||||
|
||||
List<PowerStationHistoryMonth> insertPowerStationHistoryMonths = new List<PowerStationHistoryMonth>();
|
||||
List<PowerStationHistoryMonth> updatePowerStationHistoryMonths = new List<PowerStationHistoryMonth>();
|
||||
|
||||
@ -52,7 +50,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
"Temperature"
|
||||
};
|
||||
|
||||
|
||||
List<InverterHistory> allofInverterHistorDays = new List<InverterHistory>();
|
||||
List<InverterHistory> insertInverterHistoryMonths = new List<InverterHistory>();
|
||||
List<InverterHistory> updateInverterHistoryMonths = new List<InverterHistory>();
|
||||
@ -115,9 +112,70 @@ namespace SolarPower.Quartz.Jobs
|
||||
"KWHKWP",
|
||||
};
|
||||
|
||||
List<SensorAvgHistory> sensorAvgHistoryDays = new List<SensorAvgHistory>();
|
||||
List<SensorAvgHistory> insertSensorAvgHistoryMonths = new List<SensorAvgHistory>();
|
||||
List<SensorAvgHistory> updateSensorAvgHistoryMonths = new List<SensorAvgHistory>();
|
||||
List<string> sensoravg_history_properties = new List<string>()
|
||||
{
|
||||
"PowerStationId",
|
||||
"TIMESTAMP",
|
||||
"SENSORAVG01",
|
||||
"SENSORAVG02",
|
||||
"SENSORAVG03",
|
||||
"SENSORAVG04",
|
||||
"SENSORAVG05",
|
||||
"SENSORAVG06",
|
||||
"SENSORAVG07",
|
||||
"SENSORAVG08",
|
||||
"SENSORAVG09",
|
||||
"SENSORAVG10",
|
||||
"SENSORAVG11",
|
||||
"SENSORAVG12",
|
||||
"SENSORAVG13",
|
||||
"SENSORAVG14",
|
||||
"SENSORAVG15",
|
||||
"SENSORAVG16",
|
||||
"SENSORAVG17",
|
||||
"SENSORAVG18",
|
||||
"SENSORAVG19",
|
||||
"SENSORAVG20",
|
||||
"SENSORAVG21",
|
||||
"SENSORAVG22",
|
||||
"SENSORAVG23",
|
||||
"SENSORAVG24",
|
||||
"SENSORAVG25",
|
||||
"SENSORAVG26",
|
||||
"SENSORAVG27",
|
||||
"SENSORAVG28",
|
||||
"SENSORAVG29",
|
||||
"SENSORAVG30",
|
||||
"SENSORAVG31",
|
||||
"SENSORAVG32",
|
||||
"SENSORAVG33",
|
||||
"SENSORAVG34",
|
||||
"SENSORAVG35",
|
||||
"SENSORAVG36",
|
||||
"SENSORAVG37",
|
||||
"SENSORAVG38",
|
||||
"SENSORAVG39",
|
||||
"SENSORAVG40",
|
||||
"SENSORAVG41",
|
||||
"SENSORAVG42",
|
||||
"SENSORAVG43",
|
||||
"SENSORAVG44",
|
||||
"SENSORAVG45",
|
||||
"SENSORAVG46",
|
||||
"SENSORAVG47",
|
||||
"SENSORAVG48",
|
||||
"SENSORAVG49",
|
||||
"SENSORAVG50",
|
||||
};
|
||||
|
||||
List<WeatherForecast> weatherForecasts = new List<WeatherForecast>();
|
||||
|
||||
var DateTimeNow = DateTime.Now;
|
||||
var dateNowDay = DateTimeNow.AddDays(-1).ToString("yyyy-MM-dd");
|
||||
var dateNowMonth = DateTimeNow.AddDays(-1).ToString("yyyy-MM");
|
||||
|
||||
#region 氣象觀測(取資料)
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始取得氣象觀測】");
|
||||
@ -206,7 +264,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
{
|
||||
var calcPowerStation = new PowerStation();
|
||||
calcPowerStation.Id = powerStation.Id;
|
||||
var dateNowDay = DateTimeNow.AddDays(-1).ToString("yyyy-MM-dd");
|
||||
|
||||
#region step2-1. 計算該電站的30天平均資料
|
||||
var table_name = String.Format("s{1}01_station", powerStation.SiteDB, powerStation.Code);
|
||||
@ -255,7 +312,7 @@ namespace SolarPower.Quartz.Jobs
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region step2-3. 計算昨天的所有值總和
|
||||
#region step2-2. 計算該電站昨天的所有值總和
|
||||
if (!string.IsNullOrEmpty(exist))
|
||||
{
|
||||
//電站資訊
|
||||
@ -263,7 +320,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
var historyDay = await powerStationRepository.GetLastOnePowerStationHistoryByDay(dateNowDay, full_table_name);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【取得成功電站[{0}]在{1}的所有值的總和】", powerStation.Code, dateNowDay);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【電站[{0}]在{1}的所有值的總和】 - {2}", powerStation.Code, dateNowDay, System.Text.Json.JsonSerializer.Serialize(historyDay));
|
||||
var daynow = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
var moneyandcarbon = await powerStationRepository.GetMoneyAndCarbonWithHistoryHour(powerStation.Id, dateNowDay, 1);
|
||||
var lastmoneyhistory = await powerStationRepository.GetLastMoneyAndCarbonInHour(powerStation.Id, 1, "");
|
||||
if (historyDay != null)
|
||||
@ -280,38 +336,47 @@ namespace SolarPower.Quartz.Jobs
|
||||
historyDay.Timestamp = Convert.ToDateTime(historyDay.Timestamp + ":00:00").ToString("yyyy-MM-dd");
|
||||
powerStationHistoryDays.Add(historyDay);
|
||||
}
|
||||
|
||||
//日照計
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
|
||||
var pyrheliometerHistorDay = await powerStationRepository.CalcPyrheliometerHistoryDayDataByPowerStationId(dateNowDay, powerStation.Id);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
|
||||
if (pyrheliometerHistorDay != null)
|
||||
{
|
||||
pyrheliometerHistoryDays.Add(pyrheliometerHistorDay);
|
||||
}
|
||||
|
||||
//逆變器
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
|
||||
var inverterHistoriesDay = await powerStationRepository.CalcInverterHistoryDayDataByPowerStationId(dateNowDay, powerStation.SiteDB, powerStation.Id);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
|
||||
if (inverterHistoriesDay != null)
|
||||
{
|
||||
foreach (var inverterHistoryDay in inverterHistoriesDay)
|
||||
{
|
||||
inverterHistoryDay.DC1KW = inverterHistoryDay.DC1W / 1000;
|
||||
inverterHistoryDay.DC2KW = inverterHistoryDay.DC2W / 1000;
|
||||
inverterHistoryDay.DC3KW = inverterHistoryDay.DC3W / 1000;
|
||||
inverterHistoryDay.DC4KW = inverterHistoryDay.DC4W / 1000;
|
||||
inverterHistoryDay.DC5KW = inverterHistoryDay.DC5W / 1000;
|
||||
|
||||
inverterHistoryDay.DCKW = (inverterHistoryDay.DC1W + inverterHistoryDay.DC2W + inverterHistoryDay.DC3W + inverterHistoryDay.DC4W + inverterHistoryDay.DC5W) / 1000;
|
||||
inverterHistoryDay.ACKW = (inverterHistoryDay.AC1W + inverterHistoryDay.AC2W + inverterHistoryDay.AC3W) / 1000;
|
||||
|
||||
allofInverterHistorDays.Add(inverterHistoryDay);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
//日照計
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
|
||||
var pyrheliometerHistorDay = await powerStationRepository.CalcPyrheliometerHistoryDayDataByPowerStationId(dateNowDay, powerStation.Id);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的日照計所有值的平均】", powerStation.Code, dateNowDay);
|
||||
if (pyrheliometerHistorDay != null)
|
||||
{
|
||||
pyrheliometerHistoryDays.Add(pyrheliometerHistorDay);
|
||||
}
|
||||
|
||||
//逆變器
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
|
||||
var inverterHistoriesDay = await powerStationRepository.CalcInverterHistoryDayDataByPowerStationId(dateNowDay, powerStation.SiteDB, powerStation.Id);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的逆變器所有值的平均】", powerStation.Code, dateNowDay);
|
||||
if (inverterHistoriesDay != null)
|
||||
{
|
||||
foreach (var inverterHistoryDay in inverterHistoriesDay)
|
||||
{
|
||||
inverterHistoryDay.DC1KW = inverterHistoryDay.DC1W / 1000;
|
||||
inverterHistoryDay.DC2KW = inverterHistoryDay.DC2W / 1000;
|
||||
inverterHistoryDay.DC3KW = inverterHistoryDay.DC3W / 1000;
|
||||
inverterHistoryDay.DC4KW = inverterHistoryDay.DC4W / 1000;
|
||||
inverterHistoryDay.DC5KW = inverterHistoryDay.DC5W / 1000;
|
||||
|
||||
inverterHistoryDay.DCKW = (inverterHistoryDay.DC1W + inverterHistoryDay.DC2W + inverterHistoryDay.DC3W + inverterHistoryDay.DC4W + inverterHistoryDay.DC5W) / 1000;
|
||||
inverterHistoryDay.ACKW = (inverterHistoryDay.AC1W + inverterHistoryDay.AC2W + inverterHistoryDay.AC3W) / 1000;
|
||||
|
||||
allofInverterHistorDays.Add(inverterHistoryDay);
|
||||
}
|
||||
}
|
||||
//sensor avg
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}的Sensor Avg table所有值的平均】", powerStation.Code, dateNowDay);
|
||||
var sensorAvgHistoryDay = await powerStationRepository.CalcSensorAvgDayDataByPowerStationId(dateNowDay, powerStation.Id);
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}的Sensor Avg table所有值的平均】", powerStation.Code, dateNowDay);
|
||||
if (sensorAvgHistoryDay != null)
|
||||
{
|
||||
sensorAvgHistoryDays.Add(sensorAvgHistoryDay);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
@ -328,7 +393,7 @@ namespace SolarPower.Quartz.Jobs
|
||||
#endregion
|
||||
|
||||
#region step4. 將各電站的每日的資料insert資料表
|
||||
//每日
|
||||
//每日 - 電站歷史資料
|
||||
List<string> history_properties_day = new List<string>()
|
||||
{
|
||||
"PowerStationId",
|
||||
@ -348,18 +413,18 @@ namespace SolarPower.Quartz.Jobs
|
||||
};
|
||||
await powerStationRepository.AddPowerStationHistoryDayList(powerStationHistoryDays, history_properties_day);
|
||||
|
||||
//每日
|
||||
//每日 - 日照溫度歷史資料
|
||||
await powerStationRepository.AddPyrheliometerHistoryDayList(pyrheliometerHistoryDays, pyrheliometer_history_properties);
|
||||
|
||||
//每日
|
||||
//每日 - 逆變器歷史資料
|
||||
await powerStationRepository.AddInverterHistoryDayList(allofInverterHistorDays, inverter_history_properties);
|
||||
|
||||
#region step3. 歸檔電站的每月資訊
|
||||
//每日 - sensor avg
|
||||
await powerStationRepository.AddSensorAvgHistoryDayList(sensorAvgHistoryDays, sensoravg_history_properties);
|
||||
|
||||
#region step5. 歸檔電站的每月資訊
|
||||
foreach (var powerStation in powerStations)
|
||||
{
|
||||
//判斷這個月是否已存在
|
||||
var dateNowMonth = DateTimeNow.ToString("yyyy-MM");
|
||||
|
||||
//電站該月份的歷史資料
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的歷史資料總和】", powerStation.Code, dateNowMonth);
|
||||
var exist_history = await powerStationRepository.GetOnePowerStationHistoryByPowerStationIdAndMonth(powerStation.Id, dateNowMonth);
|
||||
@ -370,8 +435,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
var lastmoneyhistorymonth = await powerStationRepository.GetLastMoneyAndCarbonInHour(powerStation.Id, 2, "");
|
||||
if (historyMonth != null)
|
||||
{
|
||||
|
||||
|
||||
historyMonth.Timestamp = Convert.ToDateTime(historyMonth.Timestamp).ToString("yyyy-MM-dd");
|
||||
historyMonth.MONEY = moneyandcarbonMon.MONEY;
|
||||
historyMonth.CARBON = moneyandcarbonMon.CARBON;
|
||||
@ -398,7 +461,6 @@ namespace SolarPower.Quartz.Jobs
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的歷史資料總和】", powerStation.Code, dateNowMonth);
|
||||
}
|
||||
|
||||
|
||||
//電站該月份的的日照度歷史資料
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的日照度歷史資料】", powerStation.Code, dateNowMonth);
|
||||
var exist_pyrheliometer_history = await powerStationRepository.GetOnePyrheliometerHistoryByMonth(dateNowMonth, powerStation.Id);
|
||||
@ -469,6 +531,30 @@ namespace SolarPower.Quartz.Jobs
|
||||
}
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的逆變器歷史資料】", powerStation.Code, dateNowMonth);
|
||||
}
|
||||
|
||||
//電站該月份的的sensoravg歷史資料
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【開始計算電站[{0}]在{1}月份的Sensor Avg table所有值的平均資料】", powerStation.Code, dateNowMonth);
|
||||
var exist_sensoravg_history = await powerStationRepository.GetSensorAvgHistoryByPowerStationIdAndMonth(dateNowMonth, powerStation.Id);
|
||||
if (exist_sensoravg_history != null)
|
||||
{ //新增
|
||||
var sensorAvgHistoryMonth = await powerStationRepository.CalcSensorAvgHistoryMonthDataByPowerStationId(dateNowMonth, powerStation.Id);
|
||||
if (sensorAvgHistoryMonth != null)
|
||||
{
|
||||
sensorAvgHistoryMonth.TIMESTAMP = Convert.ToDateTime(sensorAvgHistoryMonth.TIMESTAMP).ToString("yyyy-MM-dd");
|
||||
insertSensorAvgHistoryMonths.Add(sensorAvgHistoryMonth);
|
||||
}
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的Sensor Avg table所有值的平均資料】", powerStation.Code, dateNowMonth);
|
||||
}
|
||||
else
|
||||
{ //修改
|
||||
var sensorAvgHistoryMonth = await powerStationRepository.CalcSensorAvgHistoryMonthDataByPowerStationId(dateNowMonth, powerStation.Id);
|
||||
if (sensorAvgHistoryMonth != null)
|
||||
{
|
||||
sensorAvgHistoryMonth.TIMESTAMP = Convert.ToDateTime(sensorAvgHistoryMonth.TIMESTAMP).ToString("yyyy-MM-dd");
|
||||
updateSensorAvgHistoryMonths.Add(sensorAvgHistoryMonth);
|
||||
}
|
||||
logger.LogInformation("【CalcAvgPowerStationJob】【計算完成電站[{0}]在{1}月份的Sensor Avg table所有值的平均資料】", powerStation.Code, dateNowMonth);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
@ -516,8 +602,7 @@ namespace SolarPower.Quartz.Jobs
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region step6. 將各電站的每日及月的逆變器資料insert or update 各資料表
|
||||
|
||||
#region step6. 將各電站的每月的逆變器資料insert or update 各資料表
|
||||
//每月
|
||||
if (insertInverterHistoryMonths.Count > 0)
|
||||
{
|
||||
@ -530,6 +615,18 @@ namespace SolarPower.Quartz.Jobs
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region step6. 將各電站的每月的Sensor Avg資料insert or update 各資料表
|
||||
//每月
|
||||
if (insertSensorAvgHistoryMonths.Count > 0)
|
||||
{
|
||||
await powerStationRepository.AddSensorAvgHistoryMonthList(insertSensorAvgHistoryMonths, sensoravg_history_properties);
|
||||
}
|
||||
|
||||
if (updateSensorAvgHistoryMonths.Count > 0)
|
||||
{
|
||||
await powerStationRepository.UpdateSensorAvgHistoryMonthList(updateSensorAvgHistoryMonths);
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
catch (Exception exception)
|
||||
|
||||
@ -45,6 +45,7 @@ namespace SolarPower.Quartz.Jobs
|
||||
List<PyrheliometerHistory> TempHistoriesHour = new List<PyrheliometerHistory>();
|
||||
List<InverterHistory> inverterHistories = new List<InverterHistory>();
|
||||
List<PowerStation> calcPowerStations = new List<PowerStation>();
|
||||
List<SensorAvgHistory> sensorAvgHistoryHour = new List<SensorAvgHistory>();
|
||||
List<WeatherObservation> weatherObservations = new List<WeatherObservation>();
|
||||
|
||||
#region 氣象觀測(取資料)
|
||||
@ -227,7 +228,7 @@ namespace SolarPower.Quartz.Jobs
|
||||
|
||||
var inverter_table_name = String.Format("s{0}01_inv", powerStation.Code);
|
||||
var full_inverter_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, inverter_table_name);
|
||||
var exist_inverter_table = await powerStationRepository.ExistTable(powerStation.SiteDB, full_inverter_table_name);
|
||||
var exist_inverter_table = await powerStationRepository.ExistTable(powerStation.SiteDB, inverter_table_name);
|
||||
|
||||
if (!string.IsNullOrEmpty(exist_inverter_table))
|
||||
{
|
||||
@ -255,6 +256,26 @@ namespace SolarPower.Quartz.Jobs
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region step2-3. 計算該電站所有sensoravg
|
||||
var seneoravg_table_name = String.Format("s{0}01_sensoravg", powerStation.Code);
|
||||
var full_seneoravg_table_name = String.Format("`{0}`.`{1}`", powerStation.SiteDB, seneoravg_table_name);
|
||||
var exist_seneoravg_table = await powerStationRepository.ExistTable(powerStation.SiteDB, seneoravg_table_name);
|
||||
if (!string.IsNullOrEmpty(exist_seneoravg_table))
|
||||
{
|
||||
logger.LogInformation("【CalcPowerStationJob】【開始計算電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime);
|
||||
var sensorAvgHistory = await powerStationRepository.CalcSensorAvgHistory(dateTime, full_seneoravg_table_name);
|
||||
logger.LogInformation("【CalcPowerStationJob】【計算完成電站[{0}]在{1}的sensor avg的資訊】", powerStation.Code, dateTime);
|
||||
|
||||
if (sensorAvgHistory != null)
|
||||
{
|
||||
sensorAvgHistory.PowerStationId = powerStation.Id;
|
||||
sensorAvgHistory.TIMESTAMP = Convert.ToDateTime(sensorAvgHistory.TIMESTAMP + ":00:00").ToString("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
sensorAvgHistoryHour.Add(sensorAvgHistory);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 確認是否有觀測站(沒有則新增)
|
||||
if (powerStation.WeathersStationId == null)
|
||||
{
|
||||
@ -439,6 +460,66 @@ namespace SolarPower.Quartz.Jobs
|
||||
await powerStationRepository.AddInverterHistory(inverterHistories, inverter_history_properties);
|
||||
#endregion
|
||||
|
||||
#region step6. 將 inverter INSERT 到 inverter_history_hour 資料表
|
||||
List<string> sensoravg_history_properties = new List<string>()
|
||||
{
|
||||
"PowerStationId",
|
||||
"TIMESTAMP",
|
||||
"SENSORAVG01",
|
||||
"SENSORAVG02",
|
||||
"SENSORAVG03",
|
||||
"SENSORAVG04",
|
||||
"SENSORAVG05",
|
||||
"SENSORAVG06",
|
||||
"SENSORAVG07",
|
||||
"SENSORAVG08",
|
||||
"SENSORAVG09",
|
||||
"SENSORAVG10",
|
||||
"SENSORAVG11",
|
||||
"SENSORAVG12",
|
||||
"SENSORAVG13",
|
||||
"SENSORAVG14",
|
||||
"SENSORAVG15",
|
||||
"SENSORAVG16",
|
||||
"SENSORAVG17",
|
||||
"SENSORAVG18",
|
||||
"SENSORAVG19",
|
||||
"SENSORAVG20",
|
||||
"SENSORAVG21",
|
||||
"SENSORAVG22",
|
||||
"SENSORAVG23",
|
||||
"SENSORAVG24",
|
||||
"SENSORAVG25",
|
||||
"SENSORAVG26",
|
||||
"SENSORAVG27",
|
||||
"SENSORAVG28",
|
||||
"SENSORAVG29",
|
||||
"SENSORAVG30",
|
||||
"SENSORAVG31",
|
||||
"SENSORAVG32",
|
||||
"SENSORAVG33",
|
||||
"SENSORAVG34",
|
||||
"SENSORAVG35",
|
||||
"SENSORAVG36",
|
||||
"SENSORAVG37",
|
||||
"SENSORAVG38",
|
||||
"SENSORAVG39",
|
||||
"SENSORAVG40",
|
||||
"SENSORAVG41",
|
||||
"SENSORAVG42",
|
||||
"SENSORAVG43",
|
||||
"SENSORAVG44",
|
||||
"SENSORAVG45",
|
||||
"SENSORAVG46",
|
||||
"SENSORAVG47",
|
||||
"SENSORAVG48",
|
||||
"SENSORAVG49",
|
||||
"SENSORAVG50",
|
||||
};
|
||||
|
||||
await powerStationRepository.AddSensorAvgHistory(sensorAvgHistoryHour, sensoravg_history_properties);
|
||||
#endregion
|
||||
|
||||
List<string> weather_observation_properties = new List<string>()
|
||||
{
|
||||
"PowerStationId",
|
||||
|
||||
@ -315,12 +315,13 @@ namespace SolarPower.Repository.Implement
|
||||
{
|
||||
try
|
||||
{
|
||||
var startDateTime = dateTime + " 05:00";
|
||||
var endDataTime = dateTime + " 19:00";
|
||||
//var startDateTime = dateTime + " 05:00";
|
||||
//var endDataTime = dateTime + " 19:00";
|
||||
|
||||
var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime";
|
||||
//var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d %H:%i') BETWEEN @StartDateTime AND @EndDateTime";
|
||||
var sql = @$"SELECT * FROM inverter_history_15min WHERE PowerStationId = @PowerStationId AND DATE_FORMAT(TIMESTAMP, '%Y-%m-%d') = @DateTime";
|
||||
|
||||
result = (await conn.QueryAsync<InverterHistory>(sql, new { PowerStationId = powerStationId, StartDateTime = startDateTime, EndDateTime = endDataTime })).ToList();
|
||||
result = (await conn.QueryAsync<InverterHistory>(sql, new { PowerStationId = powerStationId, DateTime = dateTime })).ToList();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
|
||||
@ -2791,7 +2791,9 @@ namespace SolarPower.Repository.Implement
|
||||
{
|
||||
try
|
||||
{
|
||||
var sql = $@"SELECT AVG({col_name})
|
||||
var sql = $@"SELECT CASE WHEN AVG({col_name}) IS NULL THEN 0
|
||||
WHEN AVG({col_name}) IS NOT NULL THEN AVG({col_name})
|
||||
END
|
||||
FROM {db_name}.{table_name}
|
||||
WHERE FROM_UNIXTIME(TIMESTAMP/1000, '%Y-%m-%d %H') = @DateTime";
|
||||
|
||||
@ -2858,7 +2860,7 @@ namespace SolarPower.Repository.Implement
|
||||
AVG(inv.RA3) AS RA3,
|
||||
AVG(inv.RA4) AS RA4,
|
||||
AVG(inv.RA5) AS RA5,
|
||||
SUM(inv.KWH) AS KWH,
|
||||
AVG(inv.KWH) AS KWH,
|
||||
MAX(inv.TODAYKWH) AS TODAYKWH,
|
||||
MAX(inv.TODAYKWH) / i.Capacity AS KWHKWP
|
||||
FROM inverter_history_hour inv
|
||||
@ -2979,7 +2981,7 @@ namespace SolarPower.Repository.Implement
|
||||
AVG(inv.RA3) AS RA3,
|
||||
AVG(inv.RA4) AS RA4,
|
||||
AVG(inv.RA5) AS RA5,
|
||||
SUM(inv.KWH) AS KWH,
|
||||
AVG(inv.KWH) AS KWH,
|
||||
SUM(inv.TODAYKWH) AS TODAYKWH,
|
||||
SUM(inv.TODAYKWH) / i.Capacity AS KWHKWP
|
||||
FROM inverter_history_day inv
|
||||
@ -3256,7 +3258,7 @@ namespace SolarPower.Repository.Implement
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MoneyAndCarbon> GetLastMoneyAndCarbonInHour (int powerstationId ,int type,string time)
|
||||
public async Task<MoneyAndCarbon> GetLastMoneyAndCarbonInHour(int powerstationId, int type, string time)
|
||||
{
|
||||
MoneyAndCarbon result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
@ -3266,7 +3268,7 @@ namespace SolarPower.Repository.Implement
|
||||
{
|
||||
tablename = "power_station_history_hour";
|
||||
}
|
||||
else if(type == 1)
|
||||
else if (type == 1)
|
||||
{
|
||||
tablename = "power_station_history_day";
|
||||
}
|
||||
@ -3274,12 +3276,12 @@ namespace SolarPower.Repository.Implement
|
||||
{
|
||||
tablename = "power_station_history_month";
|
||||
}
|
||||
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
var sql = "";
|
||||
if(type == 0)
|
||||
if (type == 0)
|
||||
{
|
||||
var time2 = time.Split(' ');
|
||||
sql = $@"SELECT(SELECT TODAYMONEY FROM power_station_history_hour WHERE PowerStationId = {powerstationId} AND DATE_FORMAT(`TIMESTAMP`, '%Y-%m-%d') = '{time2[0]}' order by TIMESTAMP desc limit 1) AS TODAYMONEY,
|
||||
@ -3304,7 +3306,7 @@ namespace SolarPower.Repository.Implement
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<string> ExistTable(string db_name,string table_name)
|
||||
public async Task<string> ExistTable(string db_name, string table_name)
|
||||
{
|
||||
string result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
@ -3322,5 +3324,290 @@ namespace SolarPower.Repository.Implement
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SensorAvgHistory> CalcSensorAvgHistory(string dateTime, string table_name)
|
||||
{
|
||||
SensorAvgHistory result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var sensor_str = "";
|
||||
for (var i = 1; i <= 50; i++)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + "),";
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + i.ToString() + "),";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);
|
||||
|
||||
var sql = @$"SELECT
|
||||
FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H') AS TIMESTAMP,
|
||||
{sensor_str}
|
||||
FROM {table_name}
|
||||
WHERE FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H') = @DateTime
|
||||
GROUP BY FROM_UNIXTIME(timestamp / 1000, '%Y-%m-%d %H')";
|
||||
|
||||
|
||||
result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { DateTime = dateTime });
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> AddSensorAvgHistory(List<SensorAvgHistory> entity, List<string> properties)
|
||||
{
|
||||
int count;
|
||||
using (IDbConnection conn = _databaseHelper.GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
using (var trans = conn.BeginTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
string sql = GenerateInsertQueryWithCustomTable(properties, "weather_forecast");
|
||||
|
||||
count = await conn.ExecuteAsync(sql, entity, trans);
|
||||
|
||||
trans.Commit();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
trans.Rollback();
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
public async Task<SensorAvgHistory> CalcSensorAvgDayDataByPowerStationId(string nowDay, int powerStationId)
|
||||
{
|
||||
SensorAvgHistory result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var sensor_str = "";
|
||||
for (var i = 1; i <= 50; i++)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + "),";
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + i.ToString() + "),";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);
|
||||
|
||||
var sql = @$"SELECT
|
||||
DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d') AS TIMESTAMP,
|
||||
{sensor_str}
|
||||
FROM sensoravg_history_hour
|
||||
WHERE PowerStationId = @PowerStationId
|
||||
AND DATE_FORMAT(p.TIMESTAMP, '%Y-%m-%d') = @NowDay
|
||||
GROUP BY DATE_FORMAT(timestamp, '%Y-%m-%d')";
|
||||
|
||||
|
||||
result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { PowerStationId = powerStationId, NowDay = nowDay });
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> AddSensorAvgHistoryDayList(List<SensorAvgHistory> entity, List<string> properties)
|
||||
{
|
||||
int count;
|
||||
using (IDbConnection conn = _databaseHelper.GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
using (var trans = conn.BeginTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
string sql = GenerateInsertQueryWithCustomTable(properties, "sensoravg_history_day");
|
||||
|
||||
count = await conn.ExecuteAsync(sql, entity, trans);
|
||||
|
||||
trans.Commit();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
trans.Rollback();
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SensorAvgHistory> GetSensorAvgHistoryByPowerStationIdAndMonth(string month, int powerStationId)
|
||||
{
|
||||
SensorAvgHistory result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var sql = $@"SELECT * FROM sensoravg_history_month WHERE DATE_FORMAT(TIMESTAMP, '%Y-%m') = @Month AND PowerStationId = @PowerStationId";
|
||||
result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { Month = month, PowerStationId = powerStationId });
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SensorAvgHistory> CalcSensorAvgHistoryMonthDataByPowerStationId(string month, int powerStationId)
|
||||
{
|
||||
SensorAvgHistory result;
|
||||
using (IDbConnection conn = this._databaseHelper.GetConnection())
|
||||
{
|
||||
try
|
||||
{
|
||||
var sensor_str = "";
|
||||
for (var i = 1; i <= 50; i++)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + "0" + i.ToString() + "),";
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor_str += "AVG(SENSORAVG" + i.ToString() + "),";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);
|
||||
|
||||
var sql = @$"SELECT
|
||||
DATE_FORMAT(TIMESTAMP, '%Y-%m') AS TIMESTAMP,
|
||||
{sensor_str}
|
||||
FROM sensoravg_history_day
|
||||
WHERE PowerStationId = @PowerStationId
|
||||
AND DATE_FORMAT(TIMESTAMP, '%Y-%m') = @Month
|
||||
GROUP BY DATE_FORMAT(TIMESTAMP, '%Y-%m')";
|
||||
|
||||
result = await conn.QueryFirstOrDefaultAsync<SensorAvgHistory>(sql, new { Month = month, PowerStationId = powerStationId });
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
throw exception;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> AddSensorAvgHistoryMonthList(List<SensorAvgHistory> entity, List<string> properties)
|
||||
{
|
||||
int count;
|
||||
using (IDbConnection conn = _databaseHelper.GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
using (var trans = conn.BeginTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
string sql = GenerateInsertQueryWithCustomTable(properties, "sensoravg_history_month");
|
||||
|
||||
count = await conn.ExecuteAsync(sql, entity, trans);
|
||||
|
||||
trans.Commit();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
trans.Rollback();
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<int> UpdateSensorAvgHistoryMonthList(List<SensorAvgHistory> entity)
|
||||
{
|
||||
int count;
|
||||
using (IDbConnection conn = _databaseHelper.GetConnection())
|
||||
{
|
||||
conn.Open();
|
||||
using (var trans = conn.BeginTransaction())
|
||||
{
|
||||
try
|
||||
{
|
||||
var sensor_str = "";
|
||||
for (var i = 1; i <= 50; i++)
|
||||
{
|
||||
if (i < 10)
|
||||
{
|
||||
sensor_str += "SENSORAVG" + "0" + i.ToString() + " = @SENSORAVG" + "0" + i.ToString() + ",";
|
||||
}
|
||||
else
|
||||
{
|
||||
sensor_str += "SENSORAVG" + i.ToString() + " = @SENSORAVG" + i.ToString() + ",";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sensor_str = sensor_str.Substring(0, sensor_str.Length - 1);
|
||||
|
||||
string sql = @$"UPDATE sensoravg_history_month SET
|
||||
{sensor_str}
|
||||
WHERE PowerStationId = @PowerStationId
|
||||
AND TIMESTAMP LIKE CONCAT(@TIMESTAMP, '%')";
|
||||
|
||||
count = await conn.ExecuteAsync(sql, entity, trans);
|
||||
|
||||
trans.Commit();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
trans.Rollback();
|
||||
throw exception;
|
||||
}
|
||||
finally
|
||||
{
|
||||
conn.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,5 +538,13 @@ namespace SolarPower.Repository.Interface
|
||||
Task<MoneyAndCarbon> GetMoneyAndCarbonWithHistoryHour(int powerstationId, string dateTime, int type);
|
||||
Task<MoneyAndCarbon> GetLastMoneyAndCarbonInHour(int powerstationId,int type,string time);
|
||||
Task<string> ExistTable(string db_name, string table_name);
|
||||
Task<SensorAvgHistory> CalcSensorAvgHistory(string dateTime, string table_name);
|
||||
Task<int> AddSensorAvgHistory(List<SensorAvgHistory> entity, List<string> properties);
|
||||
Task<SensorAvgHistory> CalcSensorAvgDayDataByPowerStationId(string nowDay, int powerStationId);
|
||||
Task<int> AddSensorAvgHistoryDayList(List<SensorAvgHistory> entity, List<string> properties);
|
||||
Task<SensorAvgHistory> GetSensorAvgHistoryByPowerStationIdAndMonth(string month, int powerStationId);
|
||||
Task<SensorAvgHistory> CalcSensorAvgHistoryMonthDataByPowerStationId(string month, int powerStationId);
|
||||
Task<int> AddSensorAvgHistoryMonthList(List<SensorAvgHistory> entity, List<string> properties);
|
||||
Task<int> UpdateSensorAvgHistoryMonthList(List<SensorAvgHistory> entity);
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.0.78" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="3.1.17" />
|
||||
<PackageReference Include="MySql.Data" Version="8.0.24" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Quartz" Version="3.3.2" />
|
||||
|
||||
@ -18,6 +18,12 @@
|
||||
<div class="panel-content">
|
||||
<div class="subheader">
|
||||
<h1 class="subheader-title"> 電站分佈區域 </h1>
|
||||
<div>
|
||||
<a asp-controller="PowerStation" asp-action="Edit" asp-route-stationId="new" class="btn btn-success waves-effect waves-themed mb-3">
|
||||
<span class="fal fa-plus mr-1"></span>
|
||||
新增電站
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<ul id="areaTab" class="nav nav-tabs mb-5" role="tablist">
|
||||
@*<li class="nav-item">
|
||||
@ -319,13 +325,8 @@
|
||||
</div>
|
||||
<div id="templateArea" hidden="hidden">
|
||||
<div class="tab-pane" id="tab-name" role="tabpanel" aria-labelledby="tab-name">
|
||||
<div class="row mb-5 d-flex justify-content-between">
|
||||
<div class="col-6">
|
||||
<a asp-controller="PowerStation" asp-action="Edit" asp-route-stationId="new" class="btn btn-success waves-effect waves-themed mb-3">
|
||||
<span class="fal fa-plus mr-1"></span>
|
||||
新增電站
|
||||
</a>
|
||||
</div>
|
||||
<div class="row mb-5 d-flex justify-content-end">
|
||||
|
||||
<div class="col-6 text-right">
|
||||
<a href="javascript:TableDisplay();" class="btn btn-secondary btn-icon waves-effect waves-themed"><span class="fal fa-list mr-1"></span></a>
|
||||
<a href="javascript:CardDisplay();" class="btn btn-secondary btn-icon waves-effect waves-themed"><span class="fal fa-grip-horizontal mr-1"></span></a>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user