Files
zkxw/mobile-ui/zkxw-mobile-oa-progress-withdraw-cancelled-demo.html
T
2026-08-13 14:31:57 +08:00

535 lines
21 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, maximum-scale=1" />
<title>mobile-oa-h5 · 撤销后审批进度展示 Demo</title>
<style>
:root {
--brand: #0a9f6d;
--brand-dark: #087f57;
--page-bg: #f5f8f7;
--text: #1f2a26;
--text-muted: #6b7b74;
--border: #dcebe4;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: "PingFang SC", "Hiragino Sans GB", "Noto Sans SC", -apple-system, system-ui, sans-serif;
color: var(--text);
background:
radial-gradient(900px 420px at 8% -8%, rgba(10, 159, 109, 0.12), transparent 55%),
radial-gradient(700px 380px at 92% 0%, rgba(214, 163, 67, 0.1), transparent 50%),
linear-gradient(180deg, #f8fffc 0%, #f4f7fb 50%, #f7f8fa 100%);
line-height: 1.45;
}
.stage { max-width: 1320px; margin: 0 auto; padding: 28px 16px 64px; }
.hero h1 { margin: 0 0 8px; font-size: 22px; font-weight: 720; }
.hero p { margin: 0; color: #64748b; font-size: 14px; max-width: 960px; }
.goals {
margin-top: 14px; padding: 12px 14px; border-radius: 12px;
background: #ecfdf5; border: 1px solid #a7f3d0;
font-size: 13px; color: #065f46;
}
.goals ul { margin: 6px 0 0; padding-left: 18px; }
.scene {
margin-top: 16px; padding: 12px 14px; border-radius: 12px;
background: #fff; border: 1px solid #e2e8f0; font-size: 13px; color: #334155;
}
.scene code {
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 12px; background: #f1f5f9; padding: 1px 6px; border-radius: 4px;
}
.grid {
margin-top: 22px;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 18px;
align-items: start;
}
.card {
background: rgba(255,255,255,.94);
border: 1px solid #e2e8f0;
border-radius: 16px;
padding: 14px;
box-shadow: 0 10px 28px rgba(15,23,42,.05);
}
.card h2 {
margin: 0 0 4px;
font-size: 15px;
display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.card .sub { margin: 0 0 12px; font-size: 12px; color: #64748b; }
.pill {
display: inline-block; padding: 2px 8px; border-radius: 999px;
font-size: 10px; font-weight: 700; letter-spacing: 0.02em;
}
.pill.now { background: #fff1f2; color: #be123c; border: 1px solid #fecdd3; }
.pill.rec { background: #ecfdf5; color: #047857; border: 1px solid #a7f3d0; }
.pill.alt { background: #eff6ff; color: #1d4ed8; border: 1px solid #bfdbfe; }
.phone {
width: 100%; max-width: 360px; margin: 0 auto;
border-radius: 28px; border: 1px solid #cbd5e1; background: #0f172a;
padding: 10px; box-shadow: 0 18px 40px rgba(15,23,42,.12);
}
.phone__screen {
border-radius: 20px; overflow: hidden; background: var(--page-bg);
min-height: 460px; display: flex; flex-direction: column;
}
.nav {
display: flex; align-items: center; gap: 8px; min-height: 48px;
padding: 10px 12px;
background: linear-gradient(180deg, #d1fae5 0%, #ecfdf5 100%);
border-bottom: 1px solid #bbf7d0;
}
.nav__back {
width: 28px; height: 28px; border-radius: 999px;
display: grid; place-items: center;
color: var(--brand-dark); font-weight: 700; font-size: 16px;
background: rgba(255,255,255,.55);
}
.nav__title { flex: 1; font-size: 15px; font-weight: 700; color: #064e3b; }
.body { padding: 12px; display: grid; gap: 10px; }
.stamp-row {
position: relative;
background: #fff; border: 1px solid var(--border);
border-radius: 12px; padding: 12px 14px;
overflow: hidden;
}
.stamp-row__meta { font-size: 12px; color: var(--text-muted); }
.stamp-row__title { margin-top: 4px; font-size: 15px; font-weight: 700; }
.stamp {
position: absolute; right: 10px; top: 8px;
width: 64px; height: 64px; border-radius: 50%;
border: 2px solid #be123c; color: #be123c;
display: grid; place-items: center;
font-size: 13px; font-weight: 800;
transform: rotate(-18deg);
opacity: .85;
background: rgba(255,241,242,.55);
letter-spacing: 0.04em;
}
.progress {
background: #fff; border: 1px solid var(--border);
border-radius: 12px; padding: 12px;
}
.progress__title {
margin: 0 0 10px; font-size: 15px; font-weight: 700; color: #0f291e;
}
.step { display: flex; gap: 10px; min-height: 52px; }
.rail { display: flex; flex-direction: column; align-items: center; width: 16px; }
.dot {
width: 10px; height: 10px; margin-top: 6px; border-radius: 50%;
background: #94a3b8;
}
.dot.ok { background: #189b65; }
.dot.warn { background: #cf8a19; }
.dot.danger { background: #d14343; }
.dot.mute { background: #94a3b8; }
.line { flex: 1; width: 2px; margin: 4px 0 0; background: #e2e8f0; min-height: 28px; }
.step-card { flex: 1; min-width: 0; padding-bottom: 12px; }
.step:last-child .step-card { padding-bottom: 0; }
.row {
display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
}
.name { font-size: 14px; font-weight: 600; color: #0f291e; }
.person-block { margin-top: 6px; }
.person {
font-size: 12px; color: #5f7a6d;
display: flex; justify-content: space-between; gap: 8px; align-items: baseline;
}
.person strong { color: #1f2a26; font-weight: 600; }
.person.is-ok strong { color: #189b65; }
.person.is-danger strong { color: #d14343; }
.person.is-mute strong,
.person.is-mute .detail { color: #94a3b8; }
.person .time { color: #94a3b8; white-space: nowrap; font-size: 11px; }
.person .detail { margin-left: 4px; }
.badge {
display: inline-flex; align-items: center;
padding: 1px 7px; border-radius: 999px;
font-size: 11px; font-weight: 650; line-height: 18px;
border: 1px solid transparent;
}
.badge.ok { color: #047857; background: #ecfdf5; border-color: #a7f3d0; }
.badge.warn { color: #b45309; background: #fffbeb; border-color: #fde68a; }
.badge.danger { color: #b91c1c; background: #fef2f2; border-color: #fecaca; }
.badge.mute { color: #64748b; background: #f8fafc; border-color: #e2e8f0; }
.badge.and { color: #0f766e; background: #f0fdfa; border-color: #99f6e4; }
.callout {
margin-top: 10px; padding: 8px 10px; border-radius: 8px;
font-size: 12px; line-height: 1.5;
}
.callout.bad { background: #fff1f2; color: #9f1239; border: 1px solid #fecdd3; }
.callout.good { background: #ecfdf5; color: #065f46; border: 1px solid #a7f3d0; }
.callout.neutral { background: #f8fafc; color: #475569; border: 1px solid #e2e8f0; }
.legend {
margin-top: 28px; padding: 14px 16px; border-radius: 14px;
background: rgba(255,255,255,.94); border: 1px solid #e2e8f0;
font-size: 13px; color: #334155;
}
.legend h3 { margin: 0 0 8px; font-size: 14px; }
.legend table { width: 100%; border-collapse: collapse; font-size: 12px; }
.legend th, .legend td {
text-align: left; padding: 8px 6px; border-bottom: 1px solid #f1f5f9;
vertical-align: top;
}
.legend th { color: #64748b; font-weight: 600; }
</style>
</head>
<body>
<div class="stage">
<div class="hero">
<h1>撤销后 · 审批进度怎么展示?</h1>
<p>
场景:发起人提交后,在「直接主管」尚未审批时撤销。库表里该节点任务
<code>status=cancelled</code> 是引擎为清掉待办写的,不等于主管做了「撤销」。
「已撤销」语义应归发起人/实例终态,不应挂在主管节点上。
</p>
</div>
<div class="goals">
<strong>设计目标</strong>
<ul>
<li>不把发起人撤销误读成「直接主管撤销」</li>
<li>「已撤销」只出现在实例终态(印章 / 进度末行)</li>
<li>被系统取消的待办节点,展示应对齐或签免处理(「无需处理」)或弱化</li>
</ul>
</div>
<div class="scene">
<strong>样例数据</strong>:实例
<code>E40F649F…</code> · 11:17 提交 → 12:47 发起人
<code>withdraw</code> · 「直接主管」任务从未审批,仅被系统改为
<code>cancelled</code>
</div>
<div class="grid">
<!-- A: 现状问题 -->
<section class="card">
<h2>
A. 现状(有问题)
<span class="pill now">当前</span>
</h2>
<p class="sub">节点徽章 + 人员行都写「已撤销」→ 像是主管撤销了</p>
<div class="phone">
<div class="phone__screen">
<div class="nav">
<div class="nav__back">‹</div>
<div class="nav__title">审批详情</div>
</div>
<div class="body">
<div class="stamp-row">
<div class="stamp-row__meta">差旅报销 · 我发起的</div>
<div class="stamp-row__title">出差申请单</div>
<div class="stamp">已撤销</div>
</div>
<div class="progress">
<div class="progress__title">审批进度</div>
<div class="step">
<div class="rail"><div class="dot ok"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">发起人</span>
<span class="badge ok">已提交</span>
</div>
<div class="person-block">
<div class="person is-ok">
<span><strong>吴子龙</strong></span>
<span class="time">08-13 11:17</span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot danger"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">直接主管</span>
<span class="badge danger">已撤销</span>
<span class="badge and">会签</span>
</div>
<div class="person-block">
<div class="person is-danger">
<span><strong>张主管</strong><span class="detail">已撤销</span></span>
<span class="time">08-13 12:47</span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot danger"></div></div>
<div class="step-card">
<div class="row">
<span class="name">已撤销</span>
<span class="badge danger">已撤销</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="callout bad">
✗ 主管节点挂了「已撤销」,语义错位;终态行再写一次,重复且误导。
</div>
</section>
<!-- B: 推荐 -->
<section class="card">
<h2>
B. 推荐:主管「无需处理」
<span class="pill rec">推荐</span>
</h2>
<p class="sub">对齐或签免处理:系统取消的待办 = 无需处理;「已撤销」只在终态</p>
<div class="phone">
<div class="phone__screen">
<div class="nav">
<div class="nav__back">‹</div>
<div class="nav__title">审批详情</div>
</div>
<div class="body">
<div class="stamp-row">
<div class="stamp-row__meta">差旅报销 · 我发起的</div>
<div class="stamp-row__title">出差申请单</div>
<div class="stamp">已撤销</div>
</div>
<div class="progress">
<div class="progress__title">审批进度</div>
<div class="step">
<div class="rail"><div class="dot ok"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">发起人</span>
<span class="badge ok">已提交</span>
</div>
<div class="person-block">
<div class="person is-ok">
<span><strong>吴子龙</strong></span>
<span class="time">08-13 11:17</span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot mute"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">直接主管</span>
<span class="badge mute">无需处理</span>
<span class="badge and">会签</span>
</div>
<div class="person-block">
<div class="person is-mute">
<span><strong>张主管</strong><span class="detail">无需处理</span></span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot danger"></div></div>
<div class="step-card">
<div class="row">
<span class="name">已撤销</span>
<span class="badge danger">已撤销</span>
</div>
<div class="person-block">
<div class="person is-danger">
<span><strong>吴子龙</strong><span class="detail">发起人撤销</span></span>
<span class="time">08-13 12:47</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="callout good">
✓ 主管只是「未轮到 / 被取消」;谁撤销、何时撤销在终态说清楚。
</div>
</section>
<!-- C: 备选:不展示取消节点 -->
<section class="card">
<h2>
C. 备选:不展示未批节点
<span class="pill alt">备选</span>
</h2>
<p class="sub">进度只保留「已发生」动作:提交 + 终态撤销;主管卡不出现</p>
<div class="phone">
<div class="phone__screen">
<div class="nav">
<div class="nav__back">‹</div>
<div class="nav__title">审批详情</div>
</div>
<div class="body">
<div class="stamp-row">
<div class="stamp-row__meta">差旅报销 · 我发起的</div>
<div class="stamp-row__title">出差申请单</div>
<div class="stamp">已撤销</div>
</div>
<div class="progress">
<div class="progress__title">审批进度</div>
<div class="step">
<div class="rail"><div class="dot ok"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">发起人</span>
<span class="badge ok">已提交</span>
</div>
<div class="person-block">
<div class="person is-ok">
<span><strong>吴子龙</strong></span>
<span class="time">08-13 11:17</span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot danger"></div></div>
<div class="step-card">
<div class="row">
<span class="name">已撤销</span>
<span class="badge danger">已撤销</span>
</div>
<div class="person-block">
<div class="person is-danger">
<span><strong>吴子龙</strong><span class="detail">发起人撤销</span></span>
<span class="time">08-13 12:47</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="callout neutral">
○ 最干净,但看不到「曾经到过主管节点」;多人会签部分已批、部分 cancelled 时更难统一。
</div>
</section>
<!-- D: 备选:节点无状态,仅姓名 -->
<section class="card">
<h2>
D. 备选:节点弱化、无徽章
<span class="pill alt">备选</span>
</h2>
<p class="sub">主管卡只留姓名灰显,不写「已撤销/无需处理」;语义全靠终态</p>
<div class="phone">
<div class="phone__screen">
<div class="nav">
<div class="nav__back">‹</div>
<div class="nav__title">审批详情</div>
</div>
<div class="body">
<div class="stamp-row">
<div class="stamp-row__meta">差旅报销 · 我发起的</div>
<div class="stamp-row__title">出差申请单</div>
<div class="stamp">已撤销</div>
</div>
<div class="progress">
<div class="progress__title">审批进度</div>
<div class="step">
<div class="rail"><div class="dot ok"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">发起人</span>
<span class="badge ok">已提交</span>
</div>
<div class="person-block">
<div class="person is-ok">
<span><strong>吴子龙</strong></span>
<span class="time">08-13 11:17</span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot mute"></div><div class="line"></div></div>
<div class="step-card">
<div class="row">
<span class="name">直接主管</span>
<span class="badge and">会签</span>
</div>
<div class="person-block">
<div class="person is-mute">
<span><strong>张主管</strong></span>
</div>
</div>
</div>
</div>
<div class="step">
<div class="rail"><div class="dot danger"></div></div>
<div class="step-card">
<div class="row">
<span class="name">已撤销</span>
<span class="badge danger">已撤销</span>
</div>
<div class="person-block">
<div class="person is-danger">
<span><strong>吴子龙</strong><span class="detail">发起人撤销</span></span>
<span class="time">08-13 12:47</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="callout neutral">
○ 不误导,但主管行为态不明确;用户可能疑惑「卡在主管了吗」。
</div>
</section>
</div>
<div class="legend">
<h3>映射建议(若选 B)</h3>
<table>
<thead>
<tr>
<th>库表 / API</th>
<th>节点徽章</th>
<th>人员行</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>任务 <code>cancelled</code>(撤销/打回清待办)</td>
<td><span class="badge mute">无需处理</span></td>
<td>姓名 +「无需处理」(无时间,mute)</td>
<td>与或签 <code>done</code> 同文案;勿写「已撤销」</td>
</tr>
<tr>
<td>实例 <code>cancelled</code> + 终态项</td>
<td><span class="badge danger">已撤销</span></td>
<td>发起人 +「发起人撤销」+ 撤销时间</td>
<td>唯一表达「谁撤销了本单」</td>
</tr>
<tr>
<td>打回时其它人的 <code>cancelled</code></td>
<td>同上「无需处理」</td>
<td>同上</td>
<td>打回结论落在操作人任务上,不落在这些取消任务上</td>
</tr>
</tbody>
</table>
<p style="margin:12px 0 0;color:#64748b;font-size:12px;">
打开方式:用浏览器直接打开本文件即可对比。选定方案后告诉我,再落设计说明与实现。
</p>
</div>
</div>
</body>
</html>