feat(approval): 员工端审批中心入口与业务完成确认单页面 (#19)

This commit is contained in:
2026-10-30 20:20:34 +08:00
parent ae8bcb1e57
commit 370091ed6e
9 changed files with 1794 additions and 2 deletions
+57
View File
@@ -0,0 +1,57 @@
import request from '@/utils/request';
import type { ApiResult } from '@/api';
import type { ApprovalAttachment } from '../model';
import { TENANT_ID, THINK_API_URL } from '@/config/setting';
/**
* 上传附件:走审批域端点,header 带登录态与租户
*/
export function uploadAttachment(
instanceId: number,
filePath: string,
category: string
): Promise<ApprovalAttachment> {
return new Promise((resolve, reject) => {
const token = uni.getStorageSync('access_token');
uni.uploadFile({
url:
THINK_API_URL +
'/approval/attachment/upload?instanceId=' +
instanceId,
name: 'file',
filePath,
formData: { category },
header: {
TenantId: TENANT_ID,
...(token ? { Authorization: token } : {})
},
success: res => {
try {
const body =
typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
if (body.code === 0 && body.data) {
resolve(body.data as ApprovalAttachment);
return;
}
reject(new Error(body.message || '上传失败'));
} catch (err) {
reject(new Error('上传失败'));
}
},
fail: () => reject(new Error('上传失败'))
});
});
}
/**
* 逻辑删除附件
*/
export async function deleteAttachment(id: number) {
const res = await request.delete<ApiResult<unknown>>(
THINK_API_URL + '/approval/attachment/' + id
);
if (res.data.code === 0) {
return true;
}
return Promise.reject(new Error(res.data.message));
}
+63
View File
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import type {
ApprovalCompletionForm,
ApprovalInstance,
ApprovalItem,
ApprovalMineParam
} from '../model';
import { THINK_API_URL } from '@/config/setting';
/**
* 新建或保存业务完成确认单草稿,返回实例id
*/
export async function saveCompletion(data: ApprovalCompletionForm) {
const res = await request.post<ApiResult<number>>(
THINK_API_URL + '/approval/instance/completion',
data
);
if (res.data.code === 0) {
return res.data.data as number;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 提交或重提
*/
export async function submitInstance(id: number) {
const res = await request.post<ApiResult<ApprovalInstance>>(
THINK_API_URL + '/approval/instance/' + id + '/submit'
);
if (res.data.code === 0) {
return res.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 单据详情
*/
export async function getInstance(id: number) {
const res = await request.get<ApiResult<ApprovalInstance>>(
THINK_API_URL + '/approval/instance/' + id
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 我发起的
*/
export async function pageMine(params: ApprovalMineParam) {
const res = await request.get<ApiResult<PageResult<ApprovalItem>>>(
THINK_API_URL + '/approval/mine/page',
{ params }
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+149
View File
@@ -0,0 +1,149 @@
import type { PageParam } from '@/api';
/**
* 审批附件
*/
export interface ApprovalAttachment {
id: number;
fileId: number;
name: string;
url: string;
length: number;
category: string;
categoryName: string;
uploaderId: number;
uploaderName?: string;
createTime?: string;
}
/**
* 处理记录
*/
export interface ApprovalRecord {
id: number;
taskId?: number;
nodeKey?: string;
nodeName?: string;
operatorId: number;
operatorName?: string;
action: string;
actionName: string;
opinion?: string;
round: number;
createTime?: string;
}
/**
* 当前轮存档确认状态
*/
export interface ApprovalConfirm {
userId: number;
userName?: string;
status: string;
statusName: string;
handleTime?: string;
}
/**
* 当前用户待办任务
*/
export interface ApprovalMyTask {
id: number;
nodeKey: string;
nodeType: string;
status: string;
}
/**
* 详情动作权限
*/
export interface ApprovalPermissions {
canEdit: boolean;
canSubmit: boolean;
canWithdraw: boolean;
canApprove: boolean;
canReject: boolean;
canConfirm: boolean;
canArchive: boolean;
canDispatch: boolean;
canAssign: boolean;
}
/**
* 列表行
*/
export interface ApprovalItem {
id: number;
bizNo?: string;
docType: string;
docTypeName: string;
status: string;
statusName: string;
title?: string;
submitTime?: string;
currentNodeName?: string;
reporterId: number;
reporterName?: string;
reportOrgName?: string;
acceptOrgName?: string;
archiveTime?: string;
}
/**
* 单据详情
*/
export interface ApprovalInstance extends ApprovalItem {
flowCode: string;
round: number;
reportOrgId?: number;
acceptOrgId?: number;
currentNodeKey?: string;
currentNodeType?: string;
approveTime?: string;
archivistId?: number;
archivistName?: string;
name?: string;
implementOrg?: string;
fee?: number;
serviceContent?: string;
content?: string;
remark?: string;
dispatchTargetId?: number;
dispatchTargetName?: string;
attachments: ApprovalAttachment[];
records: ApprovalRecord[];
confirms: ApprovalConfirm[];
myTask?: ApprovalMyTask | null;
permissions: ApprovalPermissions;
}
/**
* 业务完成确认单草稿参数
*/
export interface ApprovalCompletionForm {
id?: number;
name: string;
implementOrg: string;
fee: number | string;
serviceContent: string;
}
/**
* 我发起的查询参数
*/
export interface ApprovalMineParam extends PageParam {
status?: string;
docType?: string;
}
/**
* 组织
*/
export interface ApprovalOrganization {
organizationId: number;
parentId?: number;
organizationName: string;
organizationFullName?: string;
organizationCode?: string;
leaderId?: number;
}
+16
View File
@@ -0,0 +1,16 @@
import request from '@/utils/request';
import type { ApiResult } from '@/api';
import { THINK_API_URL } from '@/config/setting';
/**
* 待办数量(个人中心红点)
*/
export async function getTodoCount() {
const res = await request.get<ApiResult<number>>(
THINK_API_URL + '/approval/todo/count'
);
if (res.data.code === 0 && res.data.data !== undefined) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}