feat(approvalCenter): 添加审批中心列表页功能及搜索过滤
- 在接口定义中添加handleStatus和searchStr字段支持搜索过滤 - 实现审批列表的数据加载、分页和搜索功能 - 添加表格展示及状态标签显示 - 实现不同菜单下的数据切换和加载
This commit is contained in:
parent
52f8cbff4a
commit
80dc7ecd58
|
@ -18,6 +18,18 @@ export interface SearchReturnApprovalQuery extends BasePageQuery {
|
||||||
* 0为借还柜 1为固资通
|
* 0为借还柜 1为固资通
|
||||||
*/
|
*/
|
||||||
approvalType: number;
|
approvalType: number;
|
||||||
|
/**
|
||||||
|
* 处理状态
|
||||||
|
* @remarks
|
||||||
|
* 0:待处理 1:已处理
|
||||||
|
*/
|
||||||
|
handleStatus?: number;
|
||||||
|
/**
|
||||||
|
* 搜索字符串
|
||||||
|
* @remarks
|
||||||
|
* 搜索商品名称、申请人
|
||||||
|
*/
|
||||||
|
searchStr?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 退货审批DTO */
|
/** 退货审批DTO */
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, markRaw } from 'vue';
|
import { ref, computed, markRaw, watch, onMounted } from 'vue';
|
||||||
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||||
|
import { PureTableBar } from "@/components/RePureTableBar";
|
||||||
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
import {
|
import {
|
||||||
Calendar,
|
Calendar,
|
||||||
Briefcase,
|
Briefcase,
|
||||||
|
@ -20,7 +23,11 @@ import {
|
||||||
RefreshRight,
|
RefreshRight,
|
||||||
Wallet,
|
Wallet,
|
||||||
CreditCard,
|
CreditCard,
|
||||||
|
Search,
|
||||||
|
Refresh
|
||||||
} from '@element-plus/icons-vue';
|
} from '@element-plus/icons-vue';
|
||||||
|
import { getReturnApprovalListApi } from '@/api/shop/approval';
|
||||||
|
import { debounce } from "@pureadmin/utils";
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: "approvalCenter"
|
name: "approvalCenter"
|
||||||
|
@ -33,7 +40,23 @@ const activeMenu = ref('apply');
|
||||||
const activeTab = ref('all');
|
const activeTab = ref('all');
|
||||||
|
|
||||||
// 搜索关键词
|
// 搜索关键词
|
||||||
const searchKey = ref('');
|
const searchFormParams = ref({
|
||||||
|
status: null,
|
||||||
|
searchStr: null
|
||||||
|
});
|
||||||
|
// 分页参数
|
||||||
|
const pagination = ref({
|
||||||
|
pageSize: 5,
|
||||||
|
currentPage: 1,
|
||||||
|
total: 0
|
||||||
|
});
|
||||||
|
// 列表数据
|
||||||
|
const pendingList = ref([]);
|
||||||
|
const processedList = ref([]);
|
||||||
|
const ccList = ref([]);
|
||||||
|
const submittedList = ref([]);
|
||||||
|
const loading = ref(false);
|
||||||
|
const multipleSelection = ref([]);
|
||||||
|
|
||||||
// 申请类型数据(按标签栏分类)
|
// 申请类型数据(按标签栏分类)
|
||||||
const applicationData = ref({
|
const applicationData = ref({
|
||||||
|
@ -51,18 +74,12 @@ const applicationData = ref({
|
||||||
{ icon: markRaw(Wallet), name: '退款', color: '#795548' }
|
{ icon: markRaw(Wallet), name: '退款', color: '#795548' }
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
applicationData.value.all = [...applicationData.value.shop, ...applicationData.value.other];
|
||||||
|
|
||||||
// 计算属性:合并“全部”类型数据
|
// 计算属性:过滤申请类型
|
||||||
applicationData.value.all = [
|
|
||||||
...applicationData.value.shop,
|
|
||||||
...applicationData.value.other,
|
|
||||||
];
|
|
||||||
|
|
||||||
// 计算属性:根据当前标签栏和搜索关键词过滤申请类型
|
|
||||||
const filteredApplications = computed(() => {
|
const filteredApplications = computed(() => {
|
||||||
const data = applicationData.value[activeTab.value] || [];
|
const data = applicationData.value[activeTab.value] || [];
|
||||||
if (!searchKey.value) return data;
|
return data;
|
||||||
return data.filter(item => item.name.includes(searchKey.value));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// 处理左侧菜单选中
|
// 处理左侧菜单选中
|
||||||
|
@ -75,15 +92,105 @@ const handleTabChange = (tab: any) => {
|
||||||
activeTab.value = tab.name;
|
activeTab.value = tab.name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 处理搜索(可扩展为接口请求)
|
// 搜索
|
||||||
const handleSearch = () => {
|
const onSearch = () => {
|
||||||
console.log('搜索关键词:', searchKey.value);
|
pagination.value.currentPage = 1;
|
||||||
|
loadData();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 防抖搜索
|
||||||
|
const debouncedSearch = debounce(onSearch, 500);
|
||||||
|
|
||||||
|
// 监听搜索关键词变化
|
||||||
|
watch(
|
||||||
|
() => searchFormParams.value.searchStr,
|
||||||
|
(newVal) => {
|
||||||
|
debouncedSearch();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重置
|
||||||
|
const resetForm = () => {
|
||||||
|
Object.assign(searchFormParams.value, {
|
||||||
|
approvalId: null,
|
||||||
|
orderId: null,
|
||||||
|
goodsId: null,
|
||||||
|
status: null,
|
||||||
|
approvalTime: null,
|
||||||
|
paymentMethod: null
|
||||||
|
});
|
||||||
|
onSearch();
|
||||||
|
};
|
||||||
|
|
||||||
|
// 分页变化
|
||||||
|
const handlePaginationChange = () => loadData();
|
||||||
|
|
||||||
|
// 加载列表数据
|
||||||
|
const loadData = async () => {
|
||||||
|
if (activeMenu.value !== 'received-pending' && activeMenu.value !== 'received-processed') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
const params = {
|
||||||
|
...searchFormParams.value,
|
||||||
|
approvalType: 0,
|
||||||
|
pageSize: pagination.value.pageSize,
|
||||||
|
pageNum: pagination.value.currentPage,
|
||||||
|
handleStatus: activeMenu.value === 'received-pending' ? 0 : activeMenu.value === 'received-processed' ? 1 : undefined
|
||||||
|
};
|
||||||
|
const { data } = await getReturnApprovalListApi(params);
|
||||||
|
const formattedData = data.rows.map(item => ({
|
||||||
|
...item,
|
||||||
|
statusStr: { 1: '待审核', 2: '已通过', 3: '已驳回' }[item.status],
|
||||||
|
paymentMethodStr: { wechat: '微信支付', balance: '余额支付' }[item.paymentMethod] || item.paymentMethod
|
||||||
|
}));
|
||||||
|
switch (activeMenu.value) {
|
||||||
|
case 'received-pending': pendingList.value = formattedData; break;
|
||||||
|
case 'received-processed': processedList.value = formattedData; break;
|
||||||
|
}
|
||||||
|
pagination.value.total = data.total;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载数据失败', error);
|
||||||
|
ElMessage.error('加载数据失败');
|
||||||
|
} finally {
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听菜单变化加载数据
|
||||||
|
watch(activeMenu, () => {
|
||||||
|
if (['received-pending', 'received-processed', 'cc', 'submitted-sent'].includes(activeMenu.value)) {
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 获取当前列表数据
|
||||||
|
const currentList = computed(() => {
|
||||||
|
switch (activeMenu.value) {
|
||||||
|
case 'received-pending': return pendingList.value;
|
||||||
|
case 'received-processed': return processedList.value;
|
||||||
|
case 'cc': return ccList.value;
|
||||||
|
case 'submitted-sent': return submittedList.value;
|
||||||
|
default: return [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 处理申请卡片点击(可扩展为跳转申请页面)
|
// 处理申请卡片点击(可扩展为跳转申请页面)
|
||||||
const handleCardClick = (item: any) => {
|
const handleCardClick = (item: any) => {
|
||||||
console.log('点击申请类型:', item.name);
|
console.log('点击申请类型:', item.name);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理选择变化
|
||||||
|
const handleSelectionChange = (val) => {
|
||||||
|
multipleSelection.value = val;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (['received-pending', 'received-processed', 'cc', 'submitted-sent'].includes(activeMenu.value)) {
|
||||||
|
loadData();
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,38 +199,21 @@ const handleCardClick = (item: any) => {
|
||||||
<!-- 左侧导航栏 -->
|
<!-- 左侧导航栏 -->
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<div class="custom-menu">
|
<div class="custom-menu">
|
||||||
<!-- 发起申请(无子类) -->
|
|
||||||
<div class="menu-item" :class="{ 'active': activeMenu === 'apply' }" @click="handleMenuSelect('apply')">
|
<div class="menu-item" :class="{ 'active': activeMenu === 'apply' }" @click="handleMenuSelect('apply')">
|
||||||
发起申请
|
发起申请
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 我收到的(有子类) -->
|
|
||||||
<div class="sub-menu">
|
<div class="sub-menu">
|
||||||
<div class="sub-menu-title"><span>我收到的</span></div>
|
<div class="sub-menu-title"><span>我收到的</span></div>
|
||||||
<div class="sub-menu-items">
|
<div class="sub-menu-items">
|
||||||
<div class="menu-item child" :class="{ 'active': activeMenu === 'received-pending' }"
|
<div class="menu-item child" :class="{ 'active': activeMenu === 'received-pending' }" @click="handleMenuSelect('received-pending')">待处理</div>
|
||||||
@click="handleMenuSelect('received-pending')">
|
<div class="menu-item child" :class="{ 'active': activeMenu === 'received-processed' }" @click="handleMenuSelect('received-processed')">已处理</div>
|
||||||
待处理
|
<div class="menu-item child" :class="{ 'active': activeMenu === 'cc' }" @click="handleMenuSelect('cc')">抄送我的</div>
|
||||||
</div>
|
|
||||||
<div class="menu-item child" :class="{ 'active': activeMenu === 'received-processed' }"
|
|
||||||
@click="handleMenuSelect('received-processed')">
|
|
||||||
已处理
|
|
||||||
</div>
|
|
||||||
<div class="menu-item child" :class="{ 'active': activeMenu === 'cc' }"
|
|
||||||
@click="handleMenuSelect('cc')">
|
|
||||||
已处理
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 我提交的(有子类) -->
|
|
||||||
<div class="sub-menu">
|
<div class="sub-menu">
|
||||||
<div class="sub-menu-title"><span>我提交的</span></div>
|
<div class="sub-menu-title"><span>我提交的</span></div>
|
||||||
<div class="sub-menu-items">
|
<div class="sub-menu-items">
|
||||||
<div class="menu-item child" :class="{ 'active': activeMenu === 'submitted-sent' }"
|
<div class="menu-item child" :class="{ 'active': activeMenu === 'submitted-sent' }" @click="handleMenuSelect('submitted-sent')">已提交</div>
|
||||||
@click="handleMenuSelect('submitted-sent')">
|
|
||||||
已提交
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -132,25 +222,88 @@ const handleCardClick = (item: any) => {
|
||||||
<!-- 右侧内容区域 -->
|
<!-- 右侧内容区域 -->
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<!-- 顶部导航(标签栏+搜索) -->
|
<!-- 顶部导航(标签栏+搜索) -->
|
||||||
<div class="content-header">
|
<div class="content-header" v-if="activeMenu === 'apply'">
|
||||||
<el-tabs v-model="activeTab" type="card" @tab-click="handleTabChange">
|
<el-tabs v-model="activeTab" type="card" @tab-click="handleTabChange">
|
||||||
<el-tab-pane label="全部" name="all"></el-tab-pane>
|
<el-tab-pane label="全部" name="all"></el-tab-pane>
|
||||||
<el-tab-pane label="借还审批" name="shop"></el-tab-pane>
|
<el-tab-pane label="借还审批" name="shop"></el-tab-pane>
|
||||||
<el-tab-pane label="其他" name="other"></el-tab-pane>
|
<el-tab-pane label="其他" name="other"></el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
|
|
||||||
<el-input v-model="searchKey" placeholder="搜索" prefix-icon="ep:search" class="search-input"
|
|
||||||
@keydown.enter.prevent="handleSearch" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 申请类型列表(根据标签栏切换) -->
|
<!-- 搜索表单 -->
|
||||||
<div class="application-list">
|
<el-form v-if="activeMenu !== 'apply'" :inline="true" :model="searchFormParams" class="search-form bg-bg_color flex w-[99/100]">
|
||||||
|
<el-form-item prop="approvalId">
|
||||||
|
<el-input @keydown.enter.prevent="onSearch" v-model.number="searchFormParams.searchStr" placeholder="请输入申请人/商品" clearable class="!w-[250px]" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
|
||||||
|
<!-- 列表视图 -->
|
||||||
|
<div v-if="activeMenu !== 'apply'" class="approval-list">
|
||||||
|
<el-table
|
||||||
|
:data="currentList"
|
||||||
|
v-loading="loading"
|
||||||
|
border
|
||||||
|
style="width: 100%"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
row-key="approvalId"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="55"></el-table-column>
|
||||||
|
<el-table-column prop="approvalId" label="审批ID" width="100"></el-table-column>
|
||||||
|
<el-table-column prop="name" label="用户姓名" width="100"></el-table-column>
|
||||||
|
<el-table-column prop="mobile" label="手机号" width="120"></el-table-column>
|
||||||
|
<el-table-column prop="goodsName" label="商品名称"></el-table-column>
|
||||||
|
<el-table-column label="商品封面" width="120">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div v-if="row.coverImg" class="flex gap-2">
|
||||||
|
<el-image v-for="(img, index) in row.coverImg.split(',')" :key="index" :src="img" :preview-src-list="row.coverImg.split(',')" :z-index="9999" :preview-teleported="true" :hide-on-click-modal="true" fit="cover" class="rounded" width="40" height="40" />
|
||||||
|
</div>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="goodsPrice" label="商品价格" width="100">
|
||||||
|
<template #default="{ row }">{{ row.goodsPrice }}元</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="paymentMethodStr" label="支付方式" width="100"></el-table-column>
|
||||||
|
<el-table-column prop="returnQuantity" label="归还数量" width="100"></el-table-column>
|
||||||
|
<el-table-column prop="returnAmount" label="退款金额" width="100">
|
||||||
|
<template #default="{ row }">{{ row.returnAmount }}元</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="createTime" label="提交时间" width="180">
|
||||||
|
<template #default="{ row }">{{ row.createTime ? new Date(row.createTime).toLocaleString() : '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="statusStr" label="状态" width="100">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="{ 1: 'warning', 2: 'success', 3: 'danger' }[row.status]">{{ row.statusStr }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="approvalTime" label="审批时间" width="180">
|
||||||
|
<template #default="{ row }">{{ row.approvalTime ? new Date(row.approvalTime).toLocaleString() : '-' }}</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="180" fixed="right">
|
||||||
|
<template #default="scope">
|
||||||
|
<el-button size="small" type="text">查看</el-button>
|
||||||
|
<el-button size="small" type="text" v-if="activeMenu === 'received-pending'">处理</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-pagination
|
||||||
|
v-model:current-page="pagination.currentPage"
|
||||||
|
v-model:page-size="pagination.pageSize"
|
||||||
|
:page-sizes="[5, 10, 20, 50]"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
:total="pagination.total"
|
||||||
|
@size-change="handlePaginationChange"
|
||||||
|
@current-change="handlePaginationChange"
|
||||||
|
class="pagination mt-4"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 申请类型列表 -->
|
||||||
|
<div class="application-list" v-if="activeMenu === 'apply'">
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col v-for="(item, index) in filteredApplications" :key="index" :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
|
<el-col v-for="(item, index) in filteredApplications" :key="index" :xs="24" :sm="12" :md="8" :lg="6" :xl="4">
|
||||||
<div class="application-card" @click="handleCardClick(item)">
|
<div class="application-card" @click="handleCardClick(item)">
|
||||||
<el-icon class="card-icon" :style="{ color: item.color }">
|
<el-icon class="card-icon" :style="{ color: item.color }"><component :is="item.icon" /></el-icon>
|
||||||
<component :is="item.icon" />
|
|
||||||
</el-icon>
|
|
||||||
<div class="card-name">{{ item.name }}</div>
|
<div class="card-name">{{ item.name }}</div>
|
||||||
</div>
|
</div>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
@ -303,5 +456,26 @@ const handleCardClick = (item: any) => {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 审批列表样式 */
|
||||||
|
.approval-list {
|
||||||
|
|
||||||
|
.el-table {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-table__header th {
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--text {
|
||||||
|
color: #409eff;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #66b1ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
Loading…
Reference in New Issue