feat(management): client补员工详情/分段接口+时间预设补今日昨日本周上周
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -70,3 +70,33 @@ export const getEmployees = (params: Record<string, unknown>) =>
|
||||
export const getEmployeeDrilldown = (userId: string, metricCode: DrilldownCode, start: number, end: number, channel: MgmtChannel, page = 1, pageSize = 20) =>
|
||||
getJson<DrilldownResp>(`/management/employees/${userId}/drilldown`, { metric_code: metricCode, start, end, channel, page, page_size: pageSize })
|
||||
export const getMetricDefs = () => getJson<MetricDefsResp>('/management/metric-definitions')
|
||||
|
||||
// ---- 批次D:员工详情 + 分段指标(契约已真机 8000 抽查核对,见上) ----
|
||||
export interface EmployeeAccount { channel: string; account_id: string; nick_name: string | null; user_name: string | null }
|
||||
export interface ScoreMetricDetail { value: number | null; prev: number | null; baseline: number | null; median: number | null; sample_size: number; sample_status: string; score: number | null; unit: string; name: string }
|
||||
// formula_note 在 dimensions[dim].metrics[code] 上(scoring 维度级明细),不在 metrics_detail
|
||||
export interface EmployeeDetailResp {
|
||||
user_id: string; name: string | null; is_on_job: boolean | null
|
||||
accounts: EmployeeAccount[]
|
||||
metrics: Record<string, number | string | null>
|
||||
score: {
|
||||
total_score: number | null; grade: string | null; score_status: string; trial: boolean
|
||||
dimensions: Record<string, { name: string; weight: number; score: number | null; status: string; metrics?: Record<string, { value: number | null; score: number | null; sample_size: number; sample_status: string; formula_note?: string }> }>
|
||||
metrics_detail: Record<string, ScoreMetricDetail>
|
||||
}
|
||||
anomalies: AnomalyCard[]
|
||||
prev: Record<string, number | string | null> | null
|
||||
baseline: Record<string, number | string | null> | null
|
||||
scope: MgmtScope; data_as_of: number | null; metric_version: string; config_source: 'db' | 'default'
|
||||
}
|
||||
export interface SectionResp {
|
||||
section: string; metrics: Record<string, number | null>
|
||||
trend: Record<string, number | null>[]
|
||||
comparisons: Record<string, { current: number | null; prev: number | null; baseline: number | null; median: number | null }>
|
||||
scope: MgmtScope; data_as_of: number | null; metric_version: string
|
||||
}
|
||||
export type MetricsSection = 'overview' | 'service' | 'customer' | 'workload' | 'calls'
|
||||
export const getEmployeeDetail = (userId: string, channel: MgmtChannel, start: number, end: number) =>
|
||||
getJson<EmployeeDetailResp>(`/management/employees/${userId}`, { channel, start, end })
|
||||
export const getEmployeeMetrics = (userId: string, section: MetricsSection, channel: MgmtChannel, start: number, end: number) =>
|
||||
getJson<SectionResp>(`/management/employees/${userId}/metrics`, { section, channel, start, end })
|
||||
|
||||
@@ -10,10 +10,18 @@
|
||||
placeholder="近30天"
|
||||
@change="onPresetChange"
|
||||
>
|
||||
<el-option-group label="常用">
|
||||
<el-option label="今日" value="today" />
|
||||
<el-option label="昨日" value="yesterday" />
|
||||
<el-option label="近7天" value="last7" />
|
||||
<el-option label="近30天" value="last30" />
|
||||
</el-option-group>
|
||||
<el-option-group label="日历">
|
||||
<el-option label="本周" value="thisWeek" />
|
||||
<el-option label="上周" value="lastWeek" />
|
||||
<el-option label="本月" value="thisMonth" />
|
||||
<el-option label="上月" value="lastMonth" />
|
||||
</el-option-group>
|
||||
<el-option label="自定义" value="custom" />
|
||||
</el-select>
|
||||
|
||||
|
||||
@@ -50,6 +50,26 @@ describe('presetRange(注入 today,确定性日期)', () => {
|
||||
expect(presetRange('lastMonth', D(20260115))).toEqual({ start: 20251201, end: 20251231 })
|
||||
})
|
||||
|
||||
it('today → 今天单日(2026-09-10 → 20260910..20260910)', () => {
|
||||
expect(presetRange('today', D(20260910))).toEqual({ start: 20260910, end: 20260910 })
|
||||
})
|
||||
|
||||
it('yesterday → 昨日单日(2026-09-10 → 20260909..20260909)', () => {
|
||||
expect(presetRange('yesterday', D(20260910))).toEqual({ start: 20260909, end: 20260909 })
|
||||
})
|
||||
|
||||
it('thisWeek 周中(2026-07-02 周四 → 周一到今天 20260629..20260702)', () => {
|
||||
expect(presetRange('thisWeek', D(20260702))).toEqual({ start: 20260629, end: 20260702 })
|
||||
})
|
||||
|
||||
it('thisWeek 周一当天 → 单日(2026-06-29 周一 → 20260629..20260629)', () => {
|
||||
expect(presetRange('thisWeek', D(20260629))).toEqual({ start: 20260629, end: 20260629 })
|
||||
})
|
||||
|
||||
it('lastWeek 跨月边界(2026-07-02 周四 → 上周一..上周日 20260622..20260628)', () => {
|
||||
expect(presetRange('lastWeek', D(20260702))).toEqual({ start: 20260622, end: 20260628 })
|
||||
})
|
||||
|
||||
it('custom → 今天单日兜底(2026-09-10 → 20260910..20260910)', () => {
|
||||
expect(presetRange('custom', D(20260910))).toEqual({ start: 20260910, end: 20260910 })
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
||||
export type Preset = 'last7' | 'last30' | 'thisMonth' | 'lastMonth' | 'custom'
|
||||
export type Preset = 'today' | 'yesterday' | 'last7' | 'last30' | 'thisWeek' | 'lastWeek' | 'thisMonth' | 'lastMonth' | 'custom'
|
||||
export const CHANNELS = [
|
||||
{ value: 'all', label: '全部渠道' },
|
||||
{ value: 'wechat', label: '微信' },
|
||||
@@ -22,7 +22,20 @@ function addDays(d: Date, n: number): Date {
|
||||
/** 预设 → [start,end] yyyymmdd。 */
|
||||
export function presetRange(p: Preset, today = new Date()): { start: number; end: number } {
|
||||
const t0 = new Date(today.getFullYear(), today.getMonth(), today.getDate())
|
||||
// 周一为一周起点(getDay 周日=0 → 偏移成周一=0..周日=6)
|
||||
const dow = (t0.getDay() + 6) % 7
|
||||
switch (p) {
|
||||
case 'today':
|
||||
return { start: ymd(t0), end: ymd(t0) }
|
||||
case 'yesterday':
|
||||
return { start: ymd(addDays(t0, -1)), end: ymd(addDays(t0, -1)) }
|
||||
case 'thisWeek':
|
||||
// 周一..今天;周一当天即单日
|
||||
return { start: ymd(addDays(t0, -dow)), end: ymd(t0) }
|
||||
case 'lastWeek': {
|
||||
const monday = addDays(t0, -dow - 7)
|
||||
return { start: ymd(monday), end: ymd(addDays(monday, 6)) }
|
||||
}
|
||||
case 'last7':
|
||||
return { start: ymd(addDays(t0, -6)), end: ymd(t0) }
|
||||
case 'last30':
|
||||
|
||||
Reference in New Issue
Block a user