分配详情

This commit is contained in:
18631081161 2026-01-20 15:27:21 +08:00
parent 88427cab99
commit d64ce88ec8
3 changed files with 339 additions and 49 deletions

View File

@ -507,7 +507,7 @@ public class AllocationsController : BaseApiController
/// 获取按单位汇总的上报数据
/// </summary>
[HttpGet("distributions/{distributionId}/summary")]
public async Task<IActionResult> GetReportSummaryByUnit(int distributionId, [FromQuery] string? period = null)
public async Task<IActionResult> GetReportSummaryByUnit(int distributionId, [FromQuery] string? period = null, [FromQuery] string? startDate = null, [FromQuery] string? endDate = null)
{
var unitId = GetCurrentUnitId();
var unitLevel = GetCurrentUnitLevel();
@ -521,23 +521,30 @@ public class AllocationsController : BaseApiController
return NotFound(new { message = "配额分配记录不存在" });
// 计算时间范围
DateTime? startDate = null;
DateTime? endDate = null;
if (!string.IsNullOrEmpty(period) && period != "all")
DateTime? queryStartDate = null;
DateTime? queryEndDate = null;
if (period == "custom" && !string.IsNullOrEmpty(startDate) && !string.IsNullOrEmpty(endDate))
{
endDate = DateTime.Now;
startDate = period switch
// 自定义时间范围
queryStartDate = DateTime.Parse(startDate);
queryEndDate = DateTime.Parse(endDate).AddDays(1).AddSeconds(-1);
}
else if (!string.IsNullOrEmpty(period) && period != "all")
{
queryEndDate = DateTime.Now;
queryStartDate = period switch
{
"week" => endDate.Value.AddDays(-7),
"month" => endDate.Value.AddMonths(-1),
"halfYear" => endDate.Value.AddMonths(-6),
"year" => endDate.Value.AddYears(-1),
"week" => queryEndDate.Value.AddDays(-7),
"month" => queryEndDate.Value.AddMonths(-1),
"halfYear" => queryEndDate.Value.AddMonths(-6),
"year" => queryEndDate.Value.AddYears(-1),
_ => null
};
}
// 获取按单位汇总的上报数据
var summaries = await _allocationService.GetReportSummaryByUnitAsync(distributionId, unitId.Value, unitLevel.Value, startDate, endDate);
var summaries = await _allocationService.GetReportSummaryByUnitAsync(distributionId, unitId.Value, unitLevel.Value, queryStartDate, queryEndDate);
return Ok(summaries);
}
@ -548,7 +555,7 @@ public class AllocationsController : BaseApiController
/// </summary>
[HttpGet("{id}/consumption-stats")]
[Authorize(Policy = "DivisionLevel")]
public async Task<IActionResult> GetConsumptionStats(int id, [FromQuery] string period = "month")
public async Task<IActionResult> GetConsumptionStats(int id, [FromQuery] string period = "month", [FromQuery] string? startDate = null, [FromQuery] string? endDate = null)
{
var unitId = GetCurrentUnitId();
var unitLevel = GetCurrentUnitLevel();
@ -562,18 +569,30 @@ public class AllocationsController : BaseApiController
return NotFound(new { message = "配额不存在" });
// 计算时间范围
var endDate = DateTime.Now;
var startDate = period switch
DateTime queryEndDate;
DateTime queryStartDate;
if (period == "custom" && !string.IsNullOrEmpty(startDate) && !string.IsNullOrEmpty(endDate))
{
"week" => endDate.AddDays(-7),
"month" => endDate.AddMonths(-1),
"halfYear" => endDate.AddMonths(-6),
"year" => endDate.AddYears(-1),
_ => endDate.AddMonths(-1)
};
// 自定义时间范围
queryStartDate = DateTime.Parse(startDate);
queryEndDate = DateTime.Parse(endDate).AddDays(1).AddSeconds(-1); // 包含结束日期当天
}
else
{
queryEndDate = DateTime.Now;
queryStartDate = period switch
{
"week" => queryEndDate.AddDays(-7),
"month" => queryEndDate.AddMonths(-1),
"halfYear" => queryEndDate.AddMonths(-6),
"year" => queryEndDate.AddYears(-1),
_ => queryEndDate.AddMonths(-1)
};
}
// 获取按单位汇总的消耗统计
var stats = await _allocationService.GetConsumptionStatsByPeriodAsync(id, startDate, endDate);
var stats = await _allocationService.GetConsumptionStatsByPeriodAsync(id, queryStartDate, queryEndDate);
return Ok(new
{
@ -582,8 +601,8 @@ public class AllocationsController : BaseApiController
unit = allocation.Unit,
totalQuota = allocation.TotalQuota,
period,
startDate,
endDate,
startDate = queryStartDate,
endDate = queryEndDate,
unitStats = stats
});
}

View File

@ -53,16 +53,23 @@ export const allocationsApi = {
return response.data
},
async getReportSummaryByUnit(distributionId: number, period?: string): Promise<UnitReportSummary[]> {
async getReportSummaryByUnit(distributionId: number, period?: string, startDate?: string, endDate?: string): Promise<UnitReportSummary[]> {
const params: Record<string, string> = {}
if (period) params.period = period
if (startDate) params.startDate = startDate
if (endDate) params.endDate = endDate
const response = await apiClient.get<UnitReportSummary[]>(`/allocations/distributions/${distributionId}/summary`, {
params: period ? { period } : undefined
params: Object.keys(params).length > 0 ? params : undefined
})
return response.data
},
async getConsumptionStats(allocationId: number, period: string): Promise<ConsumptionStatsResponse> {
async getConsumptionStats(allocationId: number, period: string, startDate?: string, endDate?: string): Promise<ConsumptionStatsResponse> {
const params: Record<string, string> = { period }
if (startDate) params.startDate = startDate
if (endDate) params.endDate = endDate
const response = await apiClient.get<ConsumptionStatsResponse>(`/allocations/${allocationId}/consumption-stats`, {
params: { period }
params
})
return response.data
}

View File

@ -258,13 +258,51 @@
<!-- 师部账号时间范围筛选 -->
<div v-if="authStore.canCreateAllocations" class="period-filter">
<span class="filter-label">查看时间范围</span>
<el-radio-group v-model="selectedPeriod" size="small" @change="handlePeriodChange">
<el-radio-button value="week"></el-radio-button>
<el-radio-button value="month"></el-radio-button>
<el-radio-button value="halfYear">半年</el-radio-button>
<el-radio-button value="year"></el-radio-button>
<el-radio-group v-model="periodType" size="small" @change="handlePeriodTypeChange">
<el-radio-button value="week"></el-radio-button>
<el-radio-button value="month"></el-radio-button>
<el-radio-button value="halfYear">半年</el-radio-button>
<el-radio-button value="year"></el-radio-button>
<el-radio-button value="all">全部</el-radio-button>
</el-radio-group>
<template v-if="periodType === 'week'">
<el-date-picker
v-model="selectedWeek"
type="week"
format="YYYY 第 ww 周"
placeholder="选择周"
size="small"
style="width: 160px; margin-left: 12px;"
@change="handleDateChange"
/>
</template>
<template v-else-if="periodType === 'month'">
<el-date-picker
v-model="selectedMonth"
type="month"
format="YYYY-MM"
placeholder="选择月份"
size="small"
style="width: 140px; margin-left: 12px;"
@change="handleDateChange"
/>
</template>
<template v-else-if="periodType === 'halfYear'">
<el-select v-model="selectedHalfYear" placeholder="选择半年" size="small" style="width: 160px; margin-left: 12px;" @change="handleDateChange">
<el-option v-for="item in halfYearOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
<template v-else-if="periodType === 'year'">
<el-date-picker
v-model="selectedYear"
type="year"
format="YYYY"
placeholder="选择年份"
size="small"
style="width: 120px; margin-left: 12px;"
@change="handleDateChange"
/>
</template>
</div>
<!-- 师团级和团级显示分配列表营部及以下隐藏 -->
@ -382,13 +420,51 @@
<!-- 师部账号时间范围筛选 -->
<div v-if="authStore.canCreateAllocations" class="period-filter">
<span class="filter-label">查看时间范围</span>
<el-radio-group v-model="reportsPeriod" size="small" @change="handleReportsPeriodChange">
<el-radio-button value="week"></el-radio-button>
<el-radio-button value="month"></el-radio-button>
<el-radio-button value="halfYear">半年</el-radio-button>
<el-radio-button value="year"></el-radio-button>
<el-radio-group v-model="reportsPeriodType" size="small" @change="handleReportsPeriodTypeChange">
<el-radio-button value="week"></el-radio-button>
<el-radio-button value="month"></el-radio-button>
<el-radio-button value="halfYear">半年</el-radio-button>
<el-radio-button value="year"></el-radio-button>
<el-radio-button value="all">全部</el-radio-button>
</el-radio-group>
<template v-if="reportsPeriodType === 'week'">
<el-date-picker
v-model="reportsSelectedWeek"
type="week"
format="YYYY 第 ww 周"
placeholder="选择周"
size="small"
style="width: 160px; margin-left: 12px;"
@change="handleReportsDateChange"
/>
</template>
<template v-else-if="reportsPeriodType === 'month'">
<el-date-picker
v-model="reportsSelectedMonth"
type="month"
format="YYYY-MM"
placeholder="选择月份"
size="small"
style="width: 140px; margin-left: 12px;"
@change="handleReportsDateChange"
/>
</template>
<template v-else-if="reportsPeriodType === 'halfYear'">
<el-select v-model="reportsSelectedHalfYear" placeholder="选择半年" size="small" style="width: 160px; margin-left: 12px;" @change="handleReportsDateChange">
<el-option v-for="item in halfYearOptions" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</template>
<template v-else-if="reportsPeriodType === 'year'">
<el-date-picker
v-model="reportsSelectedYear"
type="year"
format="YYYY"
placeholder="选择年份"
size="small"
style="width: 120px; margin-left: 12px;"
@change="handleReportsDateChange"
/>
</template>
</div>
<el-tabs v-model="reportsTabActive" class="reports-tabs">
@ -505,6 +581,31 @@ const selectedDistribution = ref<AllocationDistribution | null>(null)
const selectedPeriod = ref('all')
const reportsPeriod = ref('all')
//
const periodType = ref('all')
const selectedWeek = ref<Date | null>(null)
const selectedMonth = ref<Date | null>(null)
const selectedYear = ref<Date | null>(null)
const selectedHalfYear = ref('')
//
const reportsPeriodType = ref('all')
const reportsSelectedWeek = ref<Date | null>(null)
const reportsSelectedMonth = ref<Date | null>(null)
const reportsSelectedYear = ref<Date | null>(null)
const reportsSelectedHalfYear = ref('')
// 3
const halfYearOptions = computed(() => {
const options = []
const currentYear = new Date().getFullYear()
for (let year = currentYear; year >= currentYear - 2; year--) {
options.push({ label: `${year}年下半年`, value: `${year}-H2` })
options.push({ label: `${year}年上半年`, value: `${year}-H1` })
}
return options
})
const pagination = reactive({
pageNumber: 1,
pageSize: 10,
@ -633,7 +734,7 @@ function getTotalDistributed(): number {
function getTotalConsumed(): number {
// 使
if (authStore.canCreateAllocations && selectedPeriod.value !== 'all' && consumptionStats.value.length > 0) {
if (authStore.canCreateAllocations && consumptionStats.value.length > 0) {
return consumptionStats.value.reduce((sum: number, s) => sum + s.totalConsumed, 0)
}
// 使
@ -656,23 +757,106 @@ function getTotalProgressPercentage(): number {
//
const filteredDistributions = computed(() => {
if (!authStore.canCreateAllocations || selectedPeriod.value === 'all') {
if (!authStore.canCreateAllocations || (selectedPeriod.value === 'all' && periodType.value === 'all')) {
return distributions.value
}
// 使
return distributions.value.map(d => {
const stat = consumptionStats.value.find((s: UnitConsumptionStat) => s.unitId === d.targetUnitId)
if (stat) {
return {
...d,
actualCompletion: stat.totalConsumed,
completionRate: stat.completionRate
if (consumptionStats.value.length > 0) {
return distributions.value.map(d => {
const stat = consumptionStats.value.find((s: UnitConsumptionStat) => s.unitId === d.targetUnitId)
if (stat) {
return {
...d,
actualCompletion: stat.totalConsumed,
completionRate: stat.completionRate
}
}
}
return { ...d, actualCompletion: 0, completionRate: 0 }
})
return { ...d, actualCompletion: 0, completionRate: 0 }
})
}
return distributions.value
})
//
function handlePeriodTypeChange() {
//
selectedWeek.value = null
selectedMonth.value = null
selectedYear.value = null
selectedHalfYear.value = ''
if (periodType.value === 'all') {
selectedPeriod.value = 'all'
consumptionStats.value = []
}
}
//
async function handleDateChange() {
if (!selectedAllocation.value) return
let startDate: string | null = null
let endDate: string | null = null
if (periodType.value === 'week' && selectedWeek.value) {
//
const date = new Date(selectedWeek.value)
const day = date.getDay()
const diff = date.getDate() - day + (day === 0 ? -6 : 1) //
const monday = new Date(date.setDate(diff))
const sunday = new Date(monday)
sunday.setDate(monday.getDate() + 6)
startDate = formatDateParam(monday)
endDate = formatDateParam(sunday)
} else if (periodType.value === 'month' && selectedMonth.value) {
const date = new Date(selectedMonth.value)
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1)
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0)
startDate = formatDateParam(firstDay)
endDate = formatDateParam(lastDay)
} else if (periodType.value === 'halfYear' && selectedHalfYear.value) {
const [year, half] = selectedHalfYear.value.split('-')
if (half === 'H1') {
startDate = `${year}-01-01`
endDate = `${year}-06-30`
} else {
startDate = `${year}-07-01`
endDate = `${year}-12-31`
}
} else if (periodType.value === 'year' && selectedYear.value) {
const year = selectedYear.value.getFullYear()
startDate = `${year}-01-01`
endDate = `${year}-12-31`
}
if (!startDate || !endDate) return
selectedPeriod.value = 'custom'
loadingStats.value = true
try {
const response = await allocationsApi.getConsumptionStats(
selectedAllocation.value.id,
'custom',
startDate,
endDate
)
consumptionStats.value = response.unitStats
} catch (error) {
console.error('加载消耗统计失败', error)
ElMessage.error('加载消耗统计失败')
consumptionStats.value = []
} finally {
loadingStats.value = false
}
}
function formatDateParam(date: Date): string {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
async function handlePeriodChange() {
if (!selectedAllocation.value || selectedPeriod.value === 'all') {
consumptionStats.value = []
@ -732,6 +916,11 @@ async function handleViewReports(distribution: AllocationDistribution) {
showReportsDialog.value = true
reportsTabActive.value = 'summary'
reportsPeriod.value = 'all'
reportsPeriodType.value = 'all'
reportsSelectedWeek.value = null
reportsSelectedMonth.value = null
reportsSelectedYear.value = null
reportsSelectedHalfYear.value = ''
loadingReports.value = true
try {
//
@ -756,6 +945,76 @@ function getReportsTotalConsumed(): number {
return unitSummaries.value.reduce((sum, s) => sum + s.totalReported, 0)
}
//
function handleReportsPeriodTypeChange() {
reportsSelectedWeek.value = null
reportsSelectedMonth.value = null
reportsSelectedYear.value = null
reportsSelectedHalfYear.value = ''
if (reportsPeriodType.value === 'all') {
reportsPeriod.value = 'all'
handleReportsPeriodChange()
}
}
//
async function handleReportsDateChange() {
if (!selectedDistribution.value) return
let startDate: string | null = null
let endDate: string | null = null
if (reportsPeriodType.value === 'week' && reportsSelectedWeek.value) {
const date = new Date(reportsSelectedWeek.value)
const day = date.getDay()
const diff = date.getDate() - day + (day === 0 ? -6 : 1)
const monday = new Date(date.setDate(diff))
const sunday = new Date(monday)
sunday.setDate(monday.getDate() + 6)
startDate = formatDateParam(monday)
endDate = formatDateParam(sunday)
} else if (reportsPeriodType.value === 'month' && reportsSelectedMonth.value) {
const date = new Date(reportsSelectedMonth.value)
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1)
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0)
startDate = formatDateParam(firstDay)
endDate = formatDateParam(lastDay)
} else if (reportsPeriodType.value === 'halfYear' && reportsSelectedHalfYear.value) {
const [year, half] = reportsSelectedHalfYear.value.split('-')
if (half === 'H1') {
startDate = `${year}-01-01`
endDate = `${year}-06-30`
} else {
startDate = `${year}-07-01`
endDate = `${year}-12-31`
}
} else if (reportsPeriodType.value === 'year' && reportsSelectedYear.value) {
const year = reportsSelectedYear.value.getFullYear()
startDate = `${year}-01-01`
endDate = `${year}-12-31`
}
if (!startDate || !endDate) return
reportsPeriod.value = 'custom'
loadingReports.value = true
try {
const summaries = await allocationsApi.getReportSummaryByUnit(
selectedDistribution.value.id,
'custom',
startDate,
endDate
)
unitSummaries.value = summaries
} catch (error) {
console.error('加载上报记录失败', error)
ElMessage.error('加载上报记录失败')
} finally {
loadingReports.value = false
}
}
//
async function handleReportsPeriodChange() {
if (!selectedDistribution.value) return
@ -807,6 +1066,11 @@ async function loadAllocations() {
async function handleViewDistribution(allocation: MaterialAllocation) {
selectedAllocation.value = allocation
selectedPeriod.value = 'all'
periodType.value = 'all'
selectedWeek.value = null
selectedMonth.value = null
selectedYear.value = null
selectedHalfYear.value = ''
consumptionStats.value = []
//
if (authStore.canCreateAllocations) {