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;