feat(P18B-3,P18B-4): 实现资产盘点页面与流转前端入口

这个提交包含在:
2026-03-07 23:20:43 +08:00
父节点 946a357f8b
当前提交 94cb0fdf23
共修改 6 个文件,包含 774 行新增和 22 行删除
+41 -3
查看文件
@@ -106,7 +106,7 @@ export type AssetListQuery = {
mine?: boolean;
};
export type AssetPayload = {
export type CreateAssetPayload = {
name: string;
categoryId: string;
legalEntityId: string;
@@ -120,6 +120,20 @@ export type AssetPayload = {
retiredAt?: string | null;
};
export type PatchAssetPayload = Partial<
Omit<CreateAssetPayload, "purchaseRequestId" | "assigneeEmployeeId">
>;
export type AssetMovementResponse = {
assetId: string;
assetNo: string;
status: AssetStatus;
assigneeEmployeeId: string | null;
location: string | null;
assignmentId?: string | null;
transferId?: string | null;
};
function toQueryString(query: Record<string, string | boolean | undefined>) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
@@ -181,16 +195,40 @@ export async function fetchAssetDetail(assetId: string) {
return apiRequestData<{ asset: AssetItem }>(`/api/assets/${assetId}`);
}
export async function createAsset(payload: AssetPayload) {
export async function createAsset(payload: CreateAssetPayload) {
return apiRequestData<{ asset: AssetItem }>("/api/assets", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function patchAsset(assetId: string, payload: Partial<Omit<AssetPayload, "purchaseRequestId">>) {
export async function patchAsset(assetId: string, payload: PatchAssetPayload) {
return apiRequestData<{ asset: AssetItem }>(`/api/assets/${assetId}`, {
method: "PATCH",
body: JSON.stringify(payload),
});
}
export async function assignAsset(assetId: string, payload: { employeeId: string; note?: string | null }) {
return apiRequestData<AssetMovementResponse>(`/api/assets/${assetId}/assign`, {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function returnAsset(assetId: string, payload: { note?: string | null } = {}) {
return apiRequestData<AssetMovementResponse>(`/api/assets/${assetId}/return`, {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function transferAsset(
assetId: string,
payload: { toEmployeeId?: string | null; toLocation?: string | null; note?: string | null },
) {
return apiRequestData<AssetMovementResponse>(`/api/assets/${assetId}/transfer`, {
method: "POST",
body: JSON.stringify(payload),
});
}
+83
查看文件
@@ -0,0 +1,83 @@
import { apiRequestData } from "./http";
import type { AssetStatus } from "./assets";
export type InventoryCheckScopeType = "all" | "legal_entity" | "cost_center" | "location";
export type InventoryCheckStatus = "draft" | "counting" | "completed";
export type InventoryCheckResult = "matched" | "missing" | "extra" | "damaged";
export type InventoryCheckItem = {
id: string;
assetId: string;
result: InventoryCheckResult;
note: string | null;
asset: {
id: string;
assetNo: string;
name: string;
status: AssetStatus;
legalEntityId: string;
costCenterId: string;
location: string | null;
assigneeEmployeeId: string | null;
} | null;
};
export type InventoryCheck = {
id: string;
checkNo: string;
scopeType: InventoryCheckScopeType;
scopeRefId: string | null;
status: InventoryCheckStatus;
startedAt: string | null;
completedAt: string | null;
createdAt: string | null;
updatedAt: string | null;
items: InventoryCheckItem[];
};
function toQueryString(query: Record<string, string | undefined>) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(query)) {
if (!value) {
continue;
}
params.set(key, value);
}
const encoded = params.toString();
return encoded ? `?${encoded}` : "";
}
export async function fetchInventoryChecks(params: { status?: InventoryCheckStatus; scopeType?: InventoryCheckScopeType } = {}) {
return apiRequestData<{ items: InventoryCheck[] }>(
`/api/inventory-checks${toQueryString(params as Record<string, string | undefined>)}`,
);
}
export async function createInventoryCheck(payload: { scopeType: InventoryCheckScopeType; scopeRefId?: string | null }) {
return apiRequestData<{ inventoryCheck: InventoryCheck }>("/api/inventory-checks", {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function startInventoryCheck(inventoryCheckId: string) {
return apiRequestData<{ inventoryCheck: InventoryCheck }>(`/api/inventory-checks/${inventoryCheckId}/start`, {
method: "POST",
});
}
export async function recordInventoryItems(
inventoryCheckId: string,
payload: { items: Array<{ assetId: string; result: InventoryCheckResult; note?: string | null }> },
) {
return apiRequestData<{ inventoryCheck: InventoryCheck }>(`/api/inventory-checks/${inventoryCheckId}/items`, {
method: "POST",
body: JSON.stringify(payload),
});
}
export async function completeInventoryCheck(inventoryCheckId: string) {
return apiRequestData<{ inventoryCheck: InventoryCheck }>(`/api/inventory-checks/${inventoryCheckId}/complete`, {
method: "POST",
});
}