mirror of
https://github.com/woodchen-ink/aimodels-prices.git
synced 2025-07-18 05:32:00 +08:00
添加价格列表搜索功能
- 后端 prices.go 新增搜索查询参数,支持按模型名称模糊搜索 - 更新缓存键和总数缓存键,包含搜索查询参数 - 前端 Prices.vue 添加搜索输入框和搜索处理逻辑 - 实现搜索防抖,优化用户交互体验 - 重置搜索时自动返回第一页
This commit is contained in:
parent
680d684016
commit
2b2cc35a1c
@ -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 {
|
||||
|
@ -22,6 +22,21 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 添加搜索框 -->
|
||||
<div class="search-section">
|
||||
<el-input
|
||||
v-model="searchQuery"
|
||||
placeholder="搜索模型名称"
|
||||
clearable
|
||||
prefix-icon="Search"
|
||||
@input="handleSearch"
|
||||
>
|
||||
<template #prefix>
|
||||
<el-icon><Search /></el-icon>
|
||||
</template>
|
||||
</el-input>
|
||||
</div>
|
||||
|
||||
<div class="filter-section">
|
||||
<div class="filter-label">厂商筛选:</div>
|
||||
<div class="provider-filters">
|
||||
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user