feat(purchase): 采购页搜索区对齐出库记录版式

原顶部工具栏是裸 div + 状态单选,现改为 el-form :inline 版式,与出库记录 /
报废记录一致:

  状态      全部 / 待审批 / 已通过 / 已驳回 / 已完成 / 已完结
  搜索      [搜索类型下拉] + 关键词输入,500ms 防抖
  采购日期  日期范围选择
  按钮      查询 / 重置 / 新建采购申请

交互细节:
· 搜索类型切换、清空输入时立即查询(取消防抖等待);
· 「重置」恢复默认的「待审批」状态(该页默认视图),而非清成"全部"——
  与页面初始状态保持一致;
· 重置同时清空关键词、搜索类型、日期范围。

api/purchase.ts 的 getPurchaseList 补充新参数的类型定义。
This commit is contained in:
yueli
2026-09-10 17:41:29 +08:00
parent e93107458a
commit 6f2f077751
2 changed files with 120 additions and 18 deletions

View File

@ -46,10 +46,18 @@ export interface Approver {
}
// 获取采购申请列表
//
// 搜索参数语义与出库/报废记录保持一致:
// search_type: all / no(单号) / name(物料名称) / spec_model / requester(申请人)
// start_date / end_date: 按采购日期过滤
export function getPurchaseList(params: {
page?: number
limit?: number
status?: number
status?: number | ''
keyword?: string
search_type?: 'all' | 'no' | 'name' | 'spec_model' | 'requester'
start_date?: string
end_date?: string
}) {
return request({
url: '/purchase',

View File

@ -1,22 +1,60 @@
<template>
<div class="app-container">
<!-- 顶部工具栏 -->
<div class="filter-container">
<span style="font-weight: bold; font-size: 15px; margin-right: 8px;">审批状态:</span>
<el-radio-group v-model="filterStatus" size="default" @change="handleStatusChange">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button :label="0">待审批</el-radio-button>
<el-radio-button :label="1">已通过</el-radio-button>
<el-radio-button :label="2">已驳回</el-radio-button>
<el-radio-button :label="3">已完成</el-radio-button>
<el-radio-button :label="4">已完结</el-radio-button>
</el-radio-group>
<el-button type="primary" :icon="Refresh" @click="fetchData">刷新</el-button>
<el-button type="success" :icon="Plus" @click="openCreateDialog">
新建采购申请
</el-button>
</div>
<!-- 顶部工具栏搜索 + 状态筛选搜索区对齐出库记录版式 -->
<el-form :inline="true" class="filter-form" @submit.prevent>
<el-form-item label="状态">
<el-radio-group v-model="filterStatus" @change="handleStatusChange">
<el-radio-button label="">全部</el-radio-button>
<el-radio-button :label="0">待审批</el-radio-button>
<el-radio-button :label="1">已通过</el-radio-button>
<el-radio-button :label="2">已驳回</el-radio-button>
<el-radio-button :label="3">已完成</el-radio-button>
<el-radio-button :label="4">已完结</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="搜索">
<el-input
v-model="keyword"
placeholder="输入关键词"
style="width: 240px"
clearable
@input="debouncedSearch"
@clear="handleClearSearch"
>
<template #prepend>
<el-select v-model="searchType" placeholder="搜索类型" style="width: 110px" @change="handleSearchImmediate">
<el-option label="全部" value="all" />
<el-option label="单号" value="no" />
<el-option label="物料名称" value="name" />
<el-option label="规格型号" value="spec_model" />
<el-option label="申请人" value="requester" />
</el-select>
</template>
</el-input>
</el-form-item>
<el-form-item label="采购日期">
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD"
style="width: 260px"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" :icon="Refresh" @click="fetchData">查询</el-button>
<el-button @click="resetFilter">重置</el-button>
<el-button type="success" :icon="Plus" @click="openCreateDialog">
新建采购申请
</el-button>
</el-form-item>
</el-form>
<!-- 按批次分组的列表 -->
<el-table v-loading="loading" :data="list" border stripe fit style="width: 100%; margin-top: 16px;" row-key="batchKey">
@ -441,6 +479,43 @@ const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const filterStatus = ref<number | ''>(0) // 默认筛选待审批
// --- 搜索(语义与出库/报废记录一致)---
const keyword = ref('')
const searchType = ref<'all' | 'no' | 'name' | 'spec_model' | 'requester'>('all')
const dateRange = ref<string[]>([])
let debounceTimer: ReturnType<typeof setTimeout> | null = null
const debouncedSearch = () => {
if (debounceTimer) clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => {
page.value = 1
fetchData()
}, 500)
}
const handleClearSearch = () => {
if (debounceTimer) clearTimeout(debounceTimer)
page.value = 1
fetchData()
}
// 搜索类型切换:立即查询(取消防抖等待)
const handleSearchImmediate = () => {
if (debounceTimer) clearTimeout(debounceTimer)
page.value = 1
fetchData()
}
const resetFilter = () => {
if (debounceTimer) clearTimeout(debounceTimer)
filterStatus.value = 0 // 回到默认的「待审批」
keyword.value = ''
searchType.value = 'all'
dateRange.value = []
page.value = 1
fetchData()
}
const submitLoading = ref(false)
const rejectLoading = ref(false)
@ -772,8 +847,17 @@ const formatUserName = (name: string): string => {
const fetchData = async () => {
loading.value = true
try {
const params: any = { page: page.value, limit: pageSize.value }
const params: any = {
page: page.value,
limit: pageSize.value,
keyword: keyword.value.trim(),
search_type: searchType.value,
}
if (filterStatus.value !== '') params.status = filterStatus.value
if (dateRange.value && dateRange.value.length === 2) {
params.start_date = dateRange.value[0]
params.end_date = dateRange.value[1]
}
const res: any = await getPurchaseList(params)
const items = res.data?.items || []
@ -1323,6 +1407,16 @@ onMounted(() => {
</script>
<style scoped>
/* ★ 搜索区版式:与出库记录 / 报废记录保持一致 */
.filter-form {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.filter-form :deep(.el-form-item) {
margin-bottom: 0;
margin-right: 12px;
}
.app-container { padding: 20px; }
.filter-container { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }