增加移动报销查看范围(07-27-yang-jun-reimbursement-readiness)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-31 20:43:33 +08:00
父节点 20b20b100e
当前提交 8b376f4135
共修改 4 个文件,包含 139 行新增和 5 行删除
+36 -4
查看文件
@@ -160,17 +160,24 @@ export function MobileReimbursementsPage() {
const createIntentHandledRef = useRef(false);
const canCreateExpense = hasPermission(permissions, "expense.create");
const canDeleteExpense = hasPermission(permissions, "expense.delete_own");
const canViewAllExpense = hasPermission(permissions, "expense.view_all");
const scope: "own" | "all" = canViewAllExpense && searchParams.get("scope") === "all" ? "all" : "own";
const currentMobileSource = useMemo(() => {
const params = new URLSearchParams(location.search);
params.delete("intent");
params.set("status", status);
if (canViewAllExpense) {
params.set("scope", scope);
} else {
params.delete("scope");
}
const query = params.toString();
return `${location.pathname}${query ? `?${query}` : ""}`;
}, [location.pathname, location.search, status]);
}, [canViewAllExpense, location.pathname, location.search, scope, status]);
const listQuery = useQuery({
queryKey: ["mobile", "reimbursements", status],
queryFn: () => fetchReimbursements({ status, page: 1, pageSize: 20, scope: "own" }),
queryKey: ["mobile", "reimbursements", status, scope],
queryFn: () => fetchReimbursements({ status, page: 1, pageSize: 20, scope }),
});
const createMutation = useMutation({
@@ -203,6 +210,16 @@ export function MobileReimbursementsPage() {
setSearchParams(nextParams, { replace: true });
}
function handleScopeChange(value: string) {
if (!canViewAllExpense || (value !== "own" && value !== "all")) {
return;
}
const nextParams = new URLSearchParams(searchParams);
nextParams.delete("intent");
nextParams.set("scope", value);
setSearchParams(nextParams, { replace: true });
}
useEffect(() => {
if (searchParams.get("intent") !== "create" || !canCreateExpense || createIntentHandledRef.current) {
return;
@@ -293,6 +310,21 @@ export function MobileReimbursementsPage() {
</div>
</div>
<div className="mobile-command-surface">
{canViewAllExpense ? (
<div className="space-y-2">
<div className="text-xs font-medium text-zinc-500">查看范围</div>
<Tabs value={scope} onValueChange={handleScopeChange}>
<TabsList className="grid h-auto min-h-12 w-full grid-cols-2" aria-label="报销查看范围">
<TabsTrigger className="min-h-12" data-testid="mobile-reimbursements-scope-own" value="own">
我的
</TabsTrigger>
<TabsTrigger className="min-h-12" data-testid="mobile-reimbursements-scope-all" value="all">
全部
</TabsTrigger>
</TabsList>
</Tabs>
</div>
) : null}
<label className="text-xs font-medium text-zinc-500" htmlFor="mobile-reimbursements-current-search">
当前列表搜索
</label>
@@ -326,7 +358,7 @@ export function MobileReimbursementsPage() {
) : null}
{visibleItems.map((item) => (
<ReimbursementCard
canDeleteDraft={canDeleteExpense && item.status === "draft"}
canDeleteDraft={canDeleteExpense && scope === "own" && item.status === "draft"}
currentMobileSource={currentMobileSource}
isDeleting={deleteMutation.isPending}
item={item}