Commit 5cd0e3b6 by luoqi

style(web): 左栏状态药丸只显示"非默认态"

召回池每行都写「待分配」、我的每行都写「进行中」—— 整列同一个词,
读者第二行就不再看它,却一直占着行尾最值钱的位置(退回按钮就在那儿)。

 但不能把药丸整个删掉:「我的」不带 status 过滤(where.assigneeUserId = 我),
已完成 / 已放弃的单也在这一栏里,而那两个才是真要一眼看见的。
删掉等于让客服分不出哪条已经结案。

⇒ 按「这一行是不是本视图自身的定义」判断:
  pool → 隐藏 active,mine → 隐藏 assigned,其余照常显示。

两栏处理还不一样:
  · 召回池没有退回按钮 → 默认态**整个不渲染**(留 42px 空白纯属白占,
    而右侧正是手机号/诊所名要用的地方)
  · 我的有退回按钮,药丸与它叠在同一 grid 格、格宽取较大值 →
    默认态用 invisible **占位**,否则 hover 前是 0 宽,按钮一冒出来整行位移,
    而那个叠层机制存在的全部理由就是防这个

实测:召回池 25 行 0 个药丸;我的 22 个药丸全 invisible、占位 42px,
hover 姓名位移 0(退回按钮 37px 落在占位内)。tsc + build 干净。
parent 41566fd7
......@@ -433,6 +433,7 @@ export function PatientPickerRail({
<PatientRow
key={p.id}
plan={p}
view={view}
active={p.id === currentPlanId}
clinicName={p.targetClinicId ? String(clinicDict?.[p.targetClinicId] ?? '') : ''}
showClinic={showClinic}
......@@ -676,9 +677,53 @@ const STATUS_META: Record<string, { label: string; tone: string }> = {
superseded: { label: '已替代', tone: 'bg-slate-100 text-slate-600' },
};
function StatusPill({ status }: { status: string }) {
/**
* 每个视图**自身定义**的那个状态 —— 药丸对这一行是零信息,不显示。
*
* 召回池的服务端基线就是 `status='active'`(见 poolBaseSql),所以那一栏**每一行**都写着
* 「待分配」;「我的」里绝大多数行都是「进行中」。整列同一个词,读者第二行就不再看它了,
* 却一直占着行尾最值钱的位置(退回按钮就在那儿)。
*
* ⛔ **不能因此把药丸整个删掉**:「我的」不带 status 过滤(`where.assigneeUserId = 我`),
* 已完成 / 已放弃的单**也在这一栏里**,而那两个才是真要一眼看见的。
* 删掉等于让客服分不出哪条已经结案。
*/
const DEFAULT_STATUS_OF_VIEW: Partial<Record<View, string>> = {
pool: 'active', // 池子里的都是"待分配"
mine: 'assigned', // 我名下的默认就是"进行中"
};
function StatusPill({
status,
view,
reserveSpace,
}: {
status: string;
view: View;
/**
* 默认态是否仍要**占住宽度**。
* ⚠️ 只有与「退回」按钮叠在同一 grid 格时才需要 —— 格宽取两者较大值,真删掉的话
* 这一格 hover 前是 0 宽,按钮一冒出来整行就位移,而那个叠层机制存在的全部理由就是防这个。
* ⛔ 召回池那栏**不要**开:那里压根没有按钮,留 42px 空白纯属白占,
* 而这一列右侧正是手机号/诊所名要用的地方。
*/
reserveSpace?: boolean;
}) {
const m = STATUS_META[status] ?? { label: status, tone: 'bg-slate-100 text-slate-700' };
return <span className={cn('inline-block flex-none whitespace-nowrap rounded px-1.5 py-0.5 text-[10px] font-medium', m.tone)}>{m.label}</span>;
const isDefault = DEFAULT_STATUS_OF_VIEW[view] === status;
if (isDefault && !reserveSpace) return null;
return (
<span
className={cn(
'inline-block flex-none whitespace-nowrap rounded px-1.5 py-0.5 text-[10px] font-medium',
m.tone,
isDefault && 'invisible',
)}
aria-hidden={isDefault}
>
{m.label}
</span>
);
}
// ── 回访结果角标(最近一次执行的分组:成功 / 不成功 / 保持)────────
......@@ -828,10 +873,13 @@ function PatientRow({
hidePhone,
onClick,
onRecycle,
view,
}: {
plan: PlanListItem;
active: boolean;
clinicName: string;
/** 当前 tab —— 状态药丸要据此判断"这一行是不是本视图的默认态"(默认态不显示) */
view: View;
/** 跨诊所权限才显示诊所名(单诊所的人每行同一家 = 噪音);口径同顶栏「N 个诊所」 */
showClinic: boolean;
/** 宿主配了原始档案(VIEW_PATIENT)时隐藏手机号 —— 真号在宿主档案页,PAC 侧为造数假号。与详情页同条件。 */
......@@ -921,11 +969,11 @@ function PatientRow({
const act = onRecycle
? { label: '退回', tone: 'bg-amber-500 hover:bg-amber-600', fn: onRecycle }
: null;
if (!act) return <StatusPill status={p.status} />;
if (!act) return <StatusPill status={p.status} view={view} />;
return (
<span className="grid flex-none items-center justify-items-end">
<span className="col-start-1 row-start-1 group-hover:invisible">
<StatusPill status={p.status} />
<StatusPill status={p.status} view={view} reserveSpace />
</span>
<button
type="button"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment