Compare commits
No commits in common. "main" and "main" have entirely different histories.
2
.env
2
.env
@ -1,2 +1,2 @@
|
|||||||
# API配置
|
# API配置
|
||||||
VUE_APP_API_BASE_URL=/api/
|
VUE_APP_API_BASE_URL=http://localhost:8000
|
||||||
@ -3,7 +3,7 @@ AWS_SECRET_ACCESS_KEY=BQjaaHNm5skCN/3k3r/uNdEG9xb49are+hv5fajK
|
|||||||
AWS_DEFAULT_REGION=us-east-1
|
AWS_DEFAULT_REGION=us-east-1
|
||||||
|
|
||||||
# MySQL数据库配置
|
# MySQL数据库配置
|
||||||
MYSQL_HOST=163.123.183.106
|
MYSQL_HOST=47.76.209.7
|
||||||
MYSQL_USER=aws_price
|
MYSQL_USER=aws_price
|
||||||
MYSQL_PASSWORD=YCwjLmHM5dZtwHEw
|
MYSQL_PASSWORD=123456
|
||||||
MYSQL_DATABASE=aws_price
|
MYSQL_DATABASE=aws_price
|
||||||
@ -1,115 +0,0 @@
|
|||||||
# 云计算价格计算器 API 文档
|
|
||||||
|
|
||||||
**描述:** 支持多云平台价格计算的服务。
|
|
||||||
|
|
||||||
**基本 URL:** `/api`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 端点
|
|
||||||
|
|
||||||
### 1. 获取区域列表
|
|
||||||
|
|
||||||
- **描述:** 获取指定平台的可用区域列表。
|
|
||||||
- **路径:** `GET /regions`
|
|
||||||
- **方法:** `GET`
|
|
||||||
- **查询参数:**
|
|
||||||
- `platform` (string, optional, default: "aws"): 云平台。支持的值: "aws", "azure", "aliyun"。
|
|
||||||
- **成功响应 (200):**
|
|
||||||
```json
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"code": "us-east-1",
|
|
||||||
"name": "US East (N. Virginia)"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
- **错误响应 (400):** 如果平台不受支持。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 2. 获取实例类型
|
|
||||||
|
|
||||||
- **描述:** 获取指定平台的可用实例类型。
|
|
||||||
- **路径:** `GET /instance-types`
|
|
||||||
- **方法:** `GET`
|
|
||||||
- **查询参数:**
|
|
||||||
- `platform` (string, optional, default: "aws"): 云平台。
|
|
||||||
- **成功响应 (200):** 包含实例类型及其信息的字典。
|
|
||||||
- **错误响应 (400):** 如果平台不受支持。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 3. 搜索实例
|
|
||||||
|
|
||||||
- **描述:** 搜索符合指定条件的实例类型。
|
|
||||||
- **路径:** `POST /search-instances`
|
|
||||||
- **方法:** `POST`
|
|
||||||
- **请求体:** `InstanceSearchRequest`
|
|
||||||
- **成功响应 (200):** 匹配的实例列表,按月度总价排序。
|
|
||||||
- **错误响应 (400):** 如果缺少必需的参数。
|
|
||||||
- **错误响应 (500):** 内部服务器错误。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 4. 搜索实例 V2
|
|
||||||
|
|
||||||
- **描述:** 使用 MySQL 数据库搜索符合条件的 AWS 实例。
|
|
||||||
- **路径:** `POST /search-instances-v2`
|
|
||||||
- **方法:** `POST`
|
|
||||||
- **请求体:** `InstanceSearchRequestV2`
|
|
||||||
- **成功响应 (200):** 匹配的实例列表。
|
|
||||||
- **错误响应 (500):** 内部服务器错误。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 5. 比较价格
|
|
||||||
|
|
||||||
- **描述:** 比较多种实例配置的价格。
|
|
||||||
- **路径:** `POST /compare-prices`
|
|
||||||
- **方法:** `POST`
|
|
||||||
- **请求体:** `PriceComparison`
|
|
||||||
- **成功响应 (200):** 包含配置及其计算价格的列表。
|
|
||||||
- **错误响应 (500):** 内部服务器错误。
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 数据模型
|
|
||||||
|
|
||||||
### `InstanceSearchRequest`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 描述 | 默认值 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `cpu_cores` | integer | CPU 核心数 | (optional) |
|
|
||||||
| `memory_gb` | float | 内存 (GB) | (optional) |
|
|
||||||
| `disk_gb` | integer | 磁盘大小 (GB) | (optional) |
|
|
||||||
| `region` | string | 区域 | (optional) |
|
|
||||||
| `operating_system` | string | 操作系统 | "Linux" |
|
|
||||||
| `platform` | string | 云平台 | "aws" |
|
|
||||||
|
|
||||||
### `InstanceSearchRequestV2`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 描述 | 默认值 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `cpu_cores` | integer | CPU 核心数 | (optional) |
|
|
||||||
| `memory_gb` | float | 内存 (GB) | (optional) |
|
|
||||||
| `disk_gb` | integer | 磁盘大小 (GB) | (optional) |
|
|
||||||
| `region` | string | 区域 | (optional) |
|
|
||||||
| `operating_system` | string | 操作系统 | "Linux" |
|
|
||||||
|
|
||||||
### `PriceComparison`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 描述 |
|
|
||||||
|---|---|---|
|
|
||||||
| `configurations` | List[`PriceRequest`] | 价格请求配置列表 |
|
|
||||||
|
|
||||||
### `PriceRequest`
|
|
||||||
|
|
||||||
| 字段 | 类型 | 描述 | 默认值 |
|
|
||||||
|---|---|---|---|
|
|
||||||
| `instance_type` | string | 实例类型 (required) | |
|
|
||||||
| `region` | string | 区域 (required) | |
|
|
||||||
| `operating_system` | string | 操作系统 (required) | |
|
|
||||||
| `purchase_option` | string | 购买选项 (required) | |
|
|
||||||
| `duration` | integer | 持续时间 | 1 |
|
|
||||||
| `disk_gb` | integer | 磁盘大小 (GB) | 0 |
|
|
||||||
@ -1,217 +0,0 @@
|
|||||||
openapi: 3.0.0
|
|
||||||
info:
|
|
||||||
title: 云计算价格计算器 API
|
|
||||||
description: 支持多云平台价格计算的服务。
|
|
||||||
version: "1.0.0"
|
|
||||||
servers:
|
|
||||||
- url: /api
|
|
||||||
description: Main API server
|
|
||||||
|
|
||||||
paths:
|
|
||||||
/regions:
|
|
||||||
get:
|
|
||||||
summary: 获取区域列表
|
|
||||||
description: 获取指定平台的可用区域列表。
|
|
||||||
parameters:
|
|
||||||
- name: platform
|
|
||||||
in: query
|
|
||||||
description: '云平台。支持的值: "aws", "azure", "aliyun"。'
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
default: "aws"
|
|
||||||
enum: ["aws", "azure", "aliyun"]
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 成功响应
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
code:
|
|
||||||
type: string
|
|
||||||
example: "us-east-1"
|
|
||||||
name:
|
|
||||||
type: string
|
|
||||||
example: "US East (N. Virginia)"
|
|
||||||
'400':
|
|
||||||
description: 如果平台不受支持。
|
|
||||||
|
|
||||||
/instance-types:
|
|
||||||
get:
|
|
||||||
summary: 获取实例类型
|
|
||||||
description: 获取指定平台的可用实例类型。
|
|
||||||
parameters:
|
|
||||||
- name: platform
|
|
||||||
in: query
|
|
||||||
description: 云平台。
|
|
||||||
required: false
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
default: "aws"
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 成功响应,包含实例类型及其信息的字典。
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: object
|
|
||||||
'400':
|
|
||||||
description: 如果平台不受支持。
|
|
||||||
|
|
||||||
/search-instances:
|
|
||||||
post:
|
|
||||||
summary: 搜索实例
|
|
||||||
description: 搜索符合指定条件的实例类型。
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/InstanceSearchRequest'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 匹配的实例列表,按月度总价排序。
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
'400':
|
|
||||||
description: 如果缺少必需的参数。
|
|
||||||
'500':
|
|
||||||
description: 内部服务器错误。
|
|
||||||
|
|
||||||
/search-instances-v2:
|
|
||||||
post:
|
|
||||||
summary: 搜索实例 V2
|
|
||||||
description: 使用 MySQL 数据库搜索符合条件的 AWS 实例。
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/InstanceSearchRequestV2'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 匹配的实例列表。
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
'500':
|
|
||||||
description: 内部服务器错误。
|
|
||||||
|
|
||||||
/compare-prices:
|
|
||||||
post:
|
|
||||||
summary: 比较价格
|
|
||||||
description: 比较多种实例配置的价格。
|
|
||||||
requestBody:
|
|
||||||
required: true
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
$ref: '#/components/schemas/PriceComparison'
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: 包含配置及其计算价格的列表。
|
|
||||||
content:
|
|
||||||
application/json:
|
|
||||||
schema:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
type: object
|
|
||||||
'500':
|
|
||||||
description: 内部服务器错误。
|
|
||||||
|
|
||||||
components:
|
|
||||||
schemas:
|
|
||||||
InstanceSearchRequest:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
cpu_cores:
|
|
||||||
type: integer
|
|
||||||
description: CPU 核心数
|
|
||||||
memory_gb:
|
|
||||||
type: number
|
|
||||||
format: float
|
|
||||||
description: 内存 (GB)
|
|
||||||
disk_gb:
|
|
||||||
type: integer
|
|
||||||
description: 磁盘大小 (GB)
|
|
||||||
region:
|
|
||||||
type: string
|
|
||||||
description: 区域
|
|
||||||
operating_system:
|
|
||||||
type: string
|
|
||||||
description: 操作系统
|
|
||||||
default: "Linux"
|
|
||||||
platform:
|
|
||||||
type: string
|
|
||||||
description: 云平台
|
|
||||||
default: "aws"
|
|
||||||
|
|
||||||
InstanceSearchRequestV2:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
cpu_cores:
|
|
||||||
type: integer
|
|
||||||
description: CPU 核心数
|
|
||||||
memory_gb:
|
|
||||||
type: number
|
|
||||||
format: float
|
|
||||||
description: 内存 (GB)
|
|
||||||
disk_gb:
|
|
||||||
type: integer
|
|
||||||
description: 磁盘大小 (GB)
|
|
||||||
region:
|
|
||||||
type: string
|
|
||||||
description: 区域
|
|
||||||
operating_system:
|
|
||||||
type: string
|
|
||||||
description: 操作系统
|
|
||||||
default: "Linux"
|
|
||||||
|
|
||||||
PriceComparison:
|
|
||||||
type: object
|
|
||||||
properties:
|
|
||||||
configurations:
|
|
||||||
type: array
|
|
||||||
items:
|
|
||||||
$ref: '#/components/schemas/PriceRequest'
|
|
||||||
description: 价格请求配置列表
|
|
||||||
|
|
||||||
PriceRequest:
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- instance_type
|
|
||||||
- region
|
|
||||||
- operating_system
|
|
||||||
- purchase_option
|
|
||||||
properties:
|
|
||||||
instance_type:
|
|
||||||
type: string
|
|
||||||
description: 实例类型
|
|
||||||
region:
|
|
||||||
type: string
|
|
||||||
description: 区域
|
|
||||||
operating_system:
|
|
||||||
type: string
|
|
||||||
description: 操作系统
|
|
||||||
purchase_option:
|
|
||||||
type: string
|
|
||||||
description: 购买选项
|
|
||||||
duration:
|
|
||||||
type: integer
|
|
||||||
description: 持续时间
|
|
||||||
default: 1
|
|
||||||
disk_gb:
|
|
||||||
type: integer
|
|
||||||
description: 磁盘大小 (GB)
|
|
||||||
default: 0
|
|
||||||
@ -30,220 +30,210 @@ AWS_PRICING_EBS = {
|
|||||||
|
|
||||||
# 区域中文名称映射
|
# 区域中文名称映射
|
||||||
AWS_REGION_NAMES = {
|
AWS_REGION_NAMES = {
|
||||||
"Asia Pacific (Malaysia)":"区域:亚太地区(马来西亚)",
|
"af-south-1": "非洲 (开普敦)",
|
||||||
"Asia Pacific (Taipei)":"区域:亚太地区(台北)",
|
"ap-northeast-1": "亚太地区 (东京)",
|
||||||
"Asia Pacific (Thailand)":"区域:亚太地区(泰国)",
|
"ap-northeast-2": "亚太地区 (首尔)",
|
||||||
"Mexico (Central)":"区域:墨西哥(中部)",
|
"ap-northeast-3": "亚太地区 (大阪)",
|
||||||
"Africa (Cape Town)":"区域:非洲(开普敦)",
|
"ap-east-1": "亚太地区 (香港)",
|
||||||
"Asia Pacific (Hong Kong)":"区域:亚太地区(香港)",
|
"ap-south-1": "亚太地区 (孟买)",
|
||||||
"Asia Pacific (Hyderabad)":"区域:亚太地区(海得拉巴)",
|
"ap-south-2": "亚太地区 (海得拉巴)",
|
||||||
"Asia Pacific (Jakarta)":"区域:亚太地区(雅加达)",
|
"ap-southeast-1": "亚太地区 (新加坡)",
|
||||||
"Asia Pacific (Melbourne)":"区域:亚太地区(墨尔本)",
|
"ap-southeast-2": "亚太地区 (悉尼)",
|
||||||
"Asia Pacific (Osaka)":"区域:亚太地区(大阪)",
|
"ap-southeast-3": "亚太地区 (雅加达)",
|
||||||
"Canada West (Calgary)":"区域:加拿大西部(卡尔加里)",
|
"ap-southeast-4": "亚太地区 (墨尔本)",
|
||||||
"EU (Milan)":"区域:欧洲地区(米兰)",
|
"ap-southeast-5": "亚太地区 (马来西亚)",
|
||||||
"EU (Spain)":"区域:欧洲(西班牙)",
|
"ap-southeast-7": "亚太地区 (泰国)",
|
||||||
"EU (Stockholm)":"区域:欧洲地区(斯德哥尔摩)",
|
"ca-central-1": "加拿大 (中部)",
|
||||||
"EU (Zurich)":"区域:欧洲(苏黎世)",
|
"ca-west-1": "加拿大西部 (卡尔加里)",
|
||||||
"Israel (Tel Aviv)":"区域:以色列(特拉维夫)",
|
"eu-central-1": "欧洲 (法兰克福)",
|
||||||
"Middle East (Bahrain)":"区域:中东(巴林)",
|
"eu-central-2": "欧洲 (苏黎世)",
|
||||||
"Middle East (UAE)":"区域:中东(阿联酋)",
|
"eu-north-1": "欧洲 (斯德哥尔摩)",
|
||||||
"US West (N. California)":"区域:美国西部(北加利福尼亚)",
|
"eu-south-1": "欧洲 (米兰)",
|
||||||
"Argentina (Buenos Aires)":"本地区域:阿根廷(布宜诺斯艾利斯)",
|
"eu-south-2": "欧洲 (西班牙)",
|
||||||
"Asia Pacific (KDDI) - Osaka":"运营商区域:亚太地区(KDDI)– 大阪",
|
"eu-west-1": "欧洲 (爱尔兰)",
|
||||||
"Asia Pacific (KDDI) - Tokyo":"运营商区域:亚太地区(KDDI)– 东京",
|
"eu-west-2": "欧洲 (伦敦)",
|
||||||
"Asia Pacific (SKT) - Daejeon":"运营商区域:亚太地区(SKT)– 大田",
|
"eu-west-3": "欧洲 (巴黎)",
|
||||||
"Asia Pacific (SKT) - Seoul":"运营商区域:亚太地区(SKT)– 首尔",
|
"il-central-1": "以色列 (特拉维夫)",
|
||||||
"Australia (Perth)":"本地区域:澳大利亚(珀斯)",
|
"me-central-1": "中东 (阿联酋)",
|
||||||
"Canada (BELL) - Toronto":"运营商区域:加拿大(BELL)– 多伦多",
|
"me-south-1": "中东 (巴林)",
|
||||||
"Chile (Santiago)":"本地区域:智利(圣地亚哥)",
|
"mx-central-1": "墨西哥 (中部)",
|
||||||
"Denmark (Copenhagen)":"本地区域:丹麦(哥本哈根)",
|
"sa-east-1": "南美洲 (圣保罗)",
|
||||||
"EU (British Telecom) - Manchester":"运营商区域:欧洲(英国电信)- 曼彻斯特",
|
"us-east-1": "美国东部 (弗吉尼亚北部)",
|
||||||
"EU (Vodafone) - Berlin":"运营商区域:欧洲(Vodafone)– 柏林",
|
"us-east-2": "美国东部 (俄亥俄)",
|
||||||
"EU (Vodafone) - Dortmund":"运营商区域:欧洲(Vodafone)– 多特蒙德",
|
"us-east-2-mci-1": "美国东部 (堪萨斯城)",
|
||||||
"EU (Vodafone) - London":"运营商区域:欧洲(Vodafone)– 伦敦",
|
"us-gov-east-1": "AWS GovCloud (美国东部)",
|
||||||
"EU (Vodafone) - Manchester":"运营商区域:欧洲(Vodafone)– 曼彻斯特",
|
"us-gov-west-1": "AWS GovCloud (美国西部)",
|
||||||
"EU (Vodafone) - Munich":"运营商区域:欧洲(Vodafone)– 慕尼黑",
|
"us-west-1": "美国西部 (加利福尼亚北部)",
|
||||||
"Finland (Helsinki)":"本地区域:芬兰(赫尔辛基)",
|
"us-west-2": "美国西部 (俄勒冈)",
|
||||||
"Germany (Hamburg)":"本地区域:德国(汉堡)",
|
"ap-northeast-1-tpe-1": "亚太地区 (台湾)",
|
||||||
"India (Delhi)":"本地区域:印度(德里)",
|
"ap-northeast-1-wl1-kix1": "亚太地区 (KDDI) - 大阪",
|
||||||
"India (Kolkata)":"本地区域:印度(加尔各答)",
|
"ap-northeast-1-wl1-nrt1": "亚太地区 (KDDI) - 东京",
|
||||||
"Mexico (Queretaro)":"本地区域:墨西哥(克雷塔罗)",
|
"ap-northeast-2-wl1-cjj1": "亚太地区 (SKT) - 大田",
|
||||||
"Morocco (Casablanca)":"运营商区域:摩洛哥(卡萨布兰卡)",
|
"ap-northeast-2-wl1-sel1": "亚太地区 (SKT) - 首尔",
|
||||||
"New Zealand (Auckland)":"本地区域:新西兰(奥克兰)",
|
"ca-central-1-wl1-yto1": "加拿大 (BELL) - 多伦多",
|
||||||
"Nigeria (Lagos)":"本地区域:尼日利亚(拉各斯)",
|
"eu-central-1-wl1-ber1": "欧洲 (沃达丰) - 柏林",
|
||||||
"Oman (Muscat)":"本地区域:阿曼(马斯喀特)",
|
"eu-central-1-wl1-dtm1": "欧洲 (沃达丰) - 多特蒙德",
|
||||||
"Peru (Lima)":"本地区域:秘鲁(利马)",
|
"eu-central-1-wl1-muc1": "欧洲 (沃达丰) - 慕尼黑",
|
||||||
"Philippines (Manila)":"本地区域:菲律宾(马尼拉)",
|
"eu-west-2-wl1-lon1": "欧洲 (沃达丰) - 伦敦",
|
||||||
"Poland (Warsaw)":"本地区域:波兰(华沙)",
|
"eu-west-2-wl1-man1": "欧洲 (沃达丰) - 曼彻斯特",
|
||||||
"Senegal (Dakar)":"运营商区域:塞内加尔(达喀尔)",
|
"eu-west-2-wl2-man1": "欧洲 (英国电信) - 曼彻斯特",
|
||||||
"Taiwan (Taipei)":"本地区域:台湾(台北)",
|
"eu-west-3-wl1-cmn1": "摩洛哥 (卡萨布兰卡)",
|
||||||
"Thailand (Bangkok)":"本地区域:泰国(曼谷)",
|
"us-east-1-wl1": "美国东部 (Verizon) - 波士顿",
|
||||||
"US East (Atlanta)":"本地区域:美国东部(亚特兰大)",
|
"us-east-1-wl1-atl1": "美国东部 (Verizon) - 亚特兰大",
|
||||||
"US East (Boston)":"本地区域:美国东部(波士顿)",
|
"us-east-1-wl1-bna1": "美国东部 (Verizon) - 纳什维尔",
|
||||||
"US East (Chicago)":"本地区域:美国东部(芝加哥)",
|
"us-east-1-wl1-chi1": "美国东部 (Verizon) - 芝加哥",
|
||||||
"US East (Dallas)":"本地区域:美国东部(达拉斯)",
|
"us-east-1-wl1-clt1": "美国东部 (Verizon) - 夏洛特",
|
||||||
"US East (Houston)":"本地区域:美国东部(休斯顿)",
|
"us-east-1-wl1-dfw1": "美国东部 (Verizon) - 达拉斯",
|
||||||
"US East (Kansas City 2)":"本地区域:美国东部(堪萨斯城 2)",
|
"us-east-1-wl1-dtw1": "美国东部 (Verizon) - 底特律",
|
||||||
"US East (Lenexa)":"运营商区域:美国东部(列涅萨)",
|
"us-east-1-wl1-iah1": "美国东部 (Verizon) - 休斯顿",
|
||||||
"US East (Miami)":"本地区域:美国东部(迈阿密)",
|
"us-east-1-wl1-mia1": "美国东部 (Verizon) - 迈阿密",
|
||||||
"US East (Minneapolis)":"本地区域:美国东部(明尼阿波利斯)",
|
"us-east-1-wl1-msp1": "美国东部 (Verizon) - 明尼阿波利斯",
|
||||||
"US East (New York City)":"本地区域:美国东部(纽约市)",
|
"us-east-1-wl1-nyc1": "美国东部 (Verizon) - 纽约",
|
||||||
"US East (Philadelphia)":"本地区域:美国东部(费城)",
|
"us-east-1-wl1-tpa1": "美国东部 (Verizon) - 坦帕",
|
||||||
"US East (Verizon) - Atlanta":"运营商区域:美国东部(威瑞森)– 亚特兰大",
|
"us-east-1-wl1-was1": "美国东部 (Verizon) - 华盛顿特区",
|
||||||
"US East (Verizon) - Boston":"运营商区域:美国东部(威瑞森)– 波士顿",
|
"us-west-2-wl1": "美国西部 (Verizon) - 旧金山湾区",
|
||||||
"US East (Verizon) - Charlotte":"运营商区域:美国东部(威瑞森)– 夏洛特",
|
"us-west-2-wl1-den1": "美国西部 (Verizon) - 丹佛",
|
||||||
"US East (Verizon) - Chicago":"运营商区域:美国东部(威瑞森)– 芝加哥",
|
"us-west-2-wl1-las1": "美国西部 (Verizon) - 拉斯维加斯",
|
||||||
"US East (Verizon) - Dallas":"运营商区域:美国东部(威瑞森)– 达拉斯",
|
"us-west-2-wl1-lax1": "美国西部 (Verizon) - 洛杉矶",
|
||||||
"US East (Verizon) - Detroit":"运营商区域:美国东部(威瑞森)– 底特律",
|
"us-west-2-wl1-phx1": "美国西部 (Verizon) - 凤凰城",
|
||||||
"US East (Verizon) - Houston":"运营商区域:美国东部(威瑞森)– 休斯顿",
|
"us-west-2-wl1-sea1": "美国西部 (Verizon) - 西雅图",
|
||||||
"US East (Verizon) - Miami":"运营商区域:美国东部(威瑞森)– 迈阿密",
|
"af-south-1-los-1": "尼日利亚 (拉各斯)",
|
||||||
"US East (Verizon) - Minneapolis":"运营商区域:美国东部(威瑞森)– 明尼阿波利斯",
|
"ap-south-1-ccu-1": "印度 (加尔各答)",
|
||||||
"US East (Verizon) - Nashville":"运营商区域:美国东部(威瑞森)- 纳什维尔",
|
"ap-south-1-del-1": "印度 (德里)",
|
||||||
"US East (Verizon) - New York":"运营商区域:美国东部(威瑞森)– 纽约",
|
"ap-southeast-1-bkk-1": "泰国 (曼谷)",
|
||||||
"US East (Verizon) - Tampa":"运营商区域:美国东部(威瑞森)– 坦帕",
|
"ap-southeast-1-mnl-1": "菲律宾 (马尼拉)",
|
||||||
"US East (Verizon) - Washington DC":"运营商区域:美国东部(威瑞森)– 华盛顿特区",
|
"ap-southeast-2-akl-1": "新西兰 (奥克兰)",
|
||||||
"US West (Denver)":"本地区域:美国西部(丹佛)",
|
"ap-southeast-2-per-1": "澳大利亚 (珀斯)",
|
||||||
"US West (Honolulu)":"本地区域:美国西部(檀香山)",
|
"eu-central-1-ham-1": "德国 (汉堡)",
|
||||||
"US West (Las Vegas)":"本地区域:美国西部(拉斯维加斯)",
|
"eu-central-1-waw-1": "波兰 (华沙)",
|
||||||
"US West (Los Angeles)":"本地区域:美国西部(洛杉矶)",
|
"eu-north-1-cph-1": "丹麦 (哥本哈根)",
|
||||||
"US West (Phoenix)":"本地区域:美国西部(菲尼克斯)",
|
"eu-north-1-hel-1": "芬兰 (赫尔辛基)",
|
||||||
"US West (Portland)":"本地区域:美国西部(波特兰)",
|
"me-south-1-mct-1": "阿曼 (马斯喀特)",
|
||||||
"US West (Seattle)":"本地区域:美国西部(西雅图)",
|
"us-east-1-atl-1": "美国东部 (亚特兰大)",
|
||||||
"US West (Verizon) - Denver":"运营商区域:美国西部(威瑞森)- 丹佛",
|
"us-east-1-bos-1": "美国东部 (波士顿)",
|
||||||
"US West (Verizon) - Las Vegas":"运营商区域:美国西部(威瑞森)- 拉斯维加斯",
|
"us-east-1-bue-1": "阿根廷 (布宜诺斯艾利斯)",
|
||||||
"US West (Verizon) - Los Angeles":"运营商区域:美国西部(威瑞森)– 洛杉矶",
|
"us-east-1-chi-1": "美国东部 (芝加哥)",
|
||||||
"US West (Verizon) - Phoenix":"运营商区域:美国东部(威瑞森)– 凤凰城",
|
"us-east-1-dfw-1": "美国东部 (达拉斯)",
|
||||||
"US West (Verizon) - San Francisco Bay Area":"运营商区域:美国西部(威瑞森)– 旧金山港湾区",
|
"us-east-1-iah-1": "美国东部 (休斯顿)",
|
||||||
"US West (Verizon) - Seattle":"运营商区域:美国西部(威瑞森)- 西雅图",
|
"us-east-1-lim-1": "秘鲁 (利马)",
|
||||||
"AWS GovCloud (US)":"区域:AWS GovCloud(美国西部)",
|
"us-east-1-mci-1": "美国东部 (堪萨斯城 2)",
|
||||||
"AWS GovCloud (US-East)":"区域:AWS GovCloud(美国东部)",
|
"us-east-1-mia-1": "美国东部 (迈阿密)",
|
||||||
"Asia Pacific (Mumbai)":"区域:亚太地区(孟买)",
|
"us-east-1-msp-1": "美国东部 (明尼阿波利斯)",
|
||||||
"Asia Pacific (Seoul)":"区域:亚太地区(首尔)",
|
"us-east-1-nyc-1": "美国东部 (纽约市)",
|
||||||
"Asia Pacific (Singapore)":"区域:亚太地区(新加坡)",
|
"us-east-1-phl-1": "美国东部 (费城)",
|
||||||
"Asia Pacific (Sydney)":"区域:亚太地区(悉尼)",
|
"us-east-1-qro-1": "墨西哥 (克雷塔罗)",
|
||||||
"Asia Pacific (Tokyo)":"区域:亚太地区(东京)",
|
"us-east-1-scl-1": "智利 (圣地亚哥)",
|
||||||
"Canada (Central)":"区域:加拿大(中部)",
|
"us-west-2-den-1": "美国西部 (丹佛)",
|
||||||
"EU (Frankfurt)":"区域:欧洲地区(法兰克福)",
|
"us-west-2-hnl-1": "美国西部 (火奴鲁鲁)",
|
||||||
"EU (Ireland)":"区域:欧洲地区(爱尔兰)",
|
"us-west-2-las-1": "美国西部 (拉斯维加斯)",
|
||||||
"EU (London)":"区域:欧洲地区(伦敦)",
|
"us-west-2-lax-1": "美国西部 (洛杉矶)",
|
||||||
"South America (Sao Paulo)":"区域:南美洲(圣保罗)",
|
"us-west-2-pdx-1": "美国西部 (波特兰)",
|
||||||
"US East (N. Virginia)":"区域:美国东部(弗吉尼亚州北部)",
|
"us-west-2-phx-1": "美国西部 (凤凰城)",
|
||||||
"US East (Ohio)":"区域:美国东部(俄亥俄州)",
|
"us-west-2-sea-1": "美国西部 (西雅图)"
|
||||||
"US West (Oregon)":"区域:美国西部(俄勒冈州)",
|
|
||||||
"EU (Paris)":"区域:欧洲地区(巴黎)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AWS_REGION_NAMES_EN = {
|
AWS_REGION_NAMES_EN = {
|
||||||
"Asia Pacific (Malaysia)":"Asia Pacific (Malaysia)",
|
"af-south-1": "Africa (Cape Town)",
|
||||||
"Asia Pacific (Taipei)":"Asia Pacific (Taipei)",
|
"ap-northeast-1": "Asia Pacific (Tokyo)",
|
||||||
"Asia Pacific (Thailand)":"Asia Pacific (Thailand)",
|
"ap-northeast-2": "Asia Pacific (Seoul)",
|
||||||
"Mexico (Central)":"Mexico (Central)",
|
"ap-northeast-3": "Asia Pacific (Osaka)",
|
||||||
"Africa (Cape Town)":"Africa (Cape Town)",
|
"ap-south-1": "Asia Pacific (Mumbai)",
|
||||||
"Asia Pacific (Hong Kong)":"Asia Pacific (Hong Kong)",
|
"ap-east-1": "Asia Pacific (Hong Kong)",
|
||||||
"Asia Pacific (Hyderabad)":"Asia Pacific (Hyderabad)",
|
"ap-south-2": "Asia Pacific (Hyderabad)",
|
||||||
"Asia Pacific (Jakarta)":"Asia Pacific (Jakarta)",
|
"ap-southeast-1": "Asia Pacific (Singapore)",
|
||||||
"Asia Pacific (Melbourne)":"Asia Pacific (Melbourne)",
|
"ap-southeast-2": "Asia Pacific (Sydney)",
|
||||||
"Asia Pacific (Osaka)":"Asia Pacific (Osaka)",
|
"ap-southeast-3": "Asia Pacific (Jakarta)",
|
||||||
"Canada West (Calgary)":"Canada West (Calgary)",
|
"ap-southeast-4": "Asia Pacific (Melbourne)",
|
||||||
"EU (Milan)":"EU (Milan)",
|
"ap-southeast-5": "Asia Pacific (Malaysia)",
|
||||||
"EU (Spain)":"EU (Spain)",
|
"ap-southeast-7": "Asia Pacific (Thailand)",
|
||||||
"EU (Stockholm)":"EU (Stockholm)",
|
"ca-central-1": "Canada (Central)",
|
||||||
"EU (Zurich)":"EU (Zurich)",
|
"ca-west-1": "Canada West (Calgary)",
|
||||||
"Israel (Tel Aviv)":"Israel (Tel Aviv)",
|
"eu-central-1": "EU (Frankfurt)",
|
||||||
"Middle East (Bahrain)":"Middle East (Bahrain)",
|
"eu-central-2": "EU (Zurich)",
|
||||||
"Middle East (UAE)":"Middle East (UAE)",
|
"eu-north-1": "EU (Stockholm)",
|
||||||
"US West (N. California)":"US West (N. California)",
|
"eu-south-1": "EU (Milan)",
|
||||||
"External":"External",
|
"eu-south-2": "EU (Spain)",
|
||||||
"Amazon CloudFront":"Amazon CloudFront",
|
"eu-west-1": "EU (Ireland)",
|
||||||
"Argentina (Buenos Aires)":"Argentina (Buenos Aires)",
|
"eu-west-2": "EU (London)",
|
||||||
"Asia Pacific (KDDI) - Osaka":"Asia Pacific (KDDI) - Osaka",
|
"eu-west-3": "EU (Paris)",
|
||||||
"Asia Pacific (KDDI) - Tokyo":"Asia Pacific (KDDI) - Tokyo",
|
"il-central-1": "Israel (Tel Aviv)",
|
||||||
"Asia Pacific (New Zealand)":"Asia Pacific (New Zealand)",
|
"me-central-1": "Middle East (UAE)",
|
||||||
"Asia Pacific (SKT) - Daejeon":"Asia Pacific (SKT) - Daejeon",
|
"me-south-1": "Middle East (Bahrain)",
|
||||||
"Asia Pacific (SKT) - Seoul":"Asia Pacific (SKT) - Seoul",
|
"mx-central-1": "Mexico (Central)",
|
||||||
"Australia (Perth)":"Australia (Perth)",
|
"sa-east-1": "South America (Sao Paulo)",
|
||||||
"Canada (BELL) - Toronto":"Canada (BELL) - Toronto",
|
"us-east-1": "US East (N. Virginia)",
|
||||||
"Chile (Santiago)":"Chile (Santiago)",
|
"us-east-2": "US East (Ohio)",
|
||||||
"Denmark (Copenhagen)":"Denmark (Copenhagen)",
|
"us-east-2-mci-1": "US East (Kansas City)",
|
||||||
"EU (British Telecom) - Manchester":"EU (British Telecom) - Manchester",
|
"us-gov-east-1": "AWS GovCloud (US-East)",
|
||||||
"EU (Vodafone) - Berlin":"EU (Vodafone) - Berlin",
|
"us-gov-west-1": "AWS GovCloud (US)",
|
||||||
"EU (Vodafone) - Dortmund":"EU (Vodafone) - Dortmund",
|
"us-west-1": "US West (N. California)",
|
||||||
"EU (Vodafone) - London":"EU (Vodafone) - London",
|
"us-west-2": "US West (Oregon)",
|
||||||
"EU (Vodafone) - Manchester":"EU (Vodafone) - Manchester",
|
"ap-northeast-1-wl1-kix1": "Asia Pacific (KDDI) - Osaka",
|
||||||
"EU (Vodafone) - Munich":"EU (Vodafone) - Munich",
|
"ap-northeast-1-wl1-nrt1": "Asia Pacific (KDDI) - Tokyo",
|
||||||
"Finland (Helsinki)":"Finland (Helsinki)",
|
"ap-northeast-2-wl1-cjj1": "Asia Pacific (SKT) - Daejeon",
|
||||||
"Germany (Hamburg)":"Germany (Hamburg)",
|
"ap-northeast-2-wl1-sel1": "Asia Pacific (SKT) - Seoul",
|
||||||
"India (Delhi)":"India (Delhi)",
|
"ap-northeast-1-tpe-1": "Asia Pacific (Taiwan)",
|
||||||
"India (Kolkata)":"India (Kolkata)",
|
"ca-central-1-wl1-yto1": "Canada (BELL) - Toronto",
|
||||||
"Mexico (Queretaro)":"Mexico (Queretaro)",
|
"eu-central-1-wl1-ber1": "EU (Vodafone) - Berlin",
|
||||||
"Morocco (Casablanca)":"Morocco (Casablanca)",
|
"eu-central-1-wl1-dtm1": "EU (Vodafone) - Dortmund",
|
||||||
"New Zealand (Auckland)":"New Zealand (Auckland)",
|
"eu-central-1-wl1-muc1": "EU (Vodafone) - Munich",
|
||||||
"Nigeria (Lagos)":"Nigeria (Lagos)",
|
"eu-west-2-wl1-lon1": "EU (Vodafone) - London",
|
||||||
"Oman (Muscat)":"Oman (Muscat)",
|
"eu-west-2-wl1-man1": "EU (Vodafone) - Manchester",
|
||||||
"Peru (Lima)":"Peru (Lima)",
|
"eu-west-2-wl2-man1": "EU (British Telecom) - Manchester",
|
||||||
"Philippines (Manila)":"Philippines (Manila)",
|
"eu-west-3-wl1-cmn1": "Morocco (Casablanca)",
|
||||||
"Poland (Warsaw)":"Poland (Warsaw)",
|
"us-east-1-wl1": "US East (Verizon) - Boston",
|
||||||
"SG Government (Singapore)":"SG Government (Singapore)",
|
"us-east-1-wl1-atl1": "US East (Verizon) - Atlanta",
|
||||||
"Senegal (Dakar)":"Senegal (Dakar)",
|
"us-east-1-wl1-bna1": "US East (Verizon) - Nashville",
|
||||||
"Taiwan (Taipei)":"Taiwan (Taipei)",
|
"us-east-1-wl1-chi1": "US East (Verizon) - Chicago",
|
||||||
"Thailand (Bangkok)":"Thailand (Bangkok)",
|
"us-east-1-wl1-clt1": "US East (Verizon) - Charlotte",
|
||||||
"US East (Atlanta)":"US East (Atlanta)",
|
"us-east-1-wl1-dfw1": "US East (Verizon) - Dallas",
|
||||||
"US East (Boston)":"US East (Boston)",
|
"us-east-1-wl1-dtw1": "US East (Verizon) - Detroit",
|
||||||
"US East (Chicago)":"US East (Chicago)",
|
"us-east-1-wl1-iah1": "US East (Verizon) - Houston",
|
||||||
"US East (Dallas)":"US East (Dallas)",
|
"us-east-1-wl1-mia1": "US East (Verizon) - Miami",
|
||||||
"US East (Houston)":"US East (Houston)",
|
"us-east-1-wl1-msp1": "US East (Verizon) - Minneapolis",
|
||||||
"US East (Kansas City 2)":"US East (Kansas City 2)",
|
"us-east-1-wl1-nyc1": "US East (Verizon) - New York",
|
||||||
"US East (Kansas City)":"US East (Kansas City)",
|
"us-east-1-wl1-tpa1": "US East (Verizon) - Tampa",
|
||||||
"US East (Lenexa)":"US East (Lenexa)",
|
"us-east-1-wl1-was1": "US East (Verizon) - Washington DC",
|
||||||
"US East (Miami)":"US East (Miami)",
|
"us-west-2-wl1": "US West (Verizon) - San Francisco Bay Area",
|
||||||
"US East (Minneapolis)":"US East (Minneapolis)",
|
"us-west-2-wl1-den1": "US West (Verizon) - Denver",
|
||||||
"US East (New York City)":"US East (New York City)",
|
"us-west-2-wl1-las1": "US West (Verizon) - Las Vegas",
|
||||||
"US East (Philadelphia)":"US East (Philadelphia)",
|
"us-west-2-wl1-lax1": "US West (Verizon) - Los Angeles",
|
||||||
"US East (South Bend)":"US East (South Bend)",
|
"us-west-2-wl1-phx1": "US West (Verizon) - Phoenix",
|
||||||
"US East (Verizon) - Atlanta":"US East (Verizon) - Atlanta",
|
"us-west-2-wl1-sea1": "US West (Verizon) - Seattle",
|
||||||
"US East (Verizon) - Boston":"US East (Verizon) - Boston",
|
"af-south-1-los-1": "Nigeria (Lagos)",
|
||||||
"US East (Verizon) - Charlotte":"US East (Verizon) - Charlotte",
|
"ap-south-1-ccu-1": "India (Kolkata)",
|
||||||
"US East (Verizon) - Chicago":"US East (Verizon) - Chicago",
|
"ap-south-1-del-1": "India (Delhi)",
|
||||||
"US East (Verizon) - Dallas":"US East (Verizon) - Dallas",
|
"ap-southeast-1-bkk-1": "Thailand (Bangkok)",
|
||||||
"US East (Verizon) - Detroit":"US East (Verizon) - Detroit",
|
"ap-southeast-1-mnl-1": "Philippines (Manila)",
|
||||||
"US East (Verizon) - Houston":"US East (Verizon) - Houston",
|
"ap-southeast-2-akl-1": "New Zealand (Auckland)",
|
||||||
"US East (Verizon) - Miami":"US East (Verizon) - Miami",
|
"ap-southeast-2-per-1": "Australia (Perth)",
|
||||||
"US East (Verizon) - Minneapolis":"US East (Verizon) - Minneapolis",
|
"eu-central-1-ham-1": "Germany (Hamburg)",
|
||||||
"US East (Verizon) - Nashville":"US East (Verizon) - Nashville",
|
"eu-central-1-waw-1": "Poland (Warsaw)",
|
||||||
"US East (Verizon) - New York":"US East (Verizon) - New York",
|
"eu-north-1-cph-1": "Denmark (Copenhagen)",
|
||||||
"US East (Verizon) - Tampa":"US East (Verizon) - Tampa",
|
"eu-north-1-hel-1": "Finland (Helsinki)",
|
||||||
"US East (Verizon) - Washington DC":"US East (Verizon) - Washington DC",
|
"me-south-1-mct-1": "Oman (Muscat)",
|
||||||
"US West (Denver)":"US West (Denver)",
|
"us-east-1-atl-1": "US East (Atlanta)",
|
||||||
"US West (Honolulu)":"US West (Honolulu)",
|
"us-east-1-bos-1": "US East (Boston)",
|
||||||
"US West (Las Vegas)":"US West (Las Vegas)",
|
"us-east-1-bue-1": "Argentina (Buenos Aires)",
|
||||||
"US West (Los Angeles)":"US West (Los Angeles)",
|
"us-east-1-chi-1": "US East (Chicago)",
|
||||||
"US West (Phoenix)":"US West (Phoenix)",
|
"us-east-1-dfw-1": "US East (Dallas)",
|
||||||
"US West (Portland)":"US West (Portland)",
|
"us-east-1-iah-1": "US East (Houston)",
|
||||||
"US West (Seattle)":"US West (Seattle)",
|
"us-east-1-lim-1": "Peru (Lima)",
|
||||||
"US West (Verizon) - Denver":"US West (Verizon) - Denver",
|
"us-east-1-mci-1": "US East (Kansas City 2)",
|
||||||
"US West (Verizon) - Las Vegas":"US West (Verizon) - Las Vegas",
|
"us-east-1-mia-1": "US East (Miami)",
|
||||||
"US West (Verizon) - Los Angeles":"US West (Verizon) - Los Angeles",
|
"us-east-1-msp-1": "US East (Minneapolis)",
|
||||||
"US West (Verizon) - Phoenix":"US West (Verizon) - Phoenix",
|
"us-east-1-nyc-1": "US East (New York City)",
|
||||||
"US West (Verizon) - San Francisco Bay Area":"US West (Verizon) - San Francisco Bay Area",
|
"us-east-1-phl-1": "US East (Philadelphia)",
|
||||||
"US West (Verizon) - Seattle":"US West (Verizon) - Seattle",
|
"us-east-1-qro-1": "Mexico (Queretaro)",
|
||||||
"AWS GovCloud (US)":"AWS GovCloud (US)",
|
"us-east-1-scl-1": "Chile (Santiago)",
|
||||||
"AWS GovCloud (US-East)":"AWS GovCloud (US-East)",
|
"us-west-2-den-1": "US West (Denver)",
|
||||||
"Asia Pacific (Mumbai)":"Asia Pacific (Mumbai)",
|
"us-west-2-hnl-1": "US West (Honolulu)",
|
||||||
"Asia Pacific (Seoul)":"Asia Pacific (Seoul)",
|
"us-west-2-las-1": "US West (Las Vegas)",
|
||||||
"Asia Pacific (Singapore)":"Asia Pacific (Singapore)",
|
"us-west-2-lax-1": "US West (Los Angeles)",
|
||||||
"Asia Pacific (Sydney)":"Asia Pacific (Sydney)",
|
"us-west-2-pdx-1": "US West (Portland)",
|
||||||
"Asia Pacific (Tokyo)":"Asia Pacific (Tokyo)",
|
"us-west-2-phx-1": "US West (Phoenix)",
|
||||||
"Canada (Central)":"Canada (Central)",
|
"us-west-2-sea-1": "US West (Seattle)"
|
||||||
"EU (Frankfurt)":"EU (Frankfurt)",
|
|
||||||
"EU (Ireland)":"EU (Ireland)",
|
|
||||||
"EU (London)":"EU (London)",
|
|
||||||
"South America (Sao Paulo)":"South America (Sao Paulo)",
|
|
||||||
"US East (N. Virginia)":"US East (N. Virginia)",
|
|
||||||
"US East (Ohio)":"US East (Ohio)",
|
|
||||||
"US West (Oregon)":"US West (Oregon)",
|
|
||||||
"EU (Paris)":"EU (Paris)"
|
|
||||||
}
|
}
|
||||||
# 可以添加其他云平台的配置
|
# 可以添加其他云平台的配置
|
||||||
AZURE_REGION_NAMES = {
|
AZURE_REGION_NAMES = {
|
||||||
|
|||||||
@ -58,8 +58,6 @@ async def search_instances_v2(
|
|||||||
operating_system,
|
operating_system,
|
||||||
vcpu,
|
vcpu,
|
||||||
memory,
|
memory,
|
||||||
gp3,
|
|
||||||
gp2,
|
|
||||||
updatetime
|
updatetime
|
||||||
FROM aws_price
|
FROM aws_price
|
||||||
WHERE 1=1
|
WHERE 1=1
|
||||||
@ -71,11 +69,11 @@ async def search_instances_v2(
|
|||||||
query += " AND area_en = %s"
|
query += " AND area_en = %s"
|
||||||
params.append(region_name)
|
params.append(region_name)
|
||||||
|
|
||||||
if cpu_cores > 0:
|
if cpu_cores:
|
||||||
query += " AND vcpu = %s"
|
query += " AND vcpu = %s"
|
||||||
params.append(cpu_cores)
|
params.append(cpu_cores)
|
||||||
|
|
||||||
if memory_gb > 0:
|
if memory_gb:
|
||||||
query += " AND memory = %s"
|
query += " AND memory = %s"
|
||||||
params.append(memory_gb)
|
params.append(memory_gb)
|
||||||
|
|
||||||
@ -88,15 +86,10 @@ async def search_instances_v2(
|
|||||||
cursor.execute(query, params)
|
cursor.execute(query, params)
|
||||||
results = cursor.fetchall()
|
results = cursor.fetchall()
|
||||||
|
|
||||||
if len(results) >= 40:
|
|
||||||
results = results[0:40]
|
|
||||||
|
|
||||||
# 处理结果
|
# 处理结果
|
||||||
instances = []
|
instances = []
|
||||||
for row in results:
|
for row in results:
|
||||||
hourly_price = float(row['price'])
|
hourly_price = float(row['price'])
|
||||||
gp3_price = float(row['gp3'])
|
|
||||||
gp2_price = float(row['gp2'])
|
|
||||||
monthly_price = hourly_price * 730 # 730小时/月
|
monthly_price = hourly_price * 730 # 730小时/月
|
||||||
|
|
||||||
# 计算存储价格
|
# 计算存储价格
|
||||||
@ -109,8 +102,7 @@ async def search_instances_v2(
|
|||||||
region_code = code
|
region_code = code
|
||||||
break
|
break
|
||||||
|
|
||||||
# disk_monthly_price = await calculate_ebs_price(region_code, disk_gb) if region_code else 0
|
disk_monthly_price = await calculate_ebs_price(region_code, disk_gb) if region_code else 0
|
||||||
disk_monthly_price = gp3_price * disk_gb if gp3_price > 0 else gp2_price * disk_gb
|
|
||||||
|
|
||||||
# 计算总价格
|
# 计算总价格
|
||||||
total_monthly_price = monthly_price + disk_monthly_price
|
total_monthly_price = monthly_price + disk_monthly_price
|
||||||
|
|||||||
@ -1,2 +1,2 @@
|
|||||||
# 生产环境API配置
|
# 生产环境API配置
|
||||||
VUE_APP_API_BASE_URL=/api
|
VUE_APP_API_BASE_URL=http://calc.buddyscloud.com:8000
|
||||||
BIN
frontend/dist.zip
Normal file
BIN
frontend/dist.zip
Normal file
Binary file not shown.
@ -41,7 +41,7 @@ const apiService = {
|
|||||||
// 获取区域列表
|
// 获取区域列表
|
||||||
getRegions: async () => {
|
getRegions: async () => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.get('/regions')
|
const response = await apiClient.get('/api/regions')
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取区域列表失败:', error)
|
console.error('获取区域列表失败:', error)
|
||||||
@ -52,7 +52,7 @@ const apiService = {
|
|||||||
// 获取实例类型列表
|
// 获取实例类型列表
|
||||||
getInstanceTypes: async () => {
|
getInstanceTypes: async () => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.get('/instance-types')
|
const response = await apiClient.get('/api/instance-types')
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取实例类型列表失败:', error)
|
console.error('获取实例类型列表失败:', error)
|
||||||
@ -63,7 +63,7 @@ const apiService = {
|
|||||||
// 搜索实例
|
// 搜索实例
|
||||||
searchInstances: async (params) => {
|
searchInstances: async (params) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.post('/search-instances-v2', params)
|
const response = await apiClient.post('/api/search-instances-v2', params)
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('搜索实例失败:', error)
|
console.error('搜索实例失败:', error)
|
||||||
@ -74,7 +74,7 @@ const apiService = {
|
|||||||
// 计算价格
|
// 计算价格
|
||||||
calculatePrice: async (params) => {
|
calculatePrice: async (params) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.post('/calculate-price', params)
|
const response = await apiClient.post('/api/calculate-price', params)
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('计算价格失败:', error)
|
console.error('计算价格失败:', error)
|
||||||
@ -85,7 +85,7 @@ const apiService = {
|
|||||||
// 比较价格
|
// 比较价格
|
||||||
comparePrices: async (params) => {
|
comparePrices: async (params) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.post('/compare-prices', params)
|
const response = await apiClient.post('/api/compare-prices', params)
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('比较价格失败:', error)
|
console.error('比较价格失败:', error)
|
||||||
@ -96,7 +96,7 @@ const apiService = {
|
|||||||
// 获取预算估算
|
// 获取预算估算
|
||||||
getBudgetEstimate: async (params) => {
|
getBudgetEstimate: async (params) => {
|
||||||
try {
|
try {
|
||||||
const response = await apiClient.post('/budget', params)
|
const response = await apiClient.post('/api/budget', params)
|
||||||
return response.data
|
return response.data
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取预算估算失败:', error)
|
console.error('获取预算估算失败:', error)
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
// API 配置文件
|
// API 配置文件
|
||||||
const config = {
|
const config = {
|
||||||
// 后端API基础URL 使用相对路径,通过 devServer 代理到后端
|
// 后端API基础URL - 从环境变量中读取,如果不存在则使用默认值
|
||||||
// apiBaseUrl: process.env.VUE_APP_API_BASE_URL ,
|
apiBaseUrl: process.env.VUE_APP_API_BASE_URL || 'http://localhost:8000',
|
||||||
apiBaseUrl: '/api',
|
|
||||||
|
|
||||||
|
|
||||||
// 其他全局配置
|
// 其他全局配置
|
||||||
defaultRegion: 'us-east-1',
|
defaultRegion: 'us-east-1',
|
||||||
|
|||||||
@ -361,41 +361,25 @@
|
|||||||
|
|
||||||
<el-table-column label="官方月付全额" width="120" align="center">
|
<el-table-column label="官方月付全额" width="120" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="price-breakdown-text">
|
<span class="price-value">${{ scope.row.total_monthly_price.toFixed(2) }}</span>
|
||||||
<div>实例: ${{ (Number(scope.row.monthly_price) || 0).toFixed(2) }}</div>
|
|
||||||
<div>磁盘: ${{ (Number(scope.row.disk_monthly_price) || 0).toFixed(2) }}</div>
|
|
||||||
<div class="price-value highlight">共计: ${{ getOfficialMonthlyPrice(scope.row).toFixed(2) }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="月付优惠价" width="120" align="center">
|
<el-table-column label="月付优惠价" width="120" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="price-breakdown-text">
|
<span class="price-value highlight">${{ (scope.row.total_monthly_price * form.monthly_discount).toFixed(2) }}</span>
|
||||||
<div>实例: ${{ (scope.row.monthly_price * form.monthly_discount).toFixed(2) }}</div>
|
|
||||||
<div>磁盘: ${{ scope.row.disk_monthly_price.toFixed(2) }}</div>
|
|
||||||
<div class="price-value highlight">共计: ${{ getDiscountedMonthlyPrice(scope.row).toFixed(2) }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="官方年付全额" width="120" align="center">
|
<el-table-column label="官方年付全额" width="120" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="price-breakdown-text">
|
<span class="price-value">${{ (scope.row.total_monthly_price * 12).toFixed(2) }}</span>
|
||||||
<div>实例: ${{ ((Number(scope.row.monthly_price) || 0) * 12).toFixed(2) }}</div>
|
|
||||||
<div>磁盘: ${{ ((Number(scope.row.disk_monthly_price) || 0) * 12).toFixed(2) }}</div>
|
|
||||||
<div class="price-value highlight">共计: ${{ getOfficialYearlyPrice(scope.row).toFixed(2) }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<el-table-column label="年付优惠价" width="120" align="center">
|
<el-table-column label="年付优惠价" width="120" align="center">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="price-breakdown-text">
|
<span class="price-value highlight">${{ (scope.row.total_monthly_price * 12 * form.yearly_discount).toFixed(2) }}</span>
|
||||||
<div>实例: ${{ (scope.row.monthly_price * 12 * form.yearly_discount).toFixed(2) }}</div>
|
|
||||||
<div>磁盘: ${{ (scope.row.disk_monthly_price * 12).toFixed(2) }}</div>
|
|
||||||
<div class="price-value highlight">共计: ${{ getDiscountedYearlyPrice(scope.row).toFixed(2) }}</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
@ -417,8 +401,8 @@
|
|||||||
<div class="note-title">说明事项:</div>
|
<div class="note-title">说明事项:</div>
|
||||||
<div class="note-items">
|
<div class="note-items">
|
||||||
<div class="note-item">1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB</div>
|
<div class="note-item">1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB</div>
|
||||||
<div class="note-item">2. 月付(仅实例部分)按官网价 {{ formatDiscount(form.monthly_discount) }} 折,磁盘不参与优惠</div>
|
<div class="note-item">2. 月付按官网价 {{ formatDiscount(form.monthly_discount) }} 折</div>
|
||||||
<div class="note-item">3. 年付(仅实例部分)按官网价 {{ formatDiscount(form.yearly_discount) }} 折,磁盘不参与优惠</div>
|
<div class="note-item">3. 年付按官网价 {{ formatDiscount(form.yearly_discount) }} 折</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -621,32 +605,10 @@
|
|||||||
|
|
||||||
// 创建数据行
|
// 创建数据行
|
||||||
const dataRows = this.comparisonList.map(instance => {
|
const dataRows = this.comparisonList.map(instance => {
|
||||||
const officialMonthlyPrice = this.getOfficialMonthlyPrice(instance)
|
const officialMonthlyPrice = instance.total_monthly_price
|
||||||
const officialYearlyPrice = this.getOfficialYearlyPrice(instance)
|
const discountedMonthlyPrice = officialMonthlyPrice * this.form.monthly_discount
|
||||||
const discountedMonthlyPrice = this.getDiscountedMonthlyPrice(instance)
|
const officialYearlyPrice = officialMonthlyPrice * 12
|
||||||
const discountedYearlyPrice = this.getDiscountedYearlyPrice(instance)
|
const discountedYearlyPrice = officialYearlyPrice * this.form.yearly_discount
|
||||||
const instanceMonthlyPrice = Number(instance.monthly_price) || 0
|
|
||||||
const diskMonthlyPrice = Number(instance.disk_monthly_price) || 0
|
|
||||||
const officialMonthlyDetail = [
|
|
||||||
`实例: $${instanceMonthlyPrice.toFixed(2)}`,
|
|
||||||
`磁盘: $${diskMonthlyPrice.toFixed(2)}`,
|
|
||||||
`共计: $${officialMonthlyPrice.toFixed(2)}`
|
|
||||||
].join('\n')
|
|
||||||
const discountedMonthlyDetail = [
|
|
||||||
`实例: $${(instanceMonthlyPrice * Number(this.form.monthly_discount || 0)).toFixed(2)}`,
|
|
||||||
`磁盘: $${diskMonthlyPrice.toFixed(2)}`,
|
|
||||||
`共计: $${discountedMonthlyPrice.toFixed(2)}`
|
|
||||||
].join('\n')
|
|
||||||
const officialYearlyDetail = [
|
|
||||||
`实例: $${(instanceMonthlyPrice * 12).toFixed(2)}`,
|
|
||||||
`磁盘: $${(diskMonthlyPrice * 12).toFixed(2)}`,
|
|
||||||
`共计: $${officialYearlyPrice.toFixed(2)}`
|
|
||||||
].join('\n')
|
|
||||||
const discountedYearlyDetail = [
|
|
||||||
`实例: $${(instanceMonthlyPrice * 12 * Number(this.form.yearly_discount || 0)).toFixed(2)}`,
|
|
||||||
`磁盘: $${(diskMonthlyPrice * 12).toFixed(2)}`,
|
|
||||||
`共计: $${discountedYearlyPrice.toFixed(2)}`
|
|
||||||
].join('\n')
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'EC2',
|
'EC2',
|
||||||
@ -654,10 +616,10 @@
|
|||||||
`${instance.disk_gb}G GP3`,
|
`${instance.disk_gb}G GP3`,
|
||||||
this.formatOS(instance.operating_system),
|
this.formatOS(instance.operating_system),
|
||||||
this.getRegionName(instance.region),
|
this.getRegionName(instance.region),
|
||||||
officialMonthlyDetail,
|
officialMonthlyPrice.toFixed(2),
|
||||||
discountedMonthlyDetail,
|
discountedMonthlyPrice.toFixed(2),
|
||||||
officialYearlyDetail,
|
officialYearlyPrice.toFixed(2),
|
||||||
discountedYearlyDetail
|
discountedYearlyPrice.toFixed(2)
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -666,8 +628,8 @@
|
|||||||
emptyRow,
|
emptyRow,
|
||||||
['说明事项:'],
|
['说明事项:'],
|
||||||
['1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB'],
|
['1. 以上价格仅包服务器和磁盘的费用, 以上价格仅包服务器和磁盘的费用, 公共带宽流量按官网价格 均价$0.12USD/GB'],
|
||||||
[`2. 月付(仅实例部分)按官网价 ${this.formatDiscount(this.form.monthly_discount)} 折,磁盘不参与优惠`],
|
[`2. 月付按官网价 ${this.formatDiscount(this.form.monthly_discount)} 折`],
|
||||||
[`3. 年付(仅实例部分)按官网价 ${this.formatDiscount(this.form.yearly_discount)} 折,磁盘不参与优惠`]
|
[`3. 年付按官网价 ${this.formatDiscount(this.form.yearly_discount)} 折`]
|
||||||
]
|
]
|
||||||
|
|
||||||
// 合并所有行
|
// 合并所有行
|
||||||
@ -694,9 +656,6 @@
|
|||||||
const rowHeights = Array(allRows.length).fill({ hpt: 25 })
|
const rowHeights = Array(allRows.length).fill({ hpt: 25 })
|
||||||
rowHeights[0] = { hpt: 35 } // 标题行
|
rowHeights[0] = { hpt: 35 } // 标题行
|
||||||
rowHeights[4] = { hpt: 30 } // 表头行
|
rowHeights[4] = { hpt: 30 } // 表头行
|
||||||
for (let i = 0; i < dataRows.length; i++) {
|
|
||||||
rowHeights[4 + 1 + i] = { hpt: 55 }
|
|
||||||
}
|
|
||||||
ws['!rows'] = rowHeights
|
ws['!rows'] = rowHeights
|
||||||
|
|
||||||
// 设置单元格合并
|
// 设置单元格合并
|
||||||
@ -778,20 +737,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 说明事项行左对齐并自动换行
|
|
||||||
for (let r = noteStartRow; r < noteStartRow + 5; r++) {
|
|
||||||
for (let c = 0; c < 9; c++) {
|
|
||||||
const cellRef = XLSX.utils.encode_cell({ r, c })
|
|
||||||
if (!ws[cellRef]) ws[cellRef] = { v: '', t: 's' }
|
|
||||||
if (!ws[cellRef].s) ws[cellRef].s = {}
|
|
||||||
ws[cellRef].s.alignment = { horizontal: 'left', vertical: 'center', wrapText: true }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置价格列样式
|
// 设置价格列样式
|
||||||
const priceColsStyle = {
|
const priceColsStyle = {
|
||||||
|
numFmt: '0.00',
|
||||||
font: { color: { rgb: '1F7B69' } },
|
font: { color: { rgb: '1F7B69' } },
|
||||||
alignment: { horizontal: 'left', vertical: 'center', wrapText: true },
|
alignment: { horizontal: 'center', vertical: 'center' },
|
||||||
border: {
|
border: {
|
||||||
top: { style: 'thin' },
|
top: { style: 'thin' },
|
||||||
bottom: { style: 'thin' },
|
bottom: { style: 'thin' },
|
||||||
@ -858,26 +808,6 @@
|
|||||||
if (os === 'Windows') return 'Windows'
|
if (os === 'Windows') return 'Windows'
|
||||||
return os
|
return os
|
||||||
},
|
},
|
||||||
getOfficialMonthlyPrice(instance) {
|
|
||||||
const instancePrice = Number(instance.monthly_price) || 0
|
|
||||||
const diskPrice = Number(instance.disk_monthly_price) || 0
|
|
||||||
return instancePrice + diskPrice
|
|
||||||
},
|
|
||||||
getOfficialYearlyPrice(instance) {
|
|
||||||
return this.getOfficialMonthlyPrice(instance) * 12
|
|
||||||
},
|
|
||||||
getDiscountedMonthlyPrice(instance) {
|
|
||||||
const instancePrice = Number(instance.monthly_price) || 0
|
|
||||||
const diskPrice = Number(instance.disk_monthly_price) || 0
|
|
||||||
const discount = Number(this.form.monthly_discount) || 0
|
|
||||||
return instancePrice * discount + diskPrice
|
|
||||||
},
|
|
||||||
getDiscountedYearlyPrice(instance) {
|
|
||||||
const instancePrice = Number(instance.monthly_price) || 0
|
|
||||||
const diskPrice = Number(instance.disk_monthly_price) || 0
|
|
||||||
const discount = Number(this.form.yearly_discount) || 0
|
|
||||||
return instancePrice * 12 * discount + diskPrice * 12
|
|
||||||
},
|
|
||||||
// 计算打折后的价格
|
// 计算打折后的价格
|
||||||
calculateDiscountedPrice(originalPrice, discount) {
|
calculateDiscountedPrice(originalPrice, discount) {
|
||||||
return originalPrice * discount;
|
return originalPrice * discount;
|
||||||
@ -1031,14 +961,6 @@
|
|||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
|
|
||||||
.price-breakdown-text {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-results {
|
.no-results {
|
||||||
padding: 40px 0;
|
padding: 40px 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,8 +15,8 @@
|
|||||||
<el-form-item label="CPU 核心数">
|
<el-form-item label="CPU 核心数">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="form.cpu_cores"
|
v-model="form.cpu_cores"
|
||||||
:min="0"
|
:min="1"
|
||||||
:max="9999"
|
:max="64"
|
||||||
:step="1"
|
:step="1"
|
||||||
placeholder="所需CPU核心数"
|
placeholder="所需CPU核心数"
|
||||||
class="full-width">
|
class="full-width">
|
||||||
@ -28,8 +28,8 @@
|
|||||||
<el-form-item label="内存(GB)">
|
<el-form-item label="内存(GB)">
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="form.memory_gb"
|
v-model="form.memory_gb"
|
||||||
:min="0"
|
:min="0.5"
|
||||||
:max="99999"
|
:max="256"
|
||||||
:step="0.5"
|
:step="0.5"
|
||||||
placeholder="所需内存容量(GB)"
|
placeholder="所需内存容量(GB)"
|
||||||
class="full-width">
|
class="full-width">
|
||||||
@ -388,8 +388,8 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
cpu_cores: 0,
|
cpu_cores: null,
|
||||||
memory_gb: 0,
|
memory_gb: null,
|
||||||
disk_gb: 30, // 默认30GB
|
disk_gb: 30, // 默认30GB
|
||||||
region: 'us-east-1',
|
region: 'us-east-1',
|
||||||
disk_type: 'gp3',
|
disk_type: 'gp3',
|
||||||
|
|||||||
@ -1,16 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
devServer: {
|
|
||||||
proxy: {
|
|
||||||
'/api': {
|
|
||||||
target: 'http://127.0.0.1:8000',
|
|
||||||
changeOrigin: true,
|
|
||||||
ws: false,
|
|
||||||
secure: false,
|
|
||||||
// 保留 /api 前缀并转发到后端 FastAPI(后端已以 /api 为前缀)
|
|
||||||
pathRewrite: { '^/api': '/api' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user