feat: initial public release
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
This commit is contained in:
+197
@@ -0,0 +1,197 @@
|
||||
/** Shared contracts for the official XFT OpenAPI adapter. */
|
||||
export interface AuthenticatedDingTalkUser {
|
||||
userId: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
export interface XftTodoItem {
|
||||
source: "xft";
|
||||
billId: string;
|
||||
taskId?: string;
|
||||
eventSeqId?: string;
|
||||
title?: string;
|
||||
applicantName?: string;
|
||||
applicantDepartment?: string;
|
||||
applyTime?: string;
|
||||
amount?: number;
|
||||
currency?: string;
|
||||
reason?: string;
|
||||
allowPass?: boolean;
|
||||
allowReject?: boolean;
|
||||
eventType?: string;
|
||||
}
|
||||
|
||||
export type ApprovalHistoryScope = "handled" | "submitted";
|
||||
|
||||
export interface ApprovalHistoryRange {
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
}
|
||||
|
||||
export interface XftHistoryItem extends Omit<XftTodoItem, "allowPass" | "allowReject"> {
|
||||
historyScope: ApprovalHistoryScope;
|
||||
status?: string;
|
||||
statusName?: string;
|
||||
completedAt?: string;
|
||||
}
|
||||
|
||||
export type XftApprovalAction = "agree" | "reject" | "return";
|
||||
|
||||
export interface XftApprovalBatchItem {
|
||||
billId: string;
|
||||
targetNodeId?: string;
|
||||
}
|
||||
|
||||
export type XftApprovalBatchResultItem =
|
||||
| { billId: string; status: "succeeded"; success: true }
|
||||
| { billId: string; status: "failed"; success: false; failureConfirmed: true; error: string }
|
||||
| {
|
||||
billId: string;
|
||||
status: "outcome_uncertain";
|
||||
success: false;
|
||||
outcomeUncertain: true;
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type XftSubmissionKind =
|
||||
| "travel_apply"
|
||||
| "expense_apply"
|
||||
| "entertainment_apply"
|
||||
| "common_apply"
|
||||
| "use_car_apply"
|
||||
| "common_reimburse"
|
||||
| "travel_reimburse";
|
||||
|
||||
export interface XftSubmissionTemplate {
|
||||
eventSeqId: string;
|
||||
eventNumber: string;
|
||||
eventName: string;
|
||||
eventType: string;
|
||||
kind: XftSubmissionKind;
|
||||
}
|
||||
|
||||
export interface XftSubmissionField {
|
||||
fieldNumber: string;
|
||||
name: string;
|
||||
type: string;
|
||||
required: boolean;
|
||||
description?: string;
|
||||
multiple?: boolean;
|
||||
options?: unknown[];
|
||||
moduleType?: string;
|
||||
valueFormat?: string;
|
||||
itemFields?: Array<Record<string, unknown>>;
|
||||
}
|
||||
|
||||
export type XftSubmissionOptionKind = "department" | "city";
|
||||
|
||||
export interface XftSubmissionOption {
|
||||
code: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export interface XftApprovalProvider {
|
||||
authStatus(user: AuthenticatedDingTalkUser): Promise<{
|
||||
authenticated: true;
|
||||
identity: Record<string, unknown>;
|
||||
binding: Record<string, unknown>;
|
||||
persistedBusinessData: false;
|
||||
}>;
|
||||
listMyTodos(user: AuthenticatedDingTalkUser, limit: number, search?: string): Promise<{
|
||||
items: XftTodoItem[];
|
||||
totalCount: number;
|
||||
identity: Record<string, unknown>;
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
listMyHistory(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
scope: ApprovalHistoryScope,
|
||||
limit: number,
|
||||
search: string,
|
||||
range: ApprovalHistoryRange,
|
||||
): Promise<{
|
||||
items: XftHistoryItem[];
|
||||
totalCount: number;
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
getTodoDetail(user: AuthenticatedDingTalkUser, billId: string): Promise<Record<string, unknown>>;
|
||||
getHistoryDetail(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
scope: ApprovalHistoryScope,
|
||||
billId: string,
|
||||
): Promise<Record<string, unknown>>;
|
||||
listReturnNodes(user: AuthenticatedDingTalkUser, billId: string): Promise<{
|
||||
billId: string;
|
||||
nodes: Array<{ nodeId: string; nodeName?: string; approverNames?: string[] }>;
|
||||
requirements: {
|
||||
commentRequired: boolean;
|
||||
signatureRequired: boolean;
|
||||
canSkipPreviouslyApprovedNodes: boolean;
|
||||
};
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
processApprovalBatch(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
action: XftApprovalAction,
|
||||
remark: string,
|
||||
items: XftApprovalBatchItem[],
|
||||
): Promise<{
|
||||
action: XftApprovalAction;
|
||||
total: number;
|
||||
succeeded: number;
|
||||
failed: number;
|
||||
results: XftApprovalBatchResultItem[];
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
listSubmissionTemplates(user: AuthenticatedDingTalkUser, limit: number, search?: string): Promise<XftSubmissionTemplate[]>;
|
||||
getSubmissionSchema(user: AuthenticatedDingTalkUser, template: XftSubmissionTemplate): Promise<{
|
||||
template: XftSubmissionTemplate;
|
||||
fields: XftSubmissionField[];
|
||||
inputContract: Record<string, unknown>;
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
getSubmissionOptions(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
template: XftSubmissionTemplate,
|
||||
kind: XftSubmissionOptionKind,
|
||||
query?: string,
|
||||
limit?: number,
|
||||
): Promise<{
|
||||
kind: XftSubmissionOptionKind;
|
||||
items: XftSubmissionOption[];
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
validateSubmissionIdentity(user: AuthenticatedDingTalkUser): Promise<{
|
||||
validated: true;
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
submitApproval(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
template: XftSubmissionTemplate,
|
||||
values: Record<string, unknown>,
|
||||
): Promise<{ billId: string; status: "submitted"; diagnostics: Record<string, unknown> }>;
|
||||
recallSubmission(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
billId: string,
|
||||
reason?: string,
|
||||
): Promise<{ status: "revoked" | "failed" | "outcome_uncertain"; billId: string; message?: string; diagnostics: Record<string, unknown> }>;
|
||||
getMySubmissionStatus(
|
||||
user: AuthenticatedDingTalkUser,
|
||||
billId: string,
|
||||
): Promise<{
|
||||
billId: string;
|
||||
status: string;
|
||||
statusName: string;
|
||||
approvalStatus?: string;
|
||||
revoked: boolean;
|
||||
revokeAllowed: boolean;
|
||||
flowHistory?: Array<{ nodeName?: string; actions: string[] }>;
|
||||
diagnostics: Record<string, unknown>;
|
||||
}>;
|
||||
}
|
||||
|
||||
/** Success codes observed on the documented XFT OpenAPI endpoints. */
|
||||
export function isXftSuccessCode(code: string | undefined): boolean {
|
||||
if (code === undefined || code === "") return true;
|
||||
return ["0", "200", "SUCCESS", "SUC0000", "000000", "0000000"].includes(code.toUpperCase());
|
||||
}
|
||||
Reference in New Issue
Block a user