feat: 新增首页全局搜索功能,支持跨模块多词搜索

This commit is contained in:
DXC
2026-04-27 15:57:26 +08:00
parent ec71cb24f4
commit d6ae9499db
5 changed files with 205 additions and 2 deletions

View File

@ -18,6 +18,32 @@
<div class="card-body">
<h2>IRIS 库存管理系统</h2>
<div style="display: flex; justify-content: center; margin: 20px 0 30px;">
<el-autocomplete
v-model="globalSearchText"
:fetch-suggestions="queryGlobalSearch"
placeholder="全局搜索:输入物料名称、规格、条码或 BOM 编号..."
style="width: 60%; max-width: 600px;"
size="large"
clearable
@select="handleSearchSelect"
>
<template #prefix>
<el-icon><Search /></el-icon>
</template>
<template #default="{ item }">
<div style="display: flex; justify-content: space-between; align-items: center; line-height: 1.5; padding: 4px 0;">
<div>
<div style="font-size: 14px; font-weight: bold; color: #303133;">{{ item.title }}</div>
<div style="font-size: 12px; color: #909399;">{{ item.subtitle }}</div>
</div>
<el-tag size="small" :type="getBadgeType(item.type)">{{ item.badge }}</el-tag>
</div>
</template>
</el-autocomplete>
</div>
<p class="subtitle">请选择您要进行的业务操作</p>
<div class="action-buttons">
@ -215,8 +241,9 @@ import { useRouter } from 'vue-router'
// 1. 引入 User Store
import { useUserStore } from '@/stores/user'
// 引入需要的图标
import { Box, TrendCharts, ShoppingCart, Operation, Setting, Location, Plus, Edit, Delete, Close } from '@element-plus/icons-vue'
import { Box, TrendCharts, ShoppingCart, Operation, Setting, Location, Plus, Edit, Delete, Close, Search } from '@element-plus/icons-vue'
import { getPrinterConfig, updatePrinterConfig } from '@/api/common/print'
import request from '@/utils/request'
import { ElMessage, ElMessageBox } from 'element-plus'
import { getWarehouseTree, createWarehouse, updateWarehouse, deleteWarehouse, batchDeleteWarehouse, batchGenerateWarehouse } from '@/api/common/warehouse'
@ -234,6 +261,61 @@ const printerForm = reactive({
})
const loading = ref(false)
// 全局搜索相关
const globalSearchText = ref('')
const getBadgeType = (type: string) => {
const map: Record<string, string> = {
'material': 'success',
'stock_buy': 'primary',
'bom': 'warning'
}
return map[type] || 'info'
}
const queryGlobalSearch = async (queryString: string, cb: (data: any[]) => void) => {
if (!queryString || queryString.trim() === '') {
cb([])
return
}
try {
const res: any = await request({
url: '/v1/common/global-search',
method: 'get',
params: { keyword: queryString.trim() }
})
if (res.code === 200 && res.data) {
cb(res.data)
} else {
cb([])
}
} catch (error) {
console.error('全局搜索失败:', error)
cb([])
}
}
const handleSearchSelect = (item: any) => {
globalSearchText.value = ''
if (item.type === 'material') {
router.push({
path: '/material/index',
query: { edit_id: item.id, keyword: item.title }
})
} else if (item.type === 'stock_buy') {
router.push({
path: '/inventory/buy',
query: { keyword: item.title }
})
} else if (item.type === 'bom') {
router.push({
path: '/bom',
query: { keyword: item.title }
})
}
}
const openPrinterDialog = async () => {
try {
loading.value = true