优化报销功能
This commit is contained in:
1 parent
395c7f717e
commit
4306cbd74b
19 files changed
+2059
-534
No files matched your search
@@ -0,0 +1,228 @@
|
||||
<template>
|
||||
<div class="approval-page">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h2>审批列表</h2>
|
||||
<p>处理待我审批的单据,并查看已处理记录</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<el-radio-group v-model="filters.handled" @change="handleScopeChange">
|
||||
<el-radio-button :value="0">待我审批</el-radio-button>
|
||||
<el-radio-button :value="1">我已处理</el-radio-button>
|
||||
</el-radio-group>
|
||||
<el-button :icon="Refresh" @click="loadList">刷新</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-card">
|
||||
<el-form :inline="true" :model="filters" @submit.prevent>
|
||||
<el-form-item label="单据类型">
|
||||
<el-select
|
||||
v-model="filters.biz_type"
|
||||
clearable
|
||||
placeholder="全部类型"
|
||||
style="width: 160px"
|
||||
@change="loadList"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in bizTypes"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" :icon="Search" @click="loadList">查询</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<div class="table-card">
|
||||
<div class="table-scroll">
|
||||
<el-table v-loading="loading" :data="list" stripe>
|
||||
<el-table-column label="单据标题" min-width="200" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.instance?.biz_title || "-" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单据类型" width="120">
|
||||
<template #default="{ row }">{{ row.instance?.biz_type || "-" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="发起人" width="120">
|
||||
<template #default="{ row }">{{ row.instance?.submit_user_name || "-" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="node_name" label="审批节点" width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.node_name || row.node_key || "-" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="单据状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="tagType(row.instance?.status_tag)">{{
|
||||
row.instance?.status_label || "-"
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="任务状态" width="110">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="tagType(row.status_tag)">{{ row.status_label || "-" }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="create_time" label="到达时间" width="170">
|
||||
<template #default="{ row }">{{ row.create_time || "-" }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="180">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDetail(row.instance_id)">详情</el-button>
|
||||
<el-button
|
||||
v-if="row.status === 0"
|
||||
link
|
||||
type="primary"
|
||||
@click="openDetail(row.instance_id)"
|
||||
>去处理</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<template #empty><el-empty :description="emptyText" /></template>
|
||||
</el-table>
|
||||
</div>
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
:current-page="pagination.page"
|
||||
:page-size="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
@update:current-page="pagination.page = $event"
|
||||
@update:page-size="pagination.pageSize = $event"
|
||||
@current-change="loadList"
|
||||
@size-change="loadList"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DetailDrawer v-model="detailVisible" :instance-id="detailId" @changed="loadList" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { Refresh, Search } from "@element-plus/icons-vue";
|
||||
import DetailDrawer from "./components/DetailDrawer.vue";
|
||||
import { getApprovalTodo } from "@/api/approval";
|
||||
|
||||
const bizTypes = [
|
||||
{ value: "reimburse", label: "报销单" },
|
||||
{ value: "oa", label: "OA 通用审批" },
|
||||
];
|
||||
|
||||
const filters = reactive({ handled: 0, biz_type: "" });
|
||||
const pagination = reactive({ page: 1, pageSize: 10, total: 0 });
|
||||
const list = ref([]);
|
||||
const loading = ref(false);
|
||||
const detailVisible = ref(false);
|
||||
const detailId = ref("");
|
||||
|
||||
const emptyText = computed(() =>
|
||||
filters.handled === 1 ? "暂无已处理的审批" : "暂无待我审批的单据",
|
||||
);
|
||||
|
||||
const responseData = (res) => res?.data?.data ?? res?.data ?? res ?? {};
|
||||
|
||||
const loadList = async () => {
|
||||
loading.value = true;
|
||||
try {
|
||||
const data = responseData(
|
||||
await getApprovalTodo({
|
||||
handled: filters.handled,
|
||||
biz_type: filters.biz_type || "",
|
||||
page: pagination.page,
|
||||
pageSize: pagination.pageSize,
|
||||
}),
|
||||
);
|
||||
// 前端二次过滤:类型下拉切换后即时生效
|
||||
const rows = data.list || [];
|
||||
list.value = filters.biz_type
|
||||
? rows.filter((row) => row.instance?.biz_type === filters.biz_type)
|
||||
: rows;
|
||||
pagination.total = Number(data.total || 0);
|
||||
} catch (error) {
|
||||
ElMessage.error(error?.message || "加载审批列表失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleScopeChange = () => {
|
||||
pagination.page = 1;
|
||||
loadList();
|
||||
};
|
||||
|
||||
const openDetail = (id) => {
|
||||
detailId.value = id;
|
||||
detailVisible.value = true;
|
||||
};
|
||||
|
||||
function tagType(type) {
|
||||
if (type === "error") return "danger";
|
||||
return type || "info";
|
||||
}
|
||||
|
||||
onMounted(loadList);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.approval-page {
|
||||
background: #f5f7fa;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
|
||||
h2 {
|
||||
margin: 0 0 8px;
|
||||
color: #303133;
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
color: #909399;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.filter-card,
|
||||
.table-card {
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
padding: 18px;
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.filter-card {
|
||||
margin-bottom: 16px;
|
||||
|
||||
:deep(.el-form-item) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.table-scroll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user