OAFRONT5 收口PC剩余P2展示问题
这个提交包含在:
@@ -41,6 +41,7 @@ import { isApiError } from "../api/types";
|
||||
import { useAuth } from "../auth/AuthContext";
|
||||
import { hasPermission } from "../auth/permissions";
|
||||
import { ConfirmDialog } from "../components/common/ConfirmDialog";
|
||||
import { DateTextInput } from "../components/common/DateTextInput";
|
||||
import { ListWorkspace, WorkspaceHeader } from "../components/patterns/ListWorkspace";
|
||||
import { Button } from "../components/ui/button";
|
||||
import {
|
||||
@@ -62,6 +63,7 @@ import {
|
||||
} from "../components/ui/table";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "../components/ui/tabs";
|
||||
import { downloadBlob } from "../lib/download";
|
||||
import { formatDisplayDate, formatDisplayDateTime } from "../lib/displayFormat";
|
||||
|
||||
type OperationsTab = "ledger" | "pending" | "failed" | "risk" | "reconciliation";
|
||||
type RiskActionType = "resolve" | "dismiss";
|
||||
@@ -91,20 +93,24 @@ function resolveErrorMessage(error: unknown, fallback = "操作失败") {
|
||||
}
|
||||
|
||||
function formatDateTime(value: string | null) {
|
||||
if (!value) {
|
||||
return "-";
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return value;
|
||||
}
|
||||
return date.toLocaleString("zh-CN", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
});
|
||||
return formatDisplayDateTime(value);
|
||||
}
|
||||
|
||||
function formatDate(value: string | null | undefined) {
|
||||
return formatDisplayDate(value);
|
||||
}
|
||||
|
||||
function displayPersonName(value: string | null | undefined, fallback = "-") {
|
||||
const name = value?.trim();
|
||||
if (!name) return fallback;
|
||||
const smokeNameLabels: Record<string, string> = {
|
||||
Employee: "测试员工",
|
||||
Manager: "测试主管",
|
||||
Admin: "测试管理员",
|
||||
Finance: "测试财务",
|
||||
"Finance Manager": "测试财务负责人",
|
||||
};
|
||||
return smokeNameLabels[name] ?? name;
|
||||
}
|
||||
|
||||
function statusBadgeClass(status: string) {
|
||||
@@ -737,8 +743,7 @@ export function ApOperationsPage() {
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm font-medium text-zinc-700">报销日期从</div>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={ledgerDateFrom}
|
||||
onChange={(event) => {
|
||||
setLedgerDateFrom(event.target.value);
|
||||
@@ -748,8 +753,7 @@ export function ApOperationsPage() {
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm font-medium text-zinc-700">报销日期至</div>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={ledgerDateTo}
|
||||
onChange={(event) => {
|
||||
setLedgerDateTo(event.target.value);
|
||||
@@ -811,7 +815,7 @@ export function ApOperationsPage() {
|
||||
<div className="text-xs text-zinc-500">{item.description || "无说明"}</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="font-medium text-zinc-900">{item.owner?.name ?? item.submitter?.name ?? "-"}</div>
|
||||
<div className="font-medium text-zinc-900">{displayPersonName(item.owner?.name ?? item.submitter?.name)}</div>
|
||||
<div className="text-xs text-zinc-500">{item.department?.name ?? "-"}</div>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
@@ -830,7 +834,7 @@ export function ApOperationsPage() {
|
||||
{paymentStatusLabel(item.payment.status)}
|
||||
</span>
|
||||
<div className="text-xs text-zinc-500">
|
||||
{item.payment.paymentDate ?? "-"} · {item.payment.paidBy?.name ?? "未记录操作人"}
|
||||
{formatDate(item.payment.paymentDate)} · {displayPersonName(item.payment.paidBy?.name, "未记录操作人")}
|
||||
</div>
|
||||
<div className="text-xs text-zinc-500">
|
||||
凭证:{item.payment.paymentVoucherNo ?? "-"}
|
||||
@@ -912,16 +916,14 @@ export function ApOperationsPage() {
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm font-medium text-zinc-700">创建时间从</div>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={pendingCreatedAtFrom}
|
||||
onChange={(event) => setPendingCreatedAtFrom(event.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm font-medium text-zinc-700">创建时间至</div>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={pendingCreatedAtTo}
|
||||
onChange={(event) => setPendingCreatedAtTo(event.target.value)}
|
||||
/>
|
||||
|
||||
@@ -113,6 +113,20 @@ function assetTypeLabel(value: AssetType | string | null | undefined) {
|
||||
return assetTypeOptions().find((item) => item.value === value)?.label ?? "未知类型";
|
||||
}
|
||||
|
||||
function assetStatusLabel(value: AssetStatus | string | null | undefined) {
|
||||
return assetStatusOptions().find((item) => item.value === value)?.label ?? "未知状态";
|
||||
}
|
||||
|
||||
function assetErpChangeTypeLabel(value: string | null | undefined) {
|
||||
const labels: Record<string, string> = {
|
||||
created: "新建资产卡",
|
||||
updated: "资产信息更新",
|
||||
retired: "资产退役",
|
||||
archived: "资产归档",
|
||||
};
|
||||
return value ? labels[value] ?? "资产变更" : "-";
|
||||
}
|
||||
|
||||
function sensitivityOptions(): Array<{ value: AssetSensitivityLevel | ""; label: string }> {
|
||||
return [
|
||||
{ value: "", label: "全部敏感级别" },
|
||||
@@ -1335,9 +1349,9 @@ export function AssetRegistryPage() {
|
||||
|
||||
<div className="grid gap-2 rounded-lg bg-zinc-50 px-3 py-2 text-xs text-zinc-600 md:grid-cols-2">
|
||||
<div>资产编号:{assetErpTrack?.asset.assetNo ?? currentAsset?.assetNo ?? "-"}</div>
|
||||
<div>最近 changeType:{assetErpStage.preview.changeType ?? "-"}</div>
|
||||
<div>最近变更:{assetErpChangeTypeLabel(assetErpStage.preview.changeType)}</div>
|
||||
<div>分类:{assetErpStage.preview.categoryCode ?? "-"}</div>
|
||||
<div>资产状态:{assetErpStage.preview.status ?? assetErpTrack?.asset.status ?? "-"}</div>
|
||||
<div>资产状态:{assetStatusLabel(assetErpStage.preview.status ?? assetErpTrack?.asset.status)}</div>
|
||||
<div>法体:{assetErpStage.preview.legalEntityCode ?? "-"}</div>
|
||||
<div>成本中心:{assetErpStage.preview.costCenterCode ?? "-"}</div>
|
||||
</div>
|
||||
|
||||
@@ -28,6 +28,7 @@ import { useAuth } from "../auth/AuthContext";
|
||||
import { hasPermission } from "../auth/permissions";
|
||||
import { EmployeeAvatar } from "../components/common/EmployeeAvatar";
|
||||
import { ConfirmDialog } from "../components/common/ConfirmDialog";
|
||||
import { DateTextInput } from "../components/common/DateTextInput";
|
||||
import { PageHeader } from "../components/common/PageHeader";
|
||||
import { Button } from "../components/ui/button";
|
||||
import {
|
||||
@@ -566,13 +567,11 @@ export function PeoplePage() {
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={hireDateFrom}
|
||||
onChange={(event) => setHireDateFrom(event.target.value)}
|
||||
/>
|
||||
<Input
|
||||
type="date"
|
||||
<DateTextInput
|
||||
value={hireDateTo}
|
||||
onChange={(event) => setHireDateTo(event.target.value)}
|
||||
/>
|
||||
|
||||
在新工单中引用
屏蔽一个用户