Files
shz-backend/docs/recruitment-fair-statistics-proposals.html

474 lines
25 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>招聘会数据统计 · 三套界面方案</title>
<style>
:root {
--ink: #1f2a44;
--muted: #74809a;
--line: #e7ebf2;
--blue: #2468f2;
--blue-soft: #eef4ff;
--mint: #0aa678;
--amber: #e58a00;
--violet: #7659df;
--card: #ffffff;
}
* { box-sizing: border-box; }
body {
margin: 0;
color: var(--ink);
background:
radial-gradient(circle at 82% 0%, #e7efff 0, transparent 24rem),
#f6f8fc;
font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
}
button, input, select { font: inherit; }
.page-shell { max-width: 1540px; margin: 0 auto; padding: 44px 28px 64px; }
.page-header {
display: flex;
align-items: end;
justify-content: space-between;
gap: 24px;
margin-bottom: 30px;
}
.eyebrow {
display: inline-flex;
align-items: center;
height: 26px;
padding: 0 10px;
border-radius: 999px;
color: #1959d1;
background: #eaf1ff;
font-weight: 700;
font-size: 12px;
letter-spacing: .06em;
}
h1, h2, h3, p { margin: 0; }
h1 { margin-top: 11px; font-size: 30px; line-height: 1.2; letter-spacing: -.03em; }
.page-intro { max-width: 600px; color: var(--muted); }
.rule-note {
display: flex;
gap: 12px;
padding: 14px 17px;
border: 1px solid #dce7ff;
border-radius: 12px;
background: rgba(255,255,255,.72);
color: #52617b;
}
.rule-dot { flex: 0 0 auto; width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--blue); }
.rule-note strong { color: #34425e; }
.proposal-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 20px; }
.proposal {
display: flex;
flex-direction: column;
min-width: 0;
overflow: hidden;
border: 1px solid #e4e9f1;
border-radius: 18px;
background: #fff;
box-shadow: 0 12px 30px rgba(38, 61, 104, .06);
}
.proposal-top { padding: 21px 22px 18px; border-bottom: 1px solid #edf0f5; }
.proposal-kicker { color: var(--blue); font-weight: 800; font-size: 12px; letter-spacing: .08em; }
.proposal-top h2 { margin-top: 5px; font-size: 20px; }
.proposal-summary { min-height: 42px; margin-top: 7px; color: var(--muted); font-size: 13px; }
.mockup {
position: relative;
flex: 1;
min-height: 646px;
padding: 18px;
background: #f7f9fc;
}
.ui-window {
min-height: 610px;
overflow: hidden;
border: 1px solid #e3e8f0;
border-radius: 10px;
background: var(--card);
box-shadow: 0 5px 15px rgba(23, 44, 78, .06);
}
.ui-titlebar {
display: flex;
align-items: center;
justify-content: space-between;
min-height: 53px;
padding: 0 17px;
border-bottom: 1px solid #edf0f5;
}
.ui-title { font-size: 16px; font-weight: 700; }
.quiet { color: #9aa6ba; font-size: 12px; }
.segment {
display: inline-flex;
padding: 3px;
gap: 2px;
border-radius: 7px;
background: #f1f4f9;
}
.segment button {
height: 28px;
padding: 0 11px;
cursor: pointer;
border: 0;
border-radius: 5px;
color: #66738c;
background: transparent;
white-space: nowrap;
}
.segment button.active { color: #1459df; background: #fff; font-weight: 700; box-shadow: 0 1px 3px rgba(29, 58, 100, .12); }
.segment button:focus-visible, .choose-button:focus-visible, .selection-button:focus-visible { outline: 3px solid #9ec1ff; outline-offset: 2px; }
.filter-row { display: flex; flex-wrap: wrap; gap: 8px; padding: 14px 16px; border-bottom: 1px solid #edf0f5; }
.field {
display: inline-flex;
align-items: center;
min-height: 31px;
padding: 0 9px;
border: 1px solid #dde4ef;
border-radius: 5px;
color: #56647c;
background: #fff;
font-size: 12px;
white-space: nowrap;
}
.field.primary { border-color: #8eb4ff; color: #1f60d5; background: #f8fbff; }
.field .chevron { margin-left: 10px; color: #a2afc2; }
.filter-label { align-self: center; color: #8390a5; font-size: 12px; }
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 9px; }
.stat-card { min-width: 0; padding: 13px 12px; border: 1px solid #ebeff5; border-radius: 7px; background: #fff; }
.stat-card dt { overflow: hidden; color: #7c89a0; font-size: 12px; white-space: nowrap; text-overflow: ellipsis; }
.stat-card dd { margin: 7px 0 0; color: #263757; font-weight: 800; font-size: 24px; line-height: 1; letter-spacing: -.04em; }
.stat-card dd small { margin-left: 2px; color: #8995a9; font-weight: 500; font-size: 11px; letter-spacing: 0; }
.stat-card.accent { border-color: #d7e5ff; background: #f6f9ff; }
.stat-card.accent dd { color: #1b61e7; }
.data-block { margin: 14px 16px 0; border: 1px solid #e9edf4; border-radius: 7px; }
.block-head { display: flex; align-items: center; justify-content: space-between; min-height: 40px; padding: 0 12px; border-bottom: 1px solid #edf0f4; font-size: 13px; font-weight: 700; }
.block-head a { color: #3975e8; font-size: 12px; font-weight: 500; text-decoration: none; }
.rows { padding: 1px 12px; }
.data-row { display: flex; align-items: center; justify-content: space-between; min-height: 36px; border-bottom: 1px solid #f0f2f6; color: #59667e; font-size: 12px; }
.data-row:last-child { border: 0; }
.rank { display: inline-flex; justify-content: center; width: 17px; margin-right: 8px; border-radius: 3px; color: #fff; background: #aab6c8; font-weight: 800; font-size: 10px; }
.rank.top { background: #f19a22; }
.row-value { color: #2f405e; font-weight: 700; }
/* Plan A */
.plan-a .ui-window { border-radius: 8px; }
.plan-a .filter-row { align-items: center; }
.plan-a .stat-wrap { padding: 17px 16px 2px; }
.hint-line { padding: 9px 16px 0; color: #8995a7; font-size: 11px; }
.hint-line b { color: #2564db; }
/* Plan B */
.plan-b .mockup { padding: 14px; background: #f1f5fb; }
.plan-b .ui-window { display: grid; grid-template-columns: 126px minmax(0, 1fr); min-height: 610px; border-radius: 12px; }
.side-nav { padding: 16px 10px; border-right: 1px solid #ebeff5; background: #fbfcfe; }
.brand { display: flex; align-items: center; gap: 7px; margin: 0 5px 23px; color: #34425b; font-weight: 800; font-size: 12px; }
.brand-mark { width: 18px; height: 18px; border-radius: 5px; background: linear-gradient(135deg, #416ff0, #7e75ea); }
.nav-group { margin: 17px 5px 6px; color: #9aa6ba; font-size: 10px; letter-spacing: .08em; }
.nav-item { display: flex; align-items: center; gap: 7px; padding: 8px 7px; border-radius: 5px; color: #69758a; font-size: 12px; }
.nav-item.active { color: #245cda; background: #ebf2ff; font-weight: 700; }
.nav-icon { width: 11px; height: 11px; border: 1.5px solid currentColor; border-radius: 3px; opacity: .75; }
.work-area { min-width: 0; }
.plan-b .ui-titlebar { padding: 0 14px; }
.plan-b .ui-title { font-size: 15px; }
.plan-b .filter-row { padding: 12px 13px; gap: 6px; }
.plan-b .field { padding: 0 7px; font-size: 11px; }
.plan-b .scope-label { width: 100%; margin-top: 3px; color: #8490a3; font-size: 11px; }
.scope-pills { display: inline-flex; gap: 5px; }
.scope-pill { padding: 4px 7px; border-radius: 999px; color: #647188; background: #f2f5f9; font-size: 11px; }
.scope-pill.active { color: #1762d7; background: #eaf2ff; font-weight: 700; }
.plan-b .stat-wrap { padding: 14px 13px 0; }
.plan-b .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 7px; }
.plan-b .stat-card { padding: 10px; }
.plan-b .stat-card dd { font-size: 21px; }
.mini-chart { display: flex; align-items: flex-end; gap: 5px; height: 102px; padding: 18px 12px 12px; }
.bar { flex: 1; min-width: 10px; border-radius: 3px 3px 0 0; background: linear-gradient(180deg, #78a4ff, #3e73ef); }
.bar.muted { background: #dbe6fd; }
.chart-note { display: flex; justify-content: space-between; padding: 0 12px 11px; color: #929eb1; font-size: 10px; }
/* Plan C */
.plan-c .mockup { padding: 15px; background: #f5f6fb; }
.plan-c .ui-window { border: 0; border-radius: 14px; box-shadow: 0 8px 24px rgba(41, 53, 89, .08); }
.plan-c .ui-titlebar { min-height: 58px; padding: 0 17px; border: 0; }
.plan-c .ui-title { font-size: 17px; }
.plan-c .filter-row { padding: 0 17px 15px; border: 0; }
.mode-card { display: flex; align-items: center; justify-content: space-between; margin: 0 17px; padding: 12px 13px; border-radius: 9px; background: linear-gradient(102deg, #eff5ff, #f7f3ff); }
.mode-card .mode-title { color: #435373; font-size: 12px; }
.mode-card .mode-title strong { display: block; margin-top: 2px; color: #263858; font-size: 13px; }
.calendar-chip { padding: 5px 7px; border: 1px solid #d8e4f9; border-radius: 5px; color: #4770b7; background: rgba(255,255,255,.6); font-size: 11px; }
.plan-c .stat-wrap { padding: 16px 17px 1px; }
.plan-c .stat-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
.plan-c .stat-card { min-height: 77px; padding: 11px; border: 0; border-radius: 9px; background: #f7f8fb; }
.plan-c .stat-card.accent { background: #edf4ff; }
.plan-c .stat-card dd { font-size: 23px; }
.insight { display: flex; gap: 10px; align-items: flex-start; margin: 14px 17px; padding: 11px 12px; border-radius: 8px; color: #55709d; background: #f5f8fe; font-size: 11px; }
.insight-mark { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 18px; height: 18px; border-radius: 50%; color: #fff; background: #5c85e8; font-weight: 800; font-size: 11px; }
.plan-c .data-block { margin: 0 17px; }
.proposal-footer { display: flex; gap: 9px; align-items: center; justify-content: space-between; padding: 15px 22px 19px; border-top: 1px solid #edf0f5; }
.pros { color: #65728a; font-size: 12px; }
.pros strong { color: #3c4960; }
.choose-button { min-width: 104px; height: 34px; cursor: pointer; border: 1px solid #cdddfb; border-radius: 6px; color: #225fd6; background: #f6f9ff; font-weight: 700; font-size: 12px; }
.proposal.is-chosen { border-color: #81a9f6; box-shadow: 0 14px 34px rgba(41, 93, 194, .14); }
.proposal.is-chosen .choose-button { border-color: var(--blue); color: #fff; background: var(--blue); }
.selection-button { display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 14px; cursor: pointer; border: 0; border-radius: 8px; color: #fff; background: #263858; font-weight: 700; }
.selection-button .status { display: none; width: 6px; height: 6px; border-radius: 50%; background: #92edc8; }
.selection-button.has-choice .status { display: block; }
.online-only, .outdoor-only { transition: opacity .16s ease; }
.outdoor-only { display: none; }
.is-outdoor .online-only { display: none; }
.is-outdoor .outdoor-only { display: block; }
.is-outdoor .outdoor-only.inline { display: inline; }
@media (max-width: 1160px) {
.proposal-grid { grid-template-columns: 1fr; max-width: 620px; margin: 0 auto; }
.mockup { min-height: auto; }
.ui-window { min-height: 540px; }
}
@media (max-width: 680px) {
.page-shell { padding: 28px 16px 40px; }
.page-header { display: block; }
.page-intro { margin-top: 12px; }
.rule-note { margin-top: 16px; }
.proposal-top, .proposal-footer { padding-right: 16px; padding-left: 16px; }
.mockup { padding: 10px; }
.stat-grid { grid-template-columns: repeat(2, 1fr); }
.plan-b .ui-window { grid-template-columns: 102px minmax(0, 1fr); }
.side-nav { padding-right: 7px; padding-left: 7px; }
.brand { margin-left: 2px; margin-right: 2px; }
}
</style>
</head>
<body>
<main class="page-shell">
<header class="page-header">
<div>
<span class="eyebrow">UI PROPOSAL · 0103</span>
<h1>招聘会数据统计</h1>
<p class="page-intro">三套后台菜单界面方案。每套均支持按单场招聘会统计,或按招聘会起始时间统计时间段汇总。</p>
</div>
<button class="selection-button" id="selectionStatus" type="button" aria-live="polite"><i class="status"></i><span>尚未选择方案</span></button>
</header>
<aside class="rule-note" aria-label="统计口径说明">
<i class="rule-dot"></i>
<div><strong>统一统计口径:</strong>需求人数取岗位“招聘数”;招聘数填写“若干”时按 <strong>1 人</strong>计算。线上招聘会展示「投递岗位数」,户外招聘会展示「签到数」;户外招聘会不提供报名投递简历。</div>
</aside>
<section class="proposal-grid" aria-label="招聘会数据统计界面方案">
<article class="proposal plan-a" data-plan="方案一:标准后台统计页">
<header class="proposal-top">
<div class="proposal-kicker">方案一 / 标准清晰</div>
<h2>标准后台统计页</h2>
<p class="proposal-summary">筛选区、指标卡、明细区层次分明,最贴近常规管理后台的使用习惯。</p>
</header>
<div class="mockup is-online" data-mockup>
<div class="ui-window">
<div class="ui-titlebar">
<div class="ui-title">招聘会数据统计</div>
<div class="segment" aria-label="招聘会类型">
<button class="active" type="button" data-type="online">线上招聘会</button>
<button type="button" data-type="outdoor">户外招聘会</button>
</div>
</div>
<div class="filter-row">
<span class="filter-label">统计范围</span>
<span class="field primary">单场招聘会 <span class="chevron"></span></span>
<span class="field">2026 年春风行动线上招聘会 <span class="chevron"></span></span>
<span class="field">查询</span>
</div>
<div class="hint-line">也可切换为 <b>按起始时间统计</b>,选择起始日期与结束日期后汇总多场招聘会。</div>
<div class="stat-wrap">
<dl class="stat-grid">
<div class="stat-card"><dt>参会单位数</dt><dd>128<small></small></dd></div>
<div class="stat-card"><dt>职位数</dt><dd>356<small></small></dd></div>
<div class="stat-card"><dt>需求人数</dt><dd>1,024<small></small></dd></div>
<div class="stat-card accent online-only"><dt>投递岗位数</dt><dd>687<small></small></dd></div>
<div class="stat-card accent outdoor-only"><dt>签到数</dt><dd>932<small>人次</small></dd></div>
</dl>
</div>
<section class="data-block" aria-label="招聘会明细">
<div class="block-head"><span>本次统计涉及招聘会</span><a href="javascript:void(0)">查看列表</a></div>
<div class="rows">
<div class="data-row"><span>2026 年春风行动<span class="outdoor-only inline">户外</span><span class="online-only inline">线上</span>招聘会</span><span class="row-value">128 家 / 356 职位</span></div>
<div class="data-row"><span>起始时间</span><span class="row-value">2026-03-07</span></div>
<div class="data-row online-only"><span>投递最热岗位</span><span class="row-value">行政专员 · 54 次</span></div>
<div class="data-row outdoor-only"><span>签到高峰时段</span><span class="row-value">10:0011:00 · 328 人次</span></div>
</div>
</section>
</div>
</div>
<footer class="proposal-footer">
<p class="pros"><strong>适合:</strong>快速上线、表单操作优先</p>
<button class="choose-button" type="button">选择方案一</button>
</footer>
</article>
<article class="proposal plan-b" data-plan="方案二:数据工作台">
<header class="proposal-top">
<div class="proposal-kicker">方案二 / 数据工作台</div>
<h2>侧栏式数据工作台</h2>
<p class="proposal-summary">把“统计范围”作为核心入口,兼顾当场查看与时间段分析。</p>
</header>
<div class="mockup is-online" data-mockup>
<div class="ui-window">
<aside class="side-nav">
<div class="brand"><i class="brand-mark"></i>就业服务</div>
<div class="nav-group">招聘会管理</div>
<div class="nav-item"><i class="nav-icon"></i>招聘会列表</div>
<div class="nav-item active"><i class="nav-icon"></i>数据统计</div>
<div class="nav-group">常用功能</div>
<div class="nav-item"><i class="nav-icon"></i>单位管理</div>
</aside>
<div class="work-area">
<div class="ui-titlebar"><div class="ui-title">招聘会数据统计</div><span class="quiet">数据更新时间 10:30</span></div>
<div class="filter-row">
<div class="segment" aria-label="招聘会类型">
<button class="active" type="button" data-type="online">线上</button>
<button type="button" data-type="outdoor">户外</button>
</div>
<span class="field">招聘会名称 <span class="chevron"></span></span>
<span class="scope-label">统计方式</span>
<div class="scope-pills"><span class="scope-pill active">统计单场</span><span class="scope-pill">按起始时间段</span></div>
<span class="field">2026-03-01 至 2026-03-31</span>
</div>
<div class="stat-wrap">
<dl class="stat-grid">
<div class="stat-card"><dt>参会单位</dt><dd>128<small></small></dd></div>
<div class="stat-card"><dt>职位数</dt><dd>356<small></small></dd></div>
<div class="stat-card"><dt>需求人数</dt><dd>1,024<small></small></dd></div>
<div class="stat-card accent online-only"><dt>投递岗位</dt><dd>687<small></small></dd></div>
<div class="stat-card accent outdoor-only"><dt>签到数</dt><dd>932<small>人次</small></dd></div>
</dl>
</div>
<section class="data-block" aria-label="趋势概览">
<div class="block-head"><span class="online-only">投递岗位趋势</span><span class="outdoor-only">现场签到趋势</span><a href="javascript:void(0)">按日查看</a></div>
<div class="mini-chart" aria-label="近七天统计柱状图">
<i class="bar muted" style="height:31%"></i><i class="bar muted" style="height:48%"></i><i class="bar" style="height:72%"></i><i class="bar muted" style="height:53%"></i><i class="bar" style="height:88%"></i><i class="bar" style="height:63%"></i><i class="bar muted" style="height:41%"></i>
</div>
<div class="chart-note"><span>03/01</span><span>03/07</span><span>03/14</span><span>03/21</span><span>03/31</span></div>
</section>
<section class="data-block" aria-label="招聘会排行">
<div class="block-head"><span>招聘会数据排行</span><a href="javascript:void(0)">更多</a></div>
<div class="rows">
<div class="data-row"><span><i class="rank top">1</i>春风行动专场</span><span class="row-value online-only">154 次投递</span><span class="row-value outdoor-only">246 人签到</span></div>
<div class="data-row"><span><i class="rank">2</i>民营企业专场</span><span class="row-value online-only">122 次投递</span><span class="row-value outdoor-only">211 人签到</span></div>
</div>
</section>
</div>
</div>
</div>
<footer class="proposal-footer">
<p class="pros"><strong>适合:</strong>后续扩展趋势、排行分析</p>
<button class="choose-button" type="button">选择方案二</button>
</footer>
</article>
<article class="proposal plan-c" data-plan="方案三:概览看板">
<header class="proposal-top">
<div class="proposal-kicker">方案三 / 概览看板</div>
<h2>轻量概览看板</h2>
<p class="proposal-summary">将范围、类型和核心结果集中在首屏,更适合高频查数和汇报浏览。</p>
</header>
<div class="mockup is-online" data-mockup>
<div class="ui-window">
<div class="ui-titlebar">
<div class="ui-title">招聘会数据统计</div>
<div class="segment" aria-label="招聘会类型">
<button class="active" type="button" data-type="online">线上招聘会</button>
<button type="button" data-type="outdoor">户外招聘会</button>
</div>
</div>
<div class="filter-row">
<span class="field primary">统计单场 <span class="chevron"></span></span>
<span class="field">选择招聘会 <span class="chevron"></span></span>
</div>
<section class="mode-card" aria-label="统计范围">
<div class="mode-title">当前统计范围<strong>2026 年春风行动<span class="online-only">线上</span><span class="outdoor-only">户外</span>招聘会</strong></div>
<span class="calendar-chip">起始 2026-03-07</span>
</section>
<div class="stat-wrap">
<dl class="stat-grid">
<div class="stat-card"><dt>参会单位数</dt><dd>128<small></small></dd></div>
<div class="stat-card"><dt>职位数</dt><dd>356<small></small></dd></div>
<div class="stat-card"><dt>需求人数</dt><dd>1,024<small></small></dd></div>
<div class="stat-card accent online-only"><dt>投递岗位数</dt><dd>687<small></small></dd></div>
<div class="stat-card accent outdoor-only"><dt>签到数</dt><dd>932<small>人次</small></dd></div>
</dl>
</div>
<div class="insight online-only"><i class="insight-mark">i</i><span>本场招聘会共有 <b>356</b> 个岗位获得投递,其中 687 个岗位投递记录已去重汇总。</span></div>
<div class="insight outdoor-only"><i class="insight-mark">i</i><span>户外招聘会不提供报名投递简历,现场到场数据以签到记录累计为准。</span></div>
<section class="data-block" aria-label="统计口径">
<div class="block-head"><span>统计说明</span><span class="quiet">自动汇总</span></div>
<div class="rows">
<div class="data-row"><span>单位与职位</span><span>按有效参会单位及岗位统计</span></div>
<div class="data-row"><span>需求人数</span><span>“若干”按 1 人计算</span></div>
<div class="data-row online-only"><span>投递岗位数</span><span>按投递岗位汇总</span></div>
<div class="data-row outdoor-only"><span>签到数</span><span>按现场签到累计</span></div>
</div>
</section>
</div>
</div>
<footer class="proposal-footer">
<p class="pros"><strong>适合:</strong>领导查数、手机端兼容</p>
<button class="choose-button" type="button">选择方案三</button>
</footer>
</article>
</section>
</main>
<script>
document.querySelectorAll('[data-mockup]').forEach(function (mockup) {
mockup.querySelectorAll('[data-type]').forEach(function (button) {
button.addEventListener('click', function () {
var outdoor = button.dataset.type === 'outdoor';
mockup.classList.toggle('is-outdoor', outdoor);
mockup.classList.toggle('is-online', !outdoor);
mockup.querySelectorAll('[data-type]').forEach(function (item) {
item.classList.toggle('active', item === button);
});
});
});
});
var selectionStatus = document.getElementById('selectionStatus');
document.querySelectorAll('.choose-button').forEach(function (button) {
button.addEventListener('click', function () {
var proposal = button.closest('.proposal');
document.querySelectorAll('.proposal').forEach(function (item) {
item.classList.toggle('is-chosen', item === proposal);
item.querySelector('.choose-button').textContent = item === proposal ? '已选择' : '选择' + item.dataset.plan.match(/方案[一二三]/)[0];
});
selectionStatus.classList.add('has-choice');
selectionStatus.querySelector('span').textContent = '已选择:' + proposal.dataset.plan;
});
});
</script>
</body>
</html>