OAFRONT6 压缩长编号展示并修正视觉探针
这个提交包含在:
@@ -38,7 +38,7 @@ import { SectionPanel } from "../components/patterns/SectionPanel";
|
||||
import { Button } from "../components/ui/button";
|
||||
import { Input } from "../components/ui/input";
|
||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "../components/ui/table";
|
||||
import { formatDisplayDateTime } from "../lib/displayFormat";
|
||||
import { formatCompactIdentifier, formatDisplayDateTime, formatTextWithCompactLongNumbers, isCompactedIdentifier } from "../lib/displayFormat";
|
||||
|
||||
function resolveError(error: unknown) {
|
||||
if (isApiError(error)) {
|
||||
@@ -156,6 +156,41 @@ function typeHint(assetType: AssetType) {
|
||||
}
|
||||
}
|
||||
|
||||
function CompactAssetNo({ value, copyable = true }: { value: string; copyable?: boolean }) {
|
||||
const displayValue = formatCompactIdentifier(value, { head: 14, tail: 6, minLength: 24 });
|
||||
const compacted = isCompactedIdentifier(value, displayValue);
|
||||
|
||||
async function copyAssetNo() {
|
||||
if (!compacted) return;
|
||||
try {
|
||||
await navigator.clipboard.writeText(value);
|
||||
toast.success("已复制完整资产编号");
|
||||
} catch {
|
||||
toast.error("复制失败,可在资产详情中查看完整编号");
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<span className="inline-flex min-w-0 max-w-full items-center gap-1.5">
|
||||
<span className="truncate" title={compacted ? value : undefined}>
|
||||
{displayValue}
|
||||
</span>
|
||||
{compacted && copyable ? (
|
||||
<button
|
||||
className="shrink-0 rounded border border-zinc-200 px-1.5 py-0.5 text-[11px] font-medium text-zinc-500 hover:border-zinc-300 hover:text-zinc-700"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
void copyAssetNo();
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
复制
|
||||
</button>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
function unsafeAssetTextReason(value: string) {
|
||||
if (!value.trim()) {
|
||||
return "";
|
||||
@@ -796,7 +831,7 @@ export function AssetRegistryPage() {
|
||||
<option value="">使用系统默认</option>
|
||||
{(documentCategoriesQuery.data?.items ?? []).map((item) => (
|
||||
<option key={item.id} value={item.id}>
|
||||
{item.name} ({item.code})
|
||||
{formatTextWithCompactLongNumbers(item.name)} ({formatTextWithCompactLongNumbers(item.code)})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -829,8 +864,12 @@ export function AssetRegistryPage() {
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<div className="truncate text-sm font-semibold text-zinc-900">{item.name}</div>
|
||||
<div className="mt-1 text-xs text-zinc-500">{item.code}</div>
|
||||
<div className="truncate text-sm font-semibold text-zinc-900" title={item.name}>
|
||||
{formatTextWithCompactLongNumbers(item.name)}
|
||||
</div>
|
||||
<div className="mt-1 text-xs text-zinc-500" title={item.code}>
|
||||
{formatTextWithCompactLongNumbers(item.code)}
|
||||
</div>
|
||||
</div>
|
||||
<span className="shrink-0 rounded-full bg-zinc-100 px-2 py-1 text-xs text-zinc-600">
|
||||
{item.enabled ? "启用" : "停用"}
|
||||
@@ -855,9 +894,11 @@ export function AssetRegistryPage() {
|
||||
<TableBody>
|
||||
{categoryItems.map((item) => (
|
||||
<TableRow key={item.id} onClick={() => resetCategoryEditor(item)} className="cursor-pointer">
|
||||
<TableCell className="font-medium text-zinc-900">{item.code}</TableCell>
|
||||
<TableCell className="font-medium text-zinc-900" title={item.code}>
|
||||
{formatTextWithCompactLongNumbers(item.code)}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div>{item.name}</div>
|
||||
<div title={item.name}>{formatTextWithCompactLongNumbers(item.name)}</div>
|
||||
<div className="text-xs text-zinc-500">{item.documentCategory?.name ?? "系统默认"}</div>
|
||||
</TableCell>
|
||||
<TableCell>{item.enabled ? "启用" : "停用"}</TableCell>
|
||||
@@ -903,7 +944,7 @@ export function AssetRegistryPage() {
|
||||
<option value="">全部分类</option>
|
||||
{(categoriesQuery.data?.items ?? []).map((item) => (
|
||||
<option key={item.id} value={item.id}>
|
||||
{item.name}
|
||||
{formatTextWithCompactLongNumbers(item.name)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
@@ -968,15 +1009,21 @@ export function AssetRegistryPage() {
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<div className="min-w-0">
|
||||
<div className="truncate text-sm font-semibold text-zinc-900">{item.assetNo}</div>
|
||||
<div className="mt-1 truncate text-xs text-zinc-500">{item.name}</div>
|
||||
<div className="truncate text-sm font-semibold text-zinc-900">
|
||||
<CompactAssetNo copyable={false} value={item.assetNo} />
|
||||
</div>
|
||||
<div className="mt-1 truncate text-xs text-zinc-500" title={item.name}>
|
||||
{formatTextWithCompactLongNumbers(item.name)}
|
||||
</div>
|
||||
</div>
|
||||
<StatusBadge status={item.status} />
|
||||
</div>
|
||||
<div className="mt-3 grid grid-cols-2 gap-2 text-xs text-zinc-600">
|
||||
<div>
|
||||
<div className="text-zinc-400">分类</div>
|
||||
<div className="mt-0.5 truncate text-zinc-700">{item.category?.name ?? "-"}</div>
|
||||
<div className="mt-0.5 truncate text-zinc-700" title={item.category?.name ?? undefined}>
|
||||
{formatTextWithCompactLongNumbers(item.category?.name ?? "-")}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="text-zinc-400">类型</div>
|
||||
@@ -1012,11 +1059,17 @@ export function AssetRegistryPage() {
|
||||
selectAsset(item.id);
|
||||
}} className={item.id === selectedAssetId && !isCreatingAsset ? "bg-zinc-50" : "cursor-pointer"}>
|
||||
<TableCell>
|
||||
<div className="font-medium text-zinc-900">{item.assetNo}</div>
|
||||
<div className="text-xs text-zinc-500">{item.name}</div>
|
||||
<div className="font-medium text-zinc-900">
|
||||
<CompactAssetNo value={item.assetNo} />
|
||||
</div>
|
||||
<div className="text-xs text-zinc-500" title={item.name}>
|
||||
{formatTextWithCompactLongNumbers(item.name)}
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{assetTypeLabel(item.assetType)}</TableCell>
|
||||
<TableCell>{item.category?.name ?? "-"}</TableCell>
|
||||
<TableCell title={item.category?.name ?? undefined}>
|
||||
{formatTextWithCompactLongNumbers(item.category?.name ?? "-")}
|
||||
</TableCell>
|
||||
<TableCell>{sensitivityLabel(item.sensitivityLevel)}</TableCell>
|
||||
<TableCell><StatusBadge status={item.status} /></TableCell>
|
||||
<TableCell>{item.owner?.name ?? item.assignee?.name ?? "-"}</TableCell>
|
||||
@@ -1052,8 +1105,12 @@ export function AssetRegistryPage() {
|
||||
<>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div>
|
||||
<h3 className="text-lg font-semibold text-zinc-900">{isCreatingAsset ? "新建资产卡片" : currentAsset?.assetNo ?? "资产卡片"}</h3>
|
||||
<p className="text-sm text-zinc-500">{isCreatingAsset ? "创建新的资产台账卡片。" : currentAsset?.name}</p>
|
||||
<h3 className="text-lg font-semibold text-zinc-900">
|
||||
{isCreatingAsset ? "新建资产卡片" : currentAsset ? <CompactAssetNo value={currentAsset.assetNo} /> : "资产卡片"}
|
||||
</h3>
|
||||
<p className="text-sm text-zinc-500" title={currentAsset?.name ?? undefined}>
|
||||
{isCreatingAsset ? "创建新的资产台账卡片。" : formatTextWithCompactLongNumbers(currentAsset?.name)}
|
||||
</p>
|
||||
</div>
|
||||
{!isCreatingAsset && currentAsset ? <StatusBadge status={currentAsset.status} /> : null}
|
||||
</div>
|
||||
@@ -1379,9 +1436,9 @@ export function AssetRegistryPage() {
|
||||
</div>
|
||||
|
||||
<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>资产编号:{formatTextWithCompactLongNumbers(assetErpTrack?.asset.assetNo ?? currentAsset?.assetNo ?? "-")}</div>
|
||||
<div>最近变更:{assetErpChangeTypeLabel(assetErpStage.preview.changeType)}</div>
|
||||
<div>分类:{assetErpStage.preview.categoryCode ?? "-"}</div>
|
||||
<div>分类:{formatTextWithCompactLongNumbers(assetErpStage.preview.categoryCode ?? "-")}</div>
|
||||
<div>资产状态:{assetStatusLabel(assetErpStage.preview.status ?? assetErpTrack?.asset.status)}</div>
|
||||
<div>法体:{assetErpStage.preview.legalEntityCode ?? "-"}</div>
|
||||
<div>成本中心:{assetErpStage.preview.costCenterCode ?? "-"}</div>
|
||||
|
||||
在新工单中引用
屏蔽一个用户