From 2b2cc35a1cfe73ae30a64e42d6437dd44116f680 Mon Sep 17 00:00:00 2001 From: wood chen Date: Wed, 12 Mar 2025 16:46:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BB=B7=E6=A0=BC=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E6=90=9C=E7=B4=A2=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端 prices.go 新增搜索查询参数,支持按模型名称模糊搜索 - 更新缓存键和总数缓存键,包含搜索查询参数 - 前端 Prices.vue 添加搜索输入框和搜索处理逻辑 - 实现搜索防抖,优化用户交互体验 - 重置搜索时自动返回第一页 --- backend/handlers/prices.go | 11 +++++--- frontend/src/views/Prices.vue | 48 +++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/backend/handlers/prices.go b/backend/handlers/prices.go index 6b49aae..c4b406e 100644 --- a/backend/handlers/prices.go +++ b/backend/handlers/prices.go @@ -19,6 +19,7 @@ func GetPrices(c *gin.Context) { pageSize, _ := strconv.Atoi(c.DefaultQuery("pageSize", "20")) channelType := c.Query("channel_type") // 厂商筛选参数 modelType := c.Query("model_type") // 模型类型筛选参数 + searchQuery := c.Query("search") // 搜索查询参数 if page < 1 { page = 1 @@ -30,8 +31,8 @@ func GetPrices(c *gin.Context) { offset := (page - 1) * pageSize // 构建缓存键 - cacheKey := fmt.Sprintf("prices_page_%d_size_%d_channel_%s_type_%s", - page, pageSize, channelType, modelType) + cacheKey := fmt.Sprintf("prices_page_%d_size_%d_channel_%s_type_%s_search_%s", + page, pageSize, channelType, modelType, searchQuery) // 尝试从缓存获取 if cachedData, found := database.GlobalCache.Get(cacheKey); found { @@ -51,10 +52,14 @@ func GetPrices(c *gin.Context) { if modelType != "" { query = query.Where("model_type = ?", modelType) } + // 添加搜索条件 + if searchQuery != "" { + query = query.Where("model LIKE ?", "%"+searchQuery+"%") + } // 获取总数 - 使用缓存优化 var total int64 - totalCacheKey := fmt.Sprintf("prices_count_channel_%s_type_%s", channelType, modelType) + totalCacheKey := fmt.Sprintf("prices_count_channel_%s_type_%s_search_%s", channelType, modelType, searchQuery) if cachedTotal, found := database.GlobalCache.Get(totalCacheKey); found { if t, ok := cachedTotal.(int64); ok { diff --git a/frontend/src/views/Prices.vue b/frontend/src/views/Prices.vue index 13e4363..404361b 100644 --- a/frontend/src/views/Prices.vue +++ b/frontend/src/views/Prices.vue @@ -22,6 +22,21 @@ + +
+ + + +
+
厂商筛选:
@@ -502,7 +517,7 @@ import { ref, computed, onMounted, watch } from 'vue' import axios from 'axios' import { ElMessage, ElMessageBox } from 'element-plus' import { useRouter } from 'vue-router' -import { Edit, Delete, Check, Close, Document } from '@element-plus/icons-vue' +import { Edit, Delete, Check, Close, Document, Search } from '@element-plus/icons-vue' const props = defineProps({ user: Object @@ -524,6 +539,7 @@ const form = ref({ const router = useRouter() const selectedProvider = ref('') const selectedModelType = ref('') +const searchQuery = ref('') const isAdmin = computed(() => props.user?.role === 'admin') @@ -588,6 +604,10 @@ const loadPrices = async () => { if (selectedModelType.value) { params.model_type = selectedModelType.value } + // 添加搜索参数 + if (searchQuery.value) { + params.search = searchQuery.value + } try { const [pricesRes, providersRes] = await Promise.all([ @@ -600,7 +620,7 @@ const loadPrices = async () => { providers.value = providersRes.data // 缓存数据 - const cacheKey = `${currentPage.value}-${pageSize.value}-${selectedProvider.value}-${selectedModelType.value}` + const cacheKey = `${currentPage.value}-${pageSize.value}-${selectedProvider.value}-${selectedModelType.value}-${searchQuery.value}` cachedPrices.value.set(cacheKey, { prices: pricesRes.data.data, total: pricesRes.data.total @@ -1058,6 +1078,19 @@ watch(selectedModelType, () => { loadPrices() }) +// 监听搜索查询变化 +watch(searchQuery, () => { + // 使用防抖处理,避免频繁请求 + if (searchDebounceTimer) clearTimeout(searchDebounceTimer) + searchDebounceTimer = setTimeout(() => { + currentPage.value = 1 // 重置到第一页 + loadPrices() + }, 300) +}) + +// 添加防抖定时器 +let searchDebounceTimer = null + // 复制行 const duplicateRow = (index) => { const newRow = { ...batchForms.value[index] } @@ -1107,6 +1140,12 @@ const approveAllPending = async () => { } } +// 处理搜索 +const handleSearch = () => { + currentPage.value = 1 // 重置到第一页 + loadPrices() +} + onMounted(() => { loadModelTypes() loadPrices() @@ -1137,6 +1176,11 @@ onMounted(() => { color: #606266; } +.search-section { + margin: 16px 0; + max-width: 400px; +} + .provider-filters { display: flex; flex-wrap: wrap;