merge: feat/approval-phase1 并入待办审批分支 (#22)

- 解决 api/approval/instance 冲突:保留单据查询分页与详情,追加我的待办分页
- 统一类型到 api/approval/instance/model,删除重复的 api/approval/model
- 候选用户改用 api/approval/directory 的 searchApprovalUsers,去重
This commit is contained in:
2026-10-30 21:05:06 +08:00
9 changed files with 860 additions and 84 deletions
+34
View File
@@ -0,0 +1,34 @@
import request from '@/utils/request';
import type { ApiResult } from '@/api';
import type { ApprovalOrganization, ApprovalUser } from '../instance/model';
import { THINK_API_URL } from '@/config/setting';
/**
* 启用组织(审批管理下拉)
*/
export async function listApprovalOrganizations() {
const res = await request.get<ApiResult<ApprovalOrganization[]>>(
THINK_API_URL + '/approval/directory/organizations'
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 启用用户远程搜索(审批管理下拉)
*/
export async function searchApprovalUsers(params?: {
keywords?: string;
organizationId?: number;
}) {
const res = await request.get<ApiResult<ApprovalUser[]>>(
THINK_API_URL + '/approval/directory/users',
{ params }
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
+24 -11
View File
@@ -1,36 +1,49 @@
import request from '@/utils/request';
import type { ApiResult, PageResult } from '@/api';
import { THINK_API_URL } from '@/config/setting';
import type {
ApprovalInstance,
ApprovalItem,
ApprovalItemParam
} from '../model';
ApprovalQueryParam,
ApprovalTodoParam
} from './model';
import { THINK_API_URL } from '@/config/setting';
/**
* 单据查询分页
*/
export async function pageInstances(params: ApprovalQueryParam) {
const res = await request.get<ApiResult<PageResult<ApprovalItem>>>(
THINK_API_URL + '/approval/instance/page',
{ params }
);
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 我的待办分页
*/
export async function pageApprovalTodo(params: ApprovalItemParam) {
export async function pageApprovalTodo(params: ApprovalTodoParam) {
const res = await request.get<ApiResult<PageResult<ApprovalItem>>>(
THINK_API_URL + '/approval/todo/page',
{
params
}
{ params }
);
if (res.data.code === 0 && res.data.data) {
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
/**
* 审批单据详情
* 单据详情(只读)
*/
export async function getApprovalInstance(id: number) {
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) {
if (res.data.code === 0) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
@@ -1,48 +1,56 @@
import type { PageParam } from '@/api';
/**
* 审批单据列表项
* 单据查询条件
*/
export interface ApprovalQueryParam extends PageParam {
// 单据类型 completion/coordination
docType?: string;
// 单号
bizNo?: string;
// 关键词:单号、名称或标题、实施单位
keyword?: string;
// 报送部门id
reportOrgId?: number;
// 受理部门id
acceptOrgId?: number;
// 发起人id
reporterId?: number;
// 单据状态
status?: string;
// 提交时间起
submitTimeStart?: string;
// 提交时间止
submitTimeEnd?: string;
// 归档时间起
archiveTimeStart?: string;
// 归档时间止
archiveTimeEnd?: string;
}
/**
* 单据列表行
*/
export interface ApprovalItem {
id?: number;
// 单号
bizNo?: string;
// 单据类型:completion / coordination
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 ApprovalItemParam extends PageParam {
status?: string;
docType?: string;
keywords?: string;
}
/**
* 审批附件
* 附件
*/
export interface ApprovalAttachment {
id?: number;
@@ -75,7 +83,7 @@ export interface ApprovalRecord {
}
/**
* 当前轮存档确认人
* 当前轮存档确认
*/
export interface ApprovalConfirm {
userId?: number;
@@ -86,7 +94,7 @@ export interface ApprovalConfirm {
}
/**
* 当前用户的待办任务
* 我的待处理任务
*/
export interface ApprovalMyTask {
id?: number;
@@ -96,22 +104,7 @@ export interface ApprovalMyTask {
}
/**
* 详情动作权限
*/
export interface ApprovalPermissions {
canEdit?: boolean;
canSubmit?: boolean;
canWithdraw?: boolean;
canApprove?: boolean;
canReject?: boolean;
canConfirm?: boolean;
canArchive?: boolean;
canDispatch?: boolean;
canAssign?: boolean;
}
/**
* 审批单据详情
* 单据详情
*/
export interface ApprovalInstance {
id?: number;
@@ -136,12 +129,12 @@ export interface ApprovalInstance {
archiveTime?: string;
archivistId?: number;
archivistName?: string;
// 业务完成确认单字段
// 业务完成确认单
name?: string;
implementOrg?: string;
fee?: number;
serviceContent?: string;
// 内部协调单字段
// 内部协调单
title?: string;
content?: string;
remark?: string;
@@ -151,11 +144,23 @@ export interface ApprovalInstance {
records?: ApprovalRecord[];
confirms?: ApprovalConfirm[];
myTask?: ApprovalMyTask | null;
permissions?: ApprovalPermissions;
permissions?: Record<string, boolean>;
}
/**
* 改派候选用户
* 审批目录组织
*/
export interface ApprovalOrganization {
organizationId?: number;
parentId?: number;
organizationName?: string;
organizationFullName?: string;
organizationCode?: string;
leaderId?: number;
}
/**
* 审批目录用户
*/
export interface ApprovalUser {
userId?: number;
@@ -167,10 +172,24 @@ export interface ApprovalUser {
}
/**
* 改派参数
* 待办/已办查询条件
*/
export interface ApprovalTodoParam extends PageParam {
// 单据状态
status?: string;
// 单据类型
docType?: string;
// 关键词:单号、名称或标题、实施单位
keywords?: string;
}
/**
* 待办改派参数
*/
export interface ApprovalAssignParam {
// 改派对象用户id
targetUserId: number;
// 改派原因
reason: string;
}
+2 -19
View File
@@ -3,9 +3,8 @@ import type { ApiResult } from '@/api';
import { THINK_API_URL } from '@/config/setting';
import type {
ApprovalAssignParam,
ApprovalAssignResult,
ApprovalUser
} from '../model';
ApprovalAssignResult
} from '../instance/model';
/**
* 通过任务
@@ -77,19 +76,3 @@ export async function assignApprovalTask(
}
return Promise.reject(new Error(res.data.message));
}
/**
* 改派候选用户:同租户启用用户,最多 50 条
*/
export async function searchApprovalUsers(keywords?: string) {
const res = await request.get<ApiResult<ApprovalUser[]>>(
THINK_API_URL + '/approval/directory/users',
{
params: { keywords }
}
);
if (res.data.code === 0 && res.data.data) {
return res.data.data;
}
return Promise.reject(new Error(res.data.message));
}
@@ -0,0 +1,280 @@
<!-- 单据详情抽屉(只读) -->
<template>
<ele-modal
title="单据详情"
:width="860"
:footer="null"
:visible="visible"
@update:visible="updateVisible"
>
<a-spin :spinning="loading">
<template v-if="data">
<a-descriptions
:column="2"
size="small"
bordered
:label-style="{ width: '110px' }"
>
<a-descriptions-item label="单号">
{{ data.bizNo || '-' }}
</a-descriptions-item>
<a-descriptions-item label="单据类型">
{{ data.docTypeName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="状态">
<a-tag :color="statusColor(data.status)">
{{ data.statusName || '-' }}
</a-tag>
</a-descriptions-item>
<a-descriptions-item label="当前节点">
{{ data.currentNodeName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="发起人">
{{ data.reporterName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="报送部门">
{{ data.reportOrgName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="受理部门">
{{ data.acceptOrgName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="提交时间">
{{ toDateString(data.submitTime) || '-' }}
</a-descriptions-item>
<template v-if="data.docType === 'completion'">
<a-descriptions-item label="名称" :span="2">
{{ data.name || '-' }}
</a-descriptions-item>
<a-descriptions-item label="实施单位">
{{ data.implementOrg || '-' }}
</a-descriptions-item>
<a-descriptions-item label="费用(元)">
{{ data.fee ?? '-' }}
</a-descriptions-item>
<a-descriptions-item label="服务内容" :span="2">
<div class="ele-text-break">{{ data.serviceContent || '-' }}</div>
</a-descriptions-item>
</template>
<template v-else>
<a-descriptions-item label="标题" :span="2">
{{ data.title || '-' }}
</a-descriptions-item>
<a-descriptions-item label="协调内容" :span="2">
<div class="ele-text-break">{{ data.content || '-' }}</div>
</a-descriptions-item>
<a-descriptions-item label="备注" :span="2">
<div class="ele-text-break">{{ data.remark || '-' }}</div>
</a-descriptions-item>
<a-descriptions-item label="派单对象">
{{ data.dispatchTargetName || '-' }}
</a-descriptions-item>
<a-descriptions-item label="审批完成时间">
{{ toDateString(data.approveTime) || '-' }}
</a-descriptions-item>
</template>
<a-descriptions-item label="归档时间">
{{ toDateString(data.archiveTime) || '-' }}
</a-descriptions-item>
<a-descriptions-item label="归档人">
{{ data.archivistName || '-' }}
</a-descriptions-item>
</a-descriptions>
<a-divider orientation="left">附件</a-divider>
<div v-if="data.attachments && data.attachments.length">
<div
v-for="attachment in data.attachments"
:key="attachment.id"
class="attachment-item"
>
<a :href="attachment.url" target="_blank" rel="noopener noreferrer">
{{ attachment.name || '附件' }}
</a>
<a-tag style="margin-left: 8px">
{{ attachment.categoryName || '-' }}
</a-tag>
<span class="ele-text-secondary" style="margin-left: 8px">
{{ sizeText(attachment.length) }}
</span>
</div>
</div>
<div v-else class="ele-text-secondary">暂无附件</div>
<a-divider orientation="left">存档确认</a-divider>
<div v-if="data.confirms && data.confirms.length">
<div
v-for="confirm in data.confirms"
:key="confirm.userId"
class="confirm-item"
>
<span>{{ confirm.userName || '-' }}</span>
<a-tag
style="margin-left: 8px"
:color="confirm.status === 'DONE' ? 'green' : 'default'"
>
{{ confirm.statusName || '-' }}
</a-tag>
<span class="ele-text-secondary" style="margin-left: 8px">
{{ toDateString(confirm.handleTime) || '' }}
</span>
</div>
</div>
<div v-else class="ele-text-secondary">尚未进入存档环节</div>
<a-divider orientation="left">处理记录</a-divider>
<a-timeline v-if="data.records && data.records.length">
<a-timeline-item
v-for="record in data.records"
:key="record.id"
:color="actionColor(record.action)"
>
<div>
<span style="font-weight: 500">
{{ record.operatorName || '-' }}
</span>
<span style="margin-left: 8px">
{{ record.actionName || record.action }}
</span>
<span
v-if="record.nodeName"
class="ele-text-secondary"
style="margin-left: 8px"
>
({{ record.nodeName }})
</span>
</div>
<div v-if="record.opinion" class="ele-text-secondary">
意见:{{ record.opinion }}
</div>
<div class="ele-text-secondary">
{{ toDateString(record.createTime) }}
</div>
</a-timeline-item>
</a-timeline>
<div v-else class="ele-text-secondary">暂无处理记录</div>
</template>
<a-empty v-else-if="!loading" description="暂无数据" />
</a-spin>
</ele-modal>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue';
import { message } from 'ant-design-vue/es';
import { toDateString } from 'ele-admin-pro/es';
import { getInstance } from '@/api/approval/instance';
import type { ApprovalInstance } from '@/api/approval/instance/model';
const emit = defineEmits<{
(e: 'update:visible', visible: boolean): void;
}>();
const props = defineProps<{
// 抽屉是否打开
visible: boolean;
// 单据id
instanceId?: number;
}>();
// 详情数据
const data = ref<ApprovalInstance | null>(null);
// 加载状态
const loading = ref(false);
// 状态颜色
const statusColor = (status?: string) => {
switch (status) {
case 'PENDING':
return 'processing';
case 'REJECTED':
return 'red';
case 'WITHDRAWN':
return 'orange';
case 'APPROVED':
return 'green';
case 'ARCHIVED':
return 'blue';
default:
return 'default';
}
};
// 处理记录颜色
const actionColor = (action?: string) => {
switch (action) {
case 'APPROVE':
case 'CONFIRM':
case 'ARCHIVE':
return 'green';
case 'REJECT':
return 'red';
default:
return 'blue';
}
};
// 附件大小
const sizeText = (length?: number) => {
if (!length && length !== 0) {
return '';
}
if (length < 1024) {
return length + ' B';
}
if (length < 1024 * 1024) {
return (length / 1024).toFixed(1) + ' KB';
}
return (length / 1024 / 1024).toFixed(1) + ' MB';
};
/* 更新visible */
const updateVisible = (value: boolean) => {
emit('update:visible', value);
};
/* 加载详情 */
const loadData = () => {
if (!props.instanceId) {
data.value = null;
return;
}
loading.value = true;
data.value = null;
getInstance(props.instanceId)
.then((result) => {
data.value = result;
loading.value = false;
})
.catch((e) => {
loading.value = false;
message.error(e.message);
});
};
watch(
() => [props.visible, props.instanceId],
() => {
if (props.visible) {
loadData();
} else {
data.value = null;
}
},
{ immediate: true }
);
</script>
<style lang="less" scoped>
.attachment-item {
padding: 4px 0;
}
.confirm-item {
padding: 4px 0;
}
.ele-text-break {
white-space: pre-wrap;
word-break: break-all;
}
</style>
@@ -0,0 +1,254 @@
<!-- 单据查询搜索表单 -->
<template>
<a-form
:label-col="
styleResponsive ? { xl: 7, lg: 5, md: 7, sm: 4 } : { flex: '90px' }
"
:wrapper-col="
styleResponsive ? { xl: 17, lg: 19, md: 17, sm: 20 } : { flex: '1' }
"
>
<a-row :gutter="8">
<a-col v-for="field in basicFields" :key="field.prop" v-bind="colSpan">
<a-form-item :label="field.label">
<a-select
v-if="field.prop === 'docType'"
v-model:value="form.docType"
placeholder="全部"
allow-clear
:options="docTypeOptions"
/>
<a-select
v-else-if="field.prop === 'status'"
v-model:value="form.status"
placeholder="全部"
allow-clear
:options="statusOptions"
/>
<a-select
v-else-if="field.prop === 'reportOrgId'"
v-model:value="form.reportOrgId"
placeholder="全部"
allow-clear
show-search
:filter-option="filterOrganization"
:options="organizationOptions"
/>
<a-select
v-else-if="field.prop === 'acceptOrgId'"
v-model:value="form.acceptOrgId"
placeholder="全部"
allow-clear
show-search
:filter-option="filterOrganization"
:options="organizationOptions"
/>
<a-select
v-else-if="field.prop === 'reporterId'"
v-model:value="form.reporterId"
placeholder="输入姓名或账号搜索"
allow-clear
show-search
:filter-option="false"
:options="userOptions"
:loading="userLoading"
@search="searchUsers"
/>
<a-input
v-else
v-model:value.trim="form[field.prop]"
placeholder="请输入"
allow-clear
/>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="提交时间">
<a-range-picker
v-model:value="submitRange"
:show-time="true"
value-format="YYYY-MM-DD HH:mm:ss"
class="ele-fluid"
/>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item label="归档时间">
<a-range-picker
v-model:value="archiveRange"
:show-time="true"
value-format="YYYY-MM-DD HH:mm:ss"
class="ele-fluid"
/>
</a-form-item>
</a-col>
<a-col v-bind="colSpan">
<a-form-item class="ele-text-right" :wrapper-col="{ span: 24 }">
<a-space>
<a-button type="primary" @click="search">查询</a-button>
<a-button @click="reset">重置</a-button>
</a-space>
</a-form-item>
</a-col>
</a-row>
</a-form>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue';
import { storeToRefs } from 'pinia';
import { useThemeStore } from '@/store/modules/theme';
import useFormData from '@/utils/use-form-data';
import {
listApprovalOrganizations,
searchApprovalUsers
} from '@/api/approval/directory';
import type {
ApprovalOrganization,
ApprovalQueryParam,
ApprovalUser
} from '@/api/approval/instance/model';
const emit = defineEmits<{
(e: 'search', where?: ApprovalQueryParam): void;
}>();
// 是否开启响应式布局
const themeStore = useThemeStore();
const { styleResponsive } = storeToRefs(themeStore);
// 栅格宽度
const colSpan = {
xl: 6,
lg: 12,
md: 12,
sm: 24,
xs: 24
};
// 基础字段
const basicFields: {
prop:
| 'docType'
| 'bizNo'
| 'keyword'
| 'reportOrgId'
| 'acceptOrgId'
| 'reporterId'
| 'status';
label: string;
}[] = [
{ prop: 'docType', label: '单据类型' },
{ prop: 'bizNo', label: '单号' },
{ prop: 'keyword', label: '标题或名称' },
{ prop: 'reportOrgId', label: '报送部门' },
{ prop: 'acceptOrgId', label: '受理部门' },
{ prop: 'reporterId', label: '发起人' },
{ prop: 'status', label: '状态' }
];
// 单据类型选项
const docTypeOptions = [
{ label: '业务完成确认单', value: 'completion' },
{ label: '内部协调单', value: 'coordination' }
];
// 状态选项
const statusOptions = [
{ label: '未提交', value: 'DRAFT' },
{ label: '审批中', value: 'PENDING' },
{ label: '已驳回', value: 'REJECTED' },
{ label: '已撤回', value: 'WITHDRAWN' },
{ label: '审批完成', value: 'APPROVED' },
{ label: '已归档', value: 'ARCHIVED' }
];
// 表单数据
const { form, resetFields } = useFormData<ApprovalQueryParam>({
docType: undefined,
bizNo: '',
keyword: '',
reportOrgId: undefined,
acceptOrgId: undefined,
reporterId: undefined,
status: undefined
});
// 提交时间范围
const submitRange = ref<[string, string]>(['', '']);
// 归档时间范围
const archiveRange = ref<[string, string]>(['', '']);
// 组织下拉选项
const organizationOptions = ref<{ label: string; value: number }[]>([]);
// 发起人下拉选项
const userOptions = ref<{ label: string; value: number }[]>([]);
// 发起人请求状态
const userLoading = ref(false);
// 组织远程过滤
const filterOrganization = (input: string, option: { label: string }) => {
return (option?.label ?? '').toLowerCase().includes(input.toLowerCase());
};
// 远程搜索发起人
const searchUsers = (keywords?: string) => {
userLoading.value = true;
searchApprovalUsers({ keywords })
.then((data) => {
userOptions.value = data.map((user: ApprovalUser) => ({
label:
(user.realName || user.nickname || user.username || '') +
(user.username ? '(' + user.username + ')' : ''),
value: user.userId as number
}));
})
.catch(() => {
userOptions.value = [];
})
.finally(() => {
userLoading.value = false;
});
};
/* 搜索 */
const search = () => {
const [submitTimeStart, submitTimeEnd] = submitRange.value ?? ['', ''];
const [archiveTimeStart, archiveTimeEnd] = archiveRange.value ?? ['', ''];
emit('search', {
...form,
submitTimeStart,
submitTimeEnd,
archiveTimeStart,
archiveTimeEnd
});
};
/* 重置 */
const reset = () => {
resetFields();
submitRange.value = ['', ''];
archiveRange.value = ['', ''];
userOptions.value = [];
search();
};
onMounted(() => {
listApprovalOrganizations()
.then((data) => {
organizationOptions.value = data.map(
(organization: ApprovalOrganization) => ({
label:
organization.organizationFullName ||
organization.organizationName ||
'',
value: organization.organizationId as number
})
);
})
.catch(() => {
organizationOptions.value = [];
});
});
</script>
+188
View File
@@ -0,0 +1,188 @@
<!-- 审批管理 - 单据查询 -->
<template>
<div class="ele-body">
<a-card :bordered="false">
<!-- 搜索表单 -->
<search @search="reload" />
<!-- 表格 -->
<ele-pro-table
ref="tableRef"
row-key="id"
:columns="columns"
:datasource="datasource"
:scroll="{ x: 1500 }"
cache-key="proApprovalInstanceTable"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'docType'">
<a-tag :color="record.docType === 'completion' ? 'blue' : 'purple'">
{{ record.docTypeName }}
</a-tag>
</template>
<template v-else-if="column.key === 'status'">
<a-tag :color="statusColor(record.status)">
{{ record.statusName }}
</a-tag>
</template>
<template v-else-if="column.key === 'submitTime'">
{{ toDateString(record.submitTime) || '-' }}
</template>
<template v-else-if="column.key === 'archiveTime'">
{{ toDateString(record.archiveTime) || '-' }}
</template>
<template v-else-if="column.key === 'action'">
<a @click="openDetail(record)">详情</a>
</template>
</template>
</ele-pro-table>
</a-card>
<!-- 详情抽屉 -->
<detail v-model:visible="showDetail" :instance-id="currentId" />
</div>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import type { EleProTable } from 'ele-admin-pro/es';
import { toDateString } from 'ele-admin-pro/es';
import type {
DatasourceFunction,
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import Search from './components/search.vue';
import Detail from './components/detail.vue';
import { pageInstances } from '@/api/approval/instance';
import type {
ApprovalItem,
ApprovalQueryParam
} from '@/api/approval/instance/model';
// 表格实例
const tableRef = ref<InstanceType<typeof EleProTable> | null>(null);
// 详情抽屉是否显示
const showDetail = ref(false);
// 当前查看的单据id
const currentId = ref<number | undefined>(undefined);
// 表格数据源
const datasource: DatasourceFunction = ({ page, limit, where }) => {
return pageInstances({
...(where as ApprovalQueryParam),
page,
limit
});
};
// 表格列配置
const columns = ref<ColumnItem[]>([
{
title: '单号',
dataIndex: 'bizNo',
width: 180,
ellipsis: true,
customRender: ({ text }) => text || '-'
},
{
title: '单据类型',
key: 'docType',
dataIndex: 'docType',
width: 140,
align: 'center'
},
{
title: '标题或名称',
dataIndex: 'title',
minWidth: 220,
ellipsis: true
},
{
title: '报送部门',
dataIndex: 'reportOrgName',
width: 180,
ellipsis: true
},
{
title: '报送人',
dataIndex: 'reporterName',
width: 120,
ellipsis: true
},
{
title: '受理部门',
dataIndex: 'acceptOrgName',
width: 180,
ellipsis: true
},
{
title: '状态',
key: 'status',
dataIndex: 'status',
width: 110,
align: 'center'
},
{
title: '当前节点',
dataIndex: 'currentNodeName',
width: 140,
ellipsis: true
},
{
title: '提交时间',
key: 'submitTime',
dataIndex: 'submitTime',
width: 170,
align: 'center'
},
{
title: '归档时间',
key: 'archiveTime',
dataIndex: 'archiveTime',
width: 170,
align: 'center'
},
{
title: '操作',
key: 'action',
width: 90,
align: 'center',
fixed: 'right',
hideInSetting: true
}
]);
// 状态颜色
const statusColor = (status?: string) => {
switch (status) {
case 'PENDING':
return 'processing';
case 'REJECTED':
return 'red';
case 'WITHDRAWN':
return 'orange';
case 'APPROVED':
return 'green';
case 'ARCHIVED':
return 'blue';
default:
return 'default';
}
};
/* 刷新表格 */
const reload = (where?: ApprovalQueryParam) => {
tableRef?.value?.reload({ page: 1, where: where ?? {} });
};
/* 打开详情 */
const openDetail = (row: ApprovalItem) => {
currentId.value = row.id;
showDetail.value = true;
};
</script>
<script lang="ts">
export default {
name: 'ApprovalInstance'
};
</script>
@@ -268,15 +268,15 @@
import type {
ApprovalAttachment,
ApprovalInstance
} from '@/api/approval/model';
import { getApprovalInstance } from '@/api/approval/instance';
} from '@/api/approval/instance/model';
import { getInstance } from '@/api/approval/instance';
import { searchApprovalUsers } from '@/api/approval/directory';
import {
approveApprovalTask,
archiveApprovalTask,
assignApprovalTask,
confirmApprovalTask,
rejectApprovalTask,
searchApprovalUsers
rejectApprovalTask
} from '@/api/approval/task';
import {
approvalStatusColor,
@@ -317,7 +317,7 @@
}
loading.value = true;
try {
detail.value = await getApprovalInstance(props.instanceId);
detail.value = await getInstance(props.instanceId);
} catch (e: any) {
detail.value = null;
message.error(e.message);
@@ -456,7 +456,9 @@
const doSearchUsers = async (keywords?: string) => {
userLoading.value = true;
try {
const users = await searchApprovalUsers(keywords?.trim() || undefined);
const users = await searchApprovalUsers({
keywords: keywords?.trim() || undefined
});
userOptions.value = users.map((user) => ({
value: user.userId as number,
label:
+5 -2
View File
@@ -68,7 +68,10 @@
ColumnItem
} from 'ele-admin-pro/es/ele-pro-table/types';
import useSearch from '@/utils/use-search';
import type { ApprovalItem, ApprovalItemParam } from '@/api/approval/model';
import type {
ApprovalItem,
ApprovalTodoParam
} from '@/api/approval/instance/model';
import { pageApprovalTodo } from '@/api/approval/instance';
import { approvalStatusColor, formatApprovalTime } from './format';
import DetailDrawer from './components/detail-drawer.vue';
@@ -81,7 +84,7 @@
const currentId = ref<number | null>(null);
// 搜索条件
const { where, resetFields } = useSearch<ApprovalItemParam>({
const { where, resetFields } = useSearch<ApprovalTodoParam>({
status: undefined,
keywords: undefined
});