feat(M08-B): 补保洁统计明细
This commit is contained in:
@@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<section class="panel">
|
||||
<div class="panel-toolbar">
|
||||
<el-form class="stats-filter" label-position="top">
|
||||
<el-form-item label="开始">
|
||||
<el-input v-model="filterDraft.from" placeholder="2026-06-01" />
|
||||
</el-form-item>
|
||||
<el-form-item label="结束">
|
||||
<el-input v-model="filterDraft.to" placeholder="2026-07-01" />
|
||||
</el-form-item>
|
||||
<el-form-item label="门店 ID">
|
||||
<el-input v-model="filterDraft.storeId" inputmode="numeric" />
|
||||
</el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="emitFilter">查询</el-button>
|
||||
</el-form>
|
||||
<el-tooltip content="刷新统计">
|
||||
<el-button :icon="RefreshCw" :loading="loading" circle @click="$emit('refresh')" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div class="stats-body" v-loading="loading">
|
||||
<section class="metric-grid compact" aria-label="统计概览">
|
||||
<div class="metric">
|
||||
<span>任务总数</span>
|
||||
<strong>{{ statistics.summary.taskTotal }}</strong>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span>待验收</span>
|
||||
<strong>{{ statistics.summary.pendingReview }}</strong>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span>待结算</span>
|
||||
<strong>{{ money(statistics.summary.pendingSettlementCents) }}</strong>
|
||||
</div>
|
||||
<div class="metric">
|
||||
<span>已发放</span>
|
||||
<strong>{{ money(statistics.summary.paidSettlementCents) }}</strong>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="stats-grid">
|
||||
<section class="stat-block">
|
||||
<header>
|
||||
<h3>任务状态</h3>
|
||||
<span>{{ money(statistics.summary.rewardCents) }}</span>
|
||||
</header>
|
||||
<el-table :data="statistics.byStatus" size="small">
|
||||
<el-table-column prop="status" label="状态" />
|
||||
<el-table-column prop="total" label="数量" width="90" />
|
||||
<el-table-column prop="rewardCents" label="奖励" width="120">
|
||||
<template #default="{ row }">{{ money(row.rewardCents) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
<section class="stat-block">
|
||||
<header>
|
||||
<h3>结算口径</h3>
|
||||
<span>待发 {{ money(statistics.summary.confirmedSettlementCents) }}</span>
|
||||
</header>
|
||||
<el-table :data="statistics.settlements" size="small">
|
||||
<el-table-column prop="status" label="状态" />
|
||||
<el-table-column prop="total" label="单数" width="90" />
|
||||
<el-table-column prop="rewardCents" label="金额" width="120">
|
||||
<template #default="{ row }">{{ money(row.rewardCents) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="stat-block">
|
||||
<header>
|
||||
<h3>门店明细</h3>
|
||||
<span>按待验收优先</span>
|
||||
</header>
|
||||
<el-table :data="statistics.byStore" size="small">
|
||||
<el-table-column prop="storeName" label="门店" min-width="150" />
|
||||
<el-table-column prop="taskTotal" label="任务" width="90" />
|
||||
<el-table-column prop="pendingReview" label="待验" width="90" />
|
||||
<el-table-column prop="completed" label="完成" width="90" />
|
||||
<el-table-column prop="rejected" label="驳回" width="90" />
|
||||
<el-table-column prop="rewardCents" label="奖励" width="120">
|
||||
<template #default="{ row }">{{ money(row.rewardCents) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
|
||||
<section class="stat-block">
|
||||
<header>
|
||||
<h3>成员分账</h3>
|
||||
<span>按待结算金额排序</span>
|
||||
</header>
|
||||
<el-table :data="statistics.members" size="small">
|
||||
<el-table-column prop="cleanerName" label="保洁员" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<div class="stack">
|
||||
<strong>{{ row.cleanerName || compactText(row.cleanerUserId) }}</strong>
|
||||
<span>ID {{ row.cleanerUserId }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="taskCount" label="任务" width="90" />
|
||||
<el-table-column prop="pendingSettlementCents" label="待结算" width="130">
|
||||
<template #default="{ row }">{{ money(row.pendingSettlementCents) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="settledRewardCents" label="已结算" width="130">
|
||||
<template #default="{ row }">{{ money(row.settledRewardCents) }}</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, watch } from 'vue';
|
||||
import { RefreshCw, Search } from '@lucide/vue';
|
||||
import { compactText, money } from '../format';
|
||||
import type { CleaningStatistics } from '../types';
|
||||
|
||||
const props = defineProps<{
|
||||
loading: boolean;
|
||||
statistics: CleaningStatistics;
|
||||
filters: { from: string; to: string; storeId: string };
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
refresh: [];
|
||||
filter: [{ from: string; to: string; storeId: string }];
|
||||
}>();
|
||||
|
||||
const filterDraft = reactive({ ...props.filters });
|
||||
|
||||
watch(
|
||||
() => props.filters,
|
||||
(value) => Object.assign(filterDraft, value),
|
||||
{ deep: true }
|
||||
);
|
||||
|
||||
function emitFilter() {
|
||||
emit('filter', {
|
||||
from: filterDraft.from.trim(),
|
||||
to: filterDraft.to.trim(),
|
||||
storeId: filterDraft.storeId.trim()
|
||||
});
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user