diff --git a/backend/database/db.go b/backend/database/db.go index 54b19bc..ad9e98c 100644 --- a/backend/database/db.go +++ b/backend/database/db.go @@ -51,7 +51,7 @@ func createTables() error { return err } - // 创建供应商表 + // 创建模型厂商表 if _, err := DB.Exec(models.CreateProviderTableSQL()); err != nil { log.Printf("Failed to create provider table: %v", err) return err diff --git a/backend/handlers/prices.go b/backend/handlers/prices.go index cc47db7..21a7f27 100644 --- a/backend/handlers/prices.go +++ b/backend/handlers/prices.go @@ -49,7 +49,7 @@ func CreatePrice(c *gin.Context) { return } - // 验证供应商ID是否存在 + // 验证模型厂商ID是否存在 db := c.MustGet("db").(*sql.DB) var providerExists bool err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM provider WHERE id = ?)", price.ChannelType).Scan(&providerExists) @@ -157,7 +157,7 @@ func UpdatePrice(c *gin.Context) { return } - // 验证供应商ID是否存在 + // 验证模型厂商ID是否存在 db := c.MustGet("db").(*sql.DB) var providerExists bool err := db.QueryRow("SELECT EXISTS(SELECT 1 FROM provider WHERE id = ?)", price.ChannelType).Scan(&providerExists) diff --git a/backend/handlers/providers.go b/backend/handlers/providers.go index 8b462c6..baa1b9f 100644 --- a/backend/handlers/providers.go +++ b/backend/handlers/providers.go @@ -11,7 +11,7 @@ import ( "aimodels-prices/models" ) -// GetProviders 获取所有供应商 +// GetProviders 获取所有模型厂商 func GetProviders(c *gin.Context) { db := c.MustGet("db").(*sql.DB) rows, err := db.Query(` @@ -38,7 +38,7 @@ func GetProviders(c *gin.Context) { c.JSON(http.StatusOK, providers) } -// CreateProvider 创建供应商 +// CreateProvider 创建模型厂商 func CreateProvider(c *gin.Context) { var provider models.Provider if err := c.ShouldBindJSON(&provider); err != nil { @@ -80,7 +80,7 @@ func CreateProvider(c *gin.Context) { c.JSON(http.StatusCreated, provider) } -// UpdateProvider 更新供应商 +// UpdateProvider 更新模型厂商 func UpdateProvider(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 32) if err != nil { @@ -106,7 +106,7 @@ func UpdateProvider(c *gin.Context) { return } - // 获取更新后的供应商信息 + // 获取更新后的模型厂商信息 err = db.QueryRow(` SELECT id, name, icon, created_at, updated_at, created_by FROM provider WHERE id = ?`, id).Scan( @@ -120,7 +120,7 @@ func UpdateProvider(c *gin.Context) { c.JSON(http.StatusOK, provider) } -// UpdateProviderStatus 更新供应商状态 +// UpdateProviderStatus 更新模型厂商状态 func UpdateProviderStatus(c *gin.Context) { id := c.Param("id") var input struct { @@ -174,7 +174,7 @@ func UpdateProviderStatus(c *gin.Context) { }) } -// DeleteProvider 删除供应商 +// DeleteProvider 删除模型厂商 func DeleteProvider(c *gin.Context) { id := c.Param("id") db := c.MustGet("db").(*sql.DB) diff --git a/backend/main.go b/backend/main.go index c75bc93..b30509c 100644 --- a/backend/main.go +++ b/backend/main.go @@ -70,7 +70,7 @@ func main() { prices.PUT("/:id/status", middleware.AuthRequired(), middleware.AdminRequired(), handlers.UpdatePriceStatus) } - // 供应商相关路由 + // 模型厂商相关路由 providers := api.Group("/providers") { providers.GET("", handlers.GetProviders) diff --git a/backend/models/provider.go b/backend/models/provider.go index 93b29b7..cd3172a 100644 --- a/backend/models/provider.go +++ b/backend/models/provider.go @@ -11,7 +11,7 @@ type Provider struct { CreatedBy string `json:"created_by"` } -// CreateProviderTableSQL 返回创建供应商表的 SQL +// CreateProviderTableSQL 返回创建模型厂商表的 SQL func CreateProviderTableSQL() string { return ` CREATE TABLE IF NOT EXISTS provider ( diff --git a/backend/router/router.go b/backend/router/router.go index 23f8654..791be3a 100644 --- a/backend/router/router.go +++ b/backend/router/router.go @@ -22,7 +22,7 @@ func SetupRouter() *gin.Engine { auth.POST("/logout", handlers.Logout) } - // 供应商相关路由 + // 模型厂商相关路由 providers := r.Group("/providers") { providers.GET("", handlers.GetProviders) diff --git a/frontend/index.html b/frontend/index.html index b4b954d..544cb50 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,7 +5,7 @@ - + AI模型价格 diff --git a/frontend/src/App.vue b/frontend/src/App.vue index ff0799f..a5acb62 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -8,7 +8,7 @@
diff --git a/frontend/src/views/Home.vue b/frontend/src/views/Home.vue index c24eeac..ef8a889 100644 --- a/frontend/src/views/Home.vue +++ b/frontend/src/views/Home.vue @@ -8,11 +8,11 @@

项目简介

-

这是一个专门用于管理AI模型价格的系统,支持多供应商、多币种的价格管理,并提供标准的API接口供其他系统调用。

+

这是一个专门用于管理AI模型价格的系统,支持多模型厂商、多币种的价格管理,并提供标准的API接口供其他系统调用。

主要功能

- +
GET @@ -93,7 +93,7 @@
-

获取所有供应商信息

+

获取所有模型厂商信息

响应示例:

 [
@@ -219,7 +219,7 @@ onMounted(() => {
 // 添加页面元信息
 const meta = {
   title: 'AI模型价格 - 首页',
-  description: '专业的AI模型价格管理系统,支持多供应商、多币种的价格管理,提供标准的API接口。',
+  description: '专业的AI模型价格管理系统,支持多模型厂商、多币种的价格管理,提供标准的API接口。',
   keywords: 'AI模型,价格管理,API接口,OpenAI,Azure,Anthropic'
 }
 
diff --git a/frontend/src/views/Prices.vue b/frontend/src/views/Prices.vue
index 6d18d1f..9fe6a8c 100644
--- a/frontend/src/views/Prices.vue
+++ b/frontend/src/views/Prices.vue
@@ -151,6 +151,31 @@
         
添加行 删除选中行 + + + +
+

请粘贴表格数据(支持从Excel复制),每行格式为:

+

模型名称 计费类型 厂商 货币 输入价格 输出价格

+ +
+ 导入 +
+
+
{ } } +// 添加导入相关的状态 +const importText = ref('') + +// 处理导入 +const handleImport = () => { + if (!importText.value.trim()) { + ElMessage.warning('请先粘贴数据') + return + } + + const lines = importText.value.trim().split('\n') + const newRows = lines.map(line => { + const [model, billingType, providerName, currency, inputPrice, outputPrice] = line.trim().split(/\s+/) + + // 查找模型厂商ID + const provider = providers.value.find(p => p.name === providerName) + if (!provider) { + ElMessage.warning(`未找到模型厂商:${providerName}`) + return null + } + + // 处理计费类型 + let billing_type = 'tokens' + if (billingType.includes('Token')) { + billing_type = 'tokens' + } else if (billingType.includes('次')) { + billing_type = 'times' + } + + // 处理货币 + let currencyCode = 'USD' + if (currency.includes('美元')) { + currencyCode = 'USD' + } else if (currency.includes('人民币') || currency.includes('CNY')) { + currencyCode = 'CNY' + } + + return { + model, + billing_type, + channel_type: provider.id.toString(), + currency: currencyCode, + input_price: parseFloat(inputPrice), + output_price: parseFloat(outputPrice), + price_source: '官方', + created_by: props.user?.username || '' + } + }).filter(row => row !== null) + + if (newRows.length > 0) { + batchForms.value = [...batchForms.value, ...newRows] + importText.value = '' + ElMessage.success(`成功导入 ${newRows.length} 条数据`) + } +} + onMounted(async () => { await loadPrices() try { @@ -580,7 +661,7 @@ onMounted(async () => { providers.value = data } catch (error) { console.error('Failed to load providers:', error) - ElMessage.error('加载供应商数据失败') + ElMessage.error('加载模型厂商数据失败') } }) @@ -683,4 +764,31 @@ onMounted(async () => { :deep(.el-select) { width: 100%; } + +.import-popover { + display: flex; + flex-direction: column; + gap: 12px; +} + +.import-tip { + margin: 0; + color: #606266; + font-size: 14px; +} + +.import-format { + margin: 0; + color: #409EFF; + font-size: 13px; + background-color: #ecf5ff; + padding: 8px; + border-radius: 4px; +} + +.import-actions { + display: flex; + justify-content: flex-end; + margin-top: 8px; +} \ No newline at end of file diff --git a/frontend/src/views/Providers.vue b/frontend/src/views/Providers.vue index de9a561..7957dd8 100644 --- a/frontend/src/views/Providers.vue +++ b/frontend/src/views/Providers.vue @@ -3,8 +3,8 @@ @@ -82,7 +82,7 @@ const router = useRouter() const isAdmin = computed(() => props.user?.role === 'admin') -// 按ID排序的供应商列表 +// 按ID排序的模型厂商 const sortedProviders = computed(() => { return [...providers.value].sort((a, b) => a.id - b.id) }) @@ -103,14 +103,14 @@ onMounted(() => { const dialogTitle = computed(() => { if (editingProvider.value) { - return '编辑供应商' + return '编辑模型厂商' } - return '添加供应商' + return '添加模型厂商' }) const handleEdit = (provider) => { if (!isAdmin.value) { - ElMessage.warning('只有管理员可以编辑供应商信息') + ElMessage.warning('只有管理员可以编辑模型厂商信息') return } editingProvider.value = provider @@ -120,12 +120,12 @@ const handleEdit = (provider) => { const handleDelete = (provider) => { if (!isAdmin.value) { - ElMessage.warning('只有管理员可以删除供应商') + ElMessage.warning('只有管理员可以删除模型厂商') return } ElMessageBox.confirm( - '确定要删除这个供应商吗?', + '确定要删除这个模型厂商吗?', '警告', { confirmButtonText: '确定', @@ -162,10 +162,10 @@ const submitForm = async () => { try { if (editingProvider.value) { if (!isAdmin.value) { - ElMessage.error('只有管理员可以编辑供应商信息') + ElMessage.error('只有管理员可以编辑模型厂商信息') return } - // 管理员编辑供应商 + // 管理员编辑模型厂商 const { data } = await axios.put(`/api/providers/${editingProvider.value.id}`, form.value) if (data.error) { ElMessage.error(data.error) @@ -177,7 +177,7 @@ const submitForm = async () => { } ElMessage.success('更新成功') } else { - // 创建新供应商 + // 创建新模型厂商 const { data } = await axios.post('/api/providers', form.value) if (data.error) { ElMessage.error(data.error)