仪表盘优化:修复采集服务状态判断、去掉切削总时、数字保留两位小数、产量排行增加排序和TOP N

feat/windows-service-status-auto
haoliang 3 hours ago
parent 06d04c244e
commit 1600570b60

@ -227,8 +227,6 @@ export interface DashboardSummary {
activeAlerts: number activeAlerts: number
/** 今日采集成功率(%) */ /** 今日采集成功率(%) */
collectSuccessRate: number collectSuccessRate: number
/** 今日切削总时(小时) */
todayCuttingTime: number
/** 运行中机床数(有程序运行) */ /** 运行中机床数(有程序运行) */
runningMachines: number runningMachines: number
/** 数据缺失机床数(在线但采集失败) */ /** 数据缺失机床数(在线但采集失败) */

@ -38,11 +38,11 @@
</el-tooltip> </el-tooltip>
</div> </div>
<div class="stat-value"> <div class="stat-value">
<el-tag :type="collectorStatus.serviceStatus === 'Running' ? 'success' : (collectorStatus.serviceStatus === 'NotInstalled' ? 'danger' : 'warning')" size="small"> <el-tag :type="collectorTagType" size="small">
{{ serviceStatusLabel(collectorStatus.serviceStatus) }} {{ collectorStatusText }}
</el-tag> </el-tag>
</div> </div>
<div class="stat-sub" v-if="collectorStatus.serviceStatus === 'Running'"> {{ formatUptime(collectorStatus.uptimeSeconds) }}</div> <div class="stat-sub" v-if="collectorStatus.serviceStatus === 'Running' && collectorStatus.status === 'running'"> {{ formatUptime(collectorStatus.uptimeSeconds) }}</div>
</div> </div>
<div class="collector-actions"> <div class="collector-actions">
<el-button v-if="collectorStatus.serviceStatus !== 'Running'" size="small" type="success" :loading="startLoading" @click="startCollector"></el-button> <el-button v-if="collectorStatus.serviceStatus !== 'Running'" size="small" type="success" :loading="startLoading" @click="startCollector"></el-button>
@ -70,7 +70,7 @@
<!-- 统计卡片 第2行 --> <!-- 统计卡片 第2行 -->
<el-row :gutter="16" class="stat-row"> <el-row :gutter="16" class="stat-row">
<el-col :span="6"> <el-col :span="8">
<el-card shadow="hover"> <el-card shadow="hover">
<div class="stat-card"> <div class="stat-card">
<div class="stat-label"> <div class="stat-label">
@ -79,24 +79,11 @@
<span class="info-icon"></span> <span class="info-icon"></span>
</el-tooltip> </el-tooltip>
</div> </div>
<div class="stat-value">{{ summary.collectSuccessRate }}<span class="stat-unit">%</span></div> <div class="stat-value">{{ formatNumber(summary.collectSuccessRate) }}<span class="stat-unit">%</span></div>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="8">
<el-card shadow="hover">
<div class="stat-card">
<div class="stat-label">
今日切削总时
<el-tooltip content="今日所有机床实际切削加工的时间总和(单位:小时)。仅统计刀具接触工件的切削时间,不含空转和待机时间。" placement="top">
<span class="info-icon"></span>
</el-tooltip>
</div>
<div class="stat-value">{{ summary.todayCuttingTime }}<span class="stat-unit"> h</span></div>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover"> <el-card shadow="hover">
<div class="stat-card"> <div class="stat-card">
<div class="stat-label"> <div class="stat-label">
@ -109,7 +96,7 @@
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="6"> <el-col :span="8">
<el-card shadow="hover"> <el-card shadow="hover">
<div class="stat-card"> <div class="stat-card">
<div class="stat-label"> <div class="stat-label">
@ -204,8 +191,21 @@
<el-card shadow="hover"> <el-card shadow="hover">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span class="card-title">机床产量排行 TOP10<el-tooltip content="单台机床加工零件数由高到低排列,同时显示当前正在执行的程序名。" placement="top"><span class="info-icon"></span></el-tooltip></span> <span class="card-title">机床产量排行 TOP
<el-select v-model="machineTopN" size="small" style="width: 72px" @change="loadMachineRankData">
<el-option :value="5" label="5" />
<el-option :value="10" label="10" />
<el-option :value="20" label="20" />
<el-option :value="50" label="50" />
<el-option :value="100" label="100" />
</el-select>
<el-tooltip content="单台机床加工零件数排列,同时显示当前正在执行的程序名。" placement="top"><span class="info-icon"></span></el-tooltip>
</span>
<div class="date-filter"> <div class="date-filter">
<el-radio-group v-model="machineSortOrder" size="small" @change="loadMachineRankData" style="margin-right: 8px">
<el-radio-button value="asc">正序</el-radio-button>
<el-radio-button value="desc">倒序</el-radio-button>
</el-radio-group>
<el-radio-group v-model="machineDateType" size="small" @change="onMachineDateChange"> <el-radio-group v-model="machineDateType" size="small" @change="onMachineDateChange">
<el-radio-button value="today">今日</el-radio-button> <el-radio-button value="today">今日</el-radio-button>
<el-radio-button value="yesterday">昨日</el-radio-button> <el-radio-button value="yesterday">昨日</el-radio-button>
@ -225,7 +225,9 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="program" label="当前程序" show-overflow-tooltip /> <el-table-column prop="program" label="当前程序" show-overflow-tooltip />
<el-table-column prop="quantity" label="产量" width="80" align="center" /> <el-table-column label="产量" width="80" align="center">
<template #default="{ row }">{{ formatNumber(row.quantity) }}</template>
</el-table-column>
<el-table-column label="状态" width="70" align="center"> <el-table-column label="状态" width="70" align="center">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.status === 1 ? 'success' : 'danger'" size="small">{{ row.status === 1 ? '在线' : '离线' }}</el-tag> <el-tag :type="row.status === 1 ? 'success' : 'danger'" size="small">{{ row.status === 1 ? '在线' : '离线' }}</el-tag>
@ -238,8 +240,21 @@
<el-card shadow="hover"> <el-card shadow="hover">
<template #header> <template #header>
<div class="card-header"> <div class="card-header">
<span class="card-title">工人产量排行 TOP10<el-tooltip content="工人所绑定的所有机床产量合计,由高到低排列。" placement="top"><span class="info-icon"></span></el-tooltip></span> <span class="card-title">工人产量排行 TOP
<el-select v-model="workerTopN" size="small" style="width: 72px" @change="loadWorkerRankData">
<el-option :value="5" label="5" />
<el-option :value="10" label="10" />
<el-option :value="20" label="20" />
<el-option :value="50" label="50" />
<el-option :value="100" label="100" />
</el-select>
<el-tooltip content="工人所绑定的所有机床产量合计。" placement="top"><span class="info-icon"></span></el-tooltip>
</span>
<div class="date-filter"> <div class="date-filter">
<el-radio-group v-model="workerSortOrder" size="small" @change="loadWorkerRankData" style="margin-right: 8px">
<el-radio-button value="asc">正序</el-radio-button>
<el-radio-button value="desc">倒序</el-radio-button>
</el-radio-group>
<el-radio-group v-model="workerDateType" size="small" @change="onWorkerDateChange"> <el-radio-group v-model="workerDateType" size="small" @change="onWorkerDateChange">
<el-radio-button value="today">今日</el-radio-button> <el-radio-button value="today">今日</el-radio-button>
<el-radio-button value="yesterday">昨日</el-radio-button> <el-radio-button value="yesterday">昨日</el-radio-button>
@ -255,7 +270,9 @@
<el-table-column prop="rank" label="排名" width="60" align="center" /> <el-table-column prop="rank" label="排名" width="60" align="center" />
<el-table-column prop="workerName" label="工人姓名" /> <el-table-column prop="workerName" label="工人姓名" />
<el-table-column prop="machineCount" label="绑定机床" width="100" align="center" /> <el-table-column prop="machineCount" label="绑定机床" width="100" align="center" />
<el-table-column prop="totalQuantity" label="总产量" width="100" align="center" /> <el-table-column label="总产量" width="100" align="center">
<template #default="{ row }">{{ formatNumber(row.totalQuantity) }}</template>
</el-table-column>
</el-table> </el-table>
</el-card> </el-card>
</el-col> </el-col>
@ -274,7 +291,7 @@ import type { ApiResponse, DashboardSummary, CollectorStatus, MachineRankRow, Wo
const { isMock } = useMockMode() const { isMock } = useMockMode()
const summary = ref<DashboardSummary>({ onlineCount: 0, totalMachines: 0, todayProduction: 0, activeAlerts: 0, collectSuccessRate: 0, todayCuttingTime: 0, runningMachines: 0, dataMissingMachines: 0 }) const summary = ref<DashboardSummary>({ onlineCount: 0, totalMachines: 0, todayProduction: 0, activeAlerts: 0, collectSuccessRate: 0, runningMachines: 0, dataMissingMachines: 0 })
const collectorStatus = ref<CollectorStatus>({ status: 'stopped', uptimeSeconds: 0, serviceStatus: 'NotInstalled', serviceName: '' }) const collectorStatus = ref<CollectorStatus>({ status: 'stopped', uptimeSeconds: 0, serviceStatus: 'NotInstalled', serviceName: '' })
const machineRank = ref<MachineRankRow[]>([]) const machineRank = ref<MachineRankRow[]>([])
const workerRank = ref<WorkerRankRow[]>([]) const workerRank = ref<WorkerRankRow[]>([])
@ -296,6 +313,12 @@ const machineDateRange = ref<[string, string]>()
const workerDateType = ref<DateType>('today') const workerDateType = ref<DateType>('today')
const workerDateRange = ref<[string, string]>() const workerDateRange = ref<[string, string]>()
// TOP N
const machineTopN = ref(10)
const machineSortOrder = ref<'asc' | 'desc'>('asc')
const workerTopN = ref(10)
const workerSortOrder = ref<'asc' | 'desc'>('asc')
const dateLabels: Record<DateType, string> = { today: '今日', yesterday: '昨日', last3: '近3天', last7: '近7天', custom: '自定义' } const dateLabels: Record<DateType, string> = { today: '今日', yesterday: '昨日', last3: '近3天', last7: '近7天', custom: '自定义' }
const workshopDateLabel = computed(() => dateLabels[workshopDateType.value]) const workshopDateLabel = computed(() => dateLabels[workshopDateType.value])
const machineDateLabel = computed(() => dateLabels[machineDateType.value]) const machineDateLabel = computed(() => dateLabels[machineDateType.value])
@ -374,17 +397,32 @@ function formatUptime(seconds: number | undefined): string {
return `${hours}` return `${hours}`
} }
function serviceStatusLabel(status: string | undefined): string { function formatNumber(val: number | undefined | null): string {
switch ((status || '').toString()) { if (val == null) return '-'
case 'NotInstalled': return '未安装' return Number(val).toFixed(2)
case 'Running': return '运行中'
case 'Starting': return '启动中'
case 'StartFailed': return '启动失败'
case 'Stopped': return '已停止'
default: return status || '-'
}
} }
// + Windows
const collectorTagType = computed(() => {
const { serviceStatus, status } = collectorStatus.value
if (serviceStatus === 'Running' && status === 'running') return 'success'
if (serviceStatus === 'Running' && status !== 'running') return 'warning' //
if (serviceStatus === 'NotInstalled') return 'danger'
if (serviceStatus === 'StartFailed') return 'danger'
return 'warning'
})
const collectorStatusText = computed(() => {
const { serviceStatus, status } = collectorStatus.value
if (serviceStatus === 'Running' && status === 'running') return '运行中'
if (serviceStatus === 'Running' && status !== 'running') return '心跳超时'
if (serviceStatus === 'NotInstalled') return '未安装'
if (serviceStatus === 'Stopped') return '已停止'
if (serviceStatus === 'Starting') return '启动中'
if (serviceStatus === 'StartFailed') return '启动失败'
return serviceStatus || '-'
})
function alertTypeTag(type: string): string { function alertTypeTag(type: string): string {
const map: Record<string, string> = { collect_fail: 'danger', data_missing: 'warning', device_offline: 'danger', new_device: 'info' } const map: Record<string, string> = { collect_fail: 'danger', data_missing: 'warning', device_offline: 'danger', new_device: 'info' }
return map[type] || 'warning' return map[type] || 'warning'
@ -481,7 +519,7 @@ async function loadWorkshopData() {
async function loadMachineRankData() { async function loadMachineRankData() {
try { try {
const { startDate, endDate } = getDateRange(machineDateType.value, machineDateRange.value) const { startDate, endDate } = getDateRange(machineDateType.value, machineDateRange.value)
const res: ApiResponse<{ items: MachineRankRow[] }> = await request.get('/admin/dashboard/machine-rank', { params: { startDate, endDate } }) const res: ApiResponse<{ items: MachineRankRow[] }> = await request.get('/admin/dashboard/machine-rank', { params: { startDate, endDate, top: machineTopN.value, sortOrder: machineSortOrder.value } })
machineRank.value = res.data?.items || [] machineRank.value = res.data?.items || []
} catch { /* */ } } catch { /* */ }
} }
@ -489,7 +527,7 @@ async function loadMachineRankData() {
async function loadWorkerRankData() { async function loadWorkerRankData() {
try { try {
const { startDate, endDate } = getDateRange(workerDateType.value, workerDateRange.value) const { startDate, endDate } = getDateRange(workerDateType.value, workerDateRange.value)
const res: ApiResponse<{ items: WorkerRankRow[] }> = await request.get('/admin/dashboard/worker-rank', { params: { startDate, endDate } }) const res: ApiResponse<{ items: WorkerRankRow[] }> = await request.get('/admin/dashboard/worker-rank', { params: { startDate, endDate, top: workerTopN.value, sortOrder: workerSortOrder.value } })
workerRank.value = res.data?.items || [] workerRank.value = res.data?.items || []
} catch { /* */ } } catch { /* */ }
} }

@ -22,9 +22,6 @@ namespace CncModels.Dto.Dashboard
/// <summary>采集成功率(百分比,小数不放大)</summary> /// <summary>采集成功率(百分比,小数不放大)</summary>
public decimal CollectSuccessRate { get; set; } public decimal CollectSuccessRate { get; set; }
/// <summary>今日总工作时长/产线运行时间,单位分钟</summary>
public int TodayCuttingTime { get; set; }
/// <summary>正在运行的机床数量</summary> /// <summary>正在运行的机床数量</summary>
public int RunningMachines { get; set; } public int RunningMachines { get; set; }

@ -64,15 +64,6 @@ namespace CncRepository.Impl.Dashboard
var totalCount = successCount + failCount; var totalCount = successCount + failCount;
decimal collectSuccessRate = totalCount > 0 ? Math.Round((decimal)successCount / totalCount * 100, 2) : 0m; decimal collectSuccessRate = totalCount > 0 ? Math.Round((decimal)successCount / totalCount * 100, 2) : 0m;
// 今日切削总时每台机床今日最新cutting_time - 今日最早cutting_time求和后转小时
var todayCuttingTime = Convert.ToInt32(conn.ExecuteScalar<decimal>(@"
SELECT COALESCE(ROUND(SUM(today_delta)/3600, 1), 0)
FROM (
SELECT MAX(cr.cutting_time) - MIN(cr.cutting_time) AS today_delta
FROM cnc_collect_record cr
WHERE DATE(cr.collect_time) = CURDATE()
GROUP BY cr.machine_id
) t"));
var runningMachines = conn.ExecuteScalar<int>(@"SELECT COUNT(1) FROM cnc_machine WHERE last_device_status = 'running'"); var runningMachines = conn.ExecuteScalar<int>(@"SELECT COUNT(1) FROM cnc_machine WHERE last_device_status = 'running'");
var dataMissingMachines = conn.ExecuteScalar<int>(@"SELECT COUNT(1) FROM cnc_machine_daily_status WHERE production_date = CURDATE() AND data_status = 'data_missing'"); var dataMissingMachines = conn.ExecuteScalar<int>(@"SELECT COUNT(1) FROM cnc_machine_daily_status WHERE production_date = CURDATE() AND data_status = 'data_missing'");
@ -83,7 +74,6 @@ namespace CncRepository.Impl.Dashboard
TodayProduction = todayProduction, TodayProduction = todayProduction,
ActiveAlerts = activeAlerts, ActiveAlerts = activeAlerts,
CollectSuccessRate = collectSuccessRate, CollectSuccessRate = collectSuccessRate,
TodayCuttingTime = todayCuttingTime,
RunningMachines = runningMachines, RunningMachines = runningMachines,
DataMissingMachines = dataMissingMachines DataMissingMachines = dataMissingMachines
}; };
@ -131,11 +121,13 @@ namespace CncRepository.Impl.Dashboard
} }
/// <summary>机床排行</summary> /// <summary>机床排行</summary>
public List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300) public List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300, string sortOrder = "desc")
{ {
// 排序方向白名单校验防止SQL注入
var orderBy = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
using (var conn = CreateConnection()) using (var conn = CreateConnection())
{ {
var sql = @" var sql = $@"
SELECT m.id AS MachineId, SELECT m.id AS MachineId,
m.name AS MachineName, m.name AS MachineName,
COALESCE(SUM(ad.day_quantity), 0) AS Quantity, COALESCE(SUM(ad.day_quantity), 0) AS Quantity,
@ -164,7 +156,7 @@ namespace CncRepository.Impl.Dashboard
GROUP BY seg.machine_id, seg.production_date GROUP BY seg.machine_id, seg.production_date
) ad ON ad.machine_id = m.id ) ad ON ad.machine_id = m.id
GROUP BY m.id, m.name, m.is_enabled, m.last_ping_time GROUP BY m.id, m.name, m.is_enabled, m.last_ping_time
ORDER BY Quantity DESC ORDER BY Quantity {orderBy}
LIMIT @Top"; LIMIT @Top";
var rows = conn.Query<MachineRankResponse>(sql, new { StartDate = startDate, EndDate = endDate, Top = top, OnlineTimeout = onlineTimeout }).ToList(); var rows = conn.Query<MachineRankResponse>(sql, new { StartDate = startDate, EndDate = endDate, Top = top, OnlineTimeout = onlineTimeout }).ToList();
// 填充排名 // 填充排名
@ -174,11 +166,13 @@ namespace CncRepository.Impl.Dashboard
} }
/// <summary>工人排行</summary> /// <summary>工人排行</summary>
public List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top) public List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc")
{ {
// 排序方向白名单校验防止SQL注入
var orderBy = string.Equals(sortOrder, "asc", StringComparison.OrdinalIgnoreCase) ? "ASC" : "DESC";
using (var conn = CreateConnection()) using (var conn = CreateConnection())
{ {
var sql = @" var sql = $@"
SELECT w.name AS WorkerName, SELECT w.name AS WorkerName,
COUNT(DISTINCT wm.machine_id) AS MachineCount, COUNT(DISTINCT wm.machine_id) AS MachineCount,
COALESCE(SUM(ad.day_quantity), 0) AS TotalQuantity COALESCE(SUM(ad.day_quantity), 0) AS TotalQuantity
@ -204,7 +198,7 @@ namespace CncRepository.Impl.Dashboard
GROUP BY seg.machine_id, seg.production_date GROUP BY seg.machine_id, seg.production_date
) ad ON ad.machine_id = wm.machine_id ) ad ON ad.machine_id = wm.machine_id
GROUP BY w.id, w.name GROUP BY w.id, w.name
ORDER BY TotalQuantity DESC ORDER BY TotalQuantity {orderBy}
LIMIT @Top"; LIMIT @Top";
var rows = conn.Query<WorkerRankResponse>(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList(); var rows = conn.Query<WorkerRankResponse>(sql, new { StartDate = startDate, EndDate = endDate, Top = top }).ToList();
// 填充排名 // 填充排名

@ -13,9 +13,9 @@ namespace CncRepository.Interface
List<WorkshopProductionResponse> GetWorkshopProduction(DateTime startDate, DateTime endDate); List<WorkshopProductionResponse> GetWorkshopProduction(DateTime startDate, DateTime endDate);
List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300); List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int onlineTimeout = 300, string sortOrder = "desc");
List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top); List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc");
List<dynamic> GetProductionTrend(int days); List<dynamic> GetProductionTrend(int days);

@ -50,19 +50,19 @@ namespace CncService.Impl
} }
/// <inheritdoc/> /// <inheritdoc/>
public List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10) public List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10, string sortOrder = "desc")
{ {
var s = startDate ?? DateTime.Today; var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today; var e = endDate ?? DateTime.Today;
return _dashboardRepository.GetMachineRank(s, e, top, GetOnlineTimeout()); return _dashboardRepository.GetMachineRank(s, e, top, GetOnlineTimeout(), sortOrder);
} }
/// <inheritdoc/> /// <inheritdoc/>
public List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10) public List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10, string sortOrder = "desc")
{ {
var s = startDate ?? DateTime.Today; var s = startDate ?? DateTime.Today;
var e = endDate ?? DateTime.Today; var e = endDate ?? DateTime.Today;
return _dashboardRepository.GetWorkerRank(s, e, top); return _dashboardRepository.GetWorkerRank(s, e, top, sortOrder);
} }
/// <inheritdoc/> /// <inheritdoc/>

@ -23,8 +23,13 @@ namespace CncService.Impl
return ServiceStatusEnum.Running; return ServiceStatusEnum.Running;
case ServiceControllerStatus.StartPending: case ServiceControllerStatus.StartPending:
case ServiceControllerStatus.ContinuePending: case ServiceControllerStatus.ContinuePending:
return ServiceStatusEnum.Starting;
case ServiceControllerStatus.Stopped:
case ServiceControllerStatus.StopPending:
case ServiceControllerStatus.PausePending:
case ServiceControllerStatus.Paused:
return ServiceStatusEnum.Stopped;
default: default:
// 启动中的状态或未知状态视作 Starting
return ServiceStatusEnum.Starting; return ServiceStatusEnum.Starting;
} }
} }

@ -13,9 +13,9 @@ namespace CncService.Interface
List<WorkshopProductionResponse> GetWorkshopProduction(DateTime? startDate, DateTime? endDate); List<WorkshopProductionResponse> GetWorkshopProduction(DateTime? startDate, DateTime? endDate);
List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10); List<MachineRankResponse> GetMachineRank(DateTime? startDate, DateTime? endDate, int top = 10, string sortOrder = "desc");
List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10); List<WorkerRankResponse> GetWorkerRank(DateTime? startDate, DateTime? endDate, int top = 10, string sortOrder = "desc");
object GetProductionTrend(int days = 7); object GetProductionTrend(int days = 7);

@ -54,26 +54,26 @@ namespace CncWebApi.Controllers
} }
/// <summary> /// <summary>
/// 机床产量排行TOP10 /// 机床产量排行
/// GET /api/admin/dashboard/machine-rank /// GET /api/admin/dashboard/machine-rank
/// </summary> /// </summary>
[HttpGet] [HttpGet]
[Route("machine-rank")] [Route("machine-rank")]
public IHttpActionResult GetMachineRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10) public IHttpActionResult GetMachineRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10, string sortOrder = "desc")
{ {
var result = _dashboardService.GetMachineRank(startDate, endDate, top); var result = _dashboardService.GetMachineRank(startDate, endDate, top, sortOrder);
return Ok(ApiResponse<object>.Success(new { items = result })); return Ok(ApiResponse<object>.Success(new { items = result }));
} }
/// <summary> /// <summary>
/// 工人产量排行TOP10 /// 工人产量排行
/// GET /api/admin/dashboard/worker-rank /// GET /api/admin/dashboard/worker-rank
/// </summary> /// </summary>
[HttpGet] [HttpGet]
[Route("worker-rank")] [Route("worker-rank")]
public IHttpActionResult GetWorkerRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10) public IHttpActionResult GetWorkerRank(DateTime? startDate = null, DateTime? endDate = null, int top = 10, string sortOrder = "desc")
{ {
var result = _dashboardService.GetWorkerRank(startDate, endDate, top); var result = _dashboardService.GetWorkerRank(startDate, endDate, top, sortOrder);
return Ok(ApiResponse<object>.Success(new { items = result })); return Ok(ApiResponse<object>.Success(new { items = result }));
} }

@ -14,8 +14,8 @@ namespace CncService.Tests
{ {
public DashboardSummaryResponse GetSummary(int something) => new DashboardSummaryResponse(); public DashboardSummaryResponse GetSummary(int something) => new DashboardSummaryResponse();
public List<WorkshopProductionResponse> GetWorkshopProduction(DateTime startDate, DateTime endDate) => new List<WorkshopProductionResponse>(); public List<WorkshopProductionResponse> GetWorkshopProduction(DateTime startDate, DateTime endDate) => new List<WorkshopProductionResponse>();
public List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int something) => new List<MachineRankResponse>(); public List<MachineRankResponse> GetMachineRank(DateTime startDate, DateTime endDate, int top, int something, string sortOrder = "desc") => new List<MachineRankResponse>();
public List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top) => new List<WorkerRankResponse>(); public List<WorkerRankResponse> GetWorkerRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List<WorkerRankResponse>();
public List<dynamic> GetProductionTrend(int days) => new List<dynamic>(); public List<dynamic> GetProductionTrend(int days) => new List<dynamic>();
public object GetMachineStatusDistribution(int something) => new object(); public object GetMachineStatusDistribution(int something) => new object();
public List<AlertListItem> GetRecentAlerts(int count) => new List<AlertListItem>(); public List<AlertListItem> GetRecentAlerts(int count) => new List<AlertListItem>();

Loading…
Cancel
Save