增加国内站&国际站切换选项

This commit is contained in:
青柠
2026-03-20 09:21:12 +08:00
parent 08691c6207
commit 2b9ae0308e
5 changed files with 40 additions and 25 deletions

View File

@@ -89,12 +89,13 @@ class AliyunService
/**
* 获取 BSS 费用中心 API 的 regionId 和 endpoint
* 中国站(国内区域): cn-hangzhou + business.aliyuncs.com
* 国际站(海外区域): ap-southeast-1 + business.ap-southeast-1.aliyuncs.com
* 中国站: cn-hangzhou + business.aliyuncs.com
* 国际站: ap-southeast-1 + business.ap-southeast-1.aliyuncs.com
* @param string $siteType 'china' 或 'international'
*/
private function getBssEndpoint($targetRegion)
private function getBssEndpoint($siteType = 'china')
{
if ($this->isOverseas($targetRegion)) {
if ($siteType === 'international') {
return [
'regionId' => 'ap-southeast-1',
'host' => 'business.ap-southeast-1.aliyuncs.com'
@@ -257,14 +258,14 @@ class AliyunService
* @return array ['AvailableAmount' => '...', 'Currency' => 'CNY']
* @throws \Exception
*/
public function getAccountBalance($key, $secret, $targetRegion = 'cn-hangzhou')
public function getAccountBalance($key, $secret, $siteType = 'china')
{
$cacheKey = md5($key);
if (isset($this->balanceCache[$cacheKey])) {
return $this->balanceCache[$cacheKey];
}
$bss = $this->getBssEndpoint($targetRegion);
$bss = $this->getBssEndpoint($siteType);
$result = $this->executeWithRetry(function () use ($key, $secret, $bss) {
AlibabaCloud::accessKeyClient($key, $secret)
@@ -303,9 +304,9 @@ class AliyunService
* @return array ['TotalCost' => float, 'Items' => [...]]
* @throws \Exception
*/
public function getInstanceBill($key, $secret, $instanceId, $billingCycle, $targetRegion = 'cn-hangzhou')
public function getInstanceBill($key, $secret, $instanceId, $billingCycle, $siteType = 'china')
{
$bss = $this->getBssEndpoint($targetRegion);
$bss = $this->getBssEndpoint($siteType);
$result = $this->executeWithRetry(function () use ($key, $secret, $instanceId, $billingCycle, $bss) {
AlibabaCloud::accessKeyClient($key, $secret)
@@ -363,9 +364,9 @@ class AliyunService
* @return array ['TotalCost' => float, 'Products' => [...]]
* @throws \Exception
*/
public function getBillOverview($key, $secret, $billingCycle, $targetRegion = 'cn-hangzhou')
public function getBillOverview($key, $secret, $billingCycle, $siteType = 'china')
{
$bss = $this->getBssEndpoint($targetRegion);
$bss = $this->getBssEndpoint($siteType);
$result = $this->executeWithRetry(function () use ($key, $secret, $billingCycle, $bss) {
AlibabaCloud::accessKeyClient($key, $secret)

View File

@@ -159,7 +159,8 @@ class AliyunTrafficCheck
'startTime' => $row['start_time'],
'stopTime' => $row['stop_time']
],
'remark' => $row['remark'] ?? ''
'remark' => $row['remark'] ?? '',
'siteType' => $row['site_type'] ?? 'china'
];
}
@@ -549,7 +550,7 @@ class AliyunTrafficCheck
$balance = $this->aliyunService->getAccountBalance(
$targetAccount['access_key_id'],
$targetAccount['access_key_secret'],
$targetAccount['region_id']
$targetAccount['site_type'] ?? 'china'
);
$this->db->setBillingCache($targetAccount['id'], 'balance', '', $balance);
} catch (\Exception $e) {
@@ -567,7 +568,7 @@ class AliyunTrafficCheck
$targetAccount['access_key_secret'],
$targetAccount['instance_id'],
$billingCycle,
$targetAccount['region_id']
$targetAccount['site_type'] ?? 'china'
);
$this->db->setBillingCache($targetAccount['id'], 'instance_bill', $billingCycle, $bill);
} catch (\Exception $e) {
@@ -721,7 +722,7 @@ class AliyunTrafficCheck
$balance = $this->aliyunService->getAccountBalance(
$account['access_key_id'],
$account['access_key_secret'],
$account['region_id']
$account['site_type'] ?? 'china'
);
$costInfo['balance'] = $balance['AvailableAmount'];
$costInfo['currency'] = $balance['Currency'] ?? 'CNY';
@@ -743,7 +744,7 @@ class AliyunTrafficCheck
$account['access_key_secret'],
$account['instance_id'],
$billingCycle,
$account['region_id']
$account['site_type'] ?? 'china'
);
$costInfo['monthly_cost'] = $bill['TotalCost'];
$this->db->setBillingCache($account['id'], 'instance_bill', $billingCycle, $bill);

View File

@@ -135,8 +135,8 @@ class ConfigManager
}
$keptIds = [];
$insertStmt = $this->db->prepare("INSERT INTO accounts (access_key_id, access_key_secret, region_id, instance_id, max_traffic, schedule_enabled, start_time, stop_time, remark, traffic_used, instance_status, updated_at, last_keep_alive_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 'Unknown', 0, 0)");
$updateStmt = $this->db->prepare("UPDATE accounts SET access_key_secret = ?, region_id = ?, instance_id = ?, max_traffic = ?, schedule_enabled = ?, start_time = ?, stop_time = ?, remark = ? WHERE id = ?");
$insertStmt = $this->db->prepare("INSERT INTO accounts (access_key_id, access_key_secret, region_id, instance_id, max_traffic, schedule_enabled, start_time, stop_time, remark, site_type, traffic_used, instance_status, updated_at, last_keep_alive_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 0, 'Unknown', 0, 0)");
$updateStmt = $this->db->prepare("UPDATE accounts SET access_key_secret = ?, region_id = ?, instance_id = ?, max_traffic = ?, schedule_enabled = ?, start_time = ?, stop_time = ?, remark = ?, site_type = ? WHERE id = ?");
foreach ($newAccounts as $acc) {
$key = $acc['AccessKeyId'];
@@ -152,7 +152,8 @@ class ConfigManager
($acc['schedule']['enabled'] ?? false) ? 1 : 0,
$acc['schedule']['startTime'] ?? '',
$acc['schedule']['stopTime'] ?? '',
$acc['remark'] ?? ''
$acc['remark'] ?? '',
$acc['siteType'] ?? 'china'
];
if (isset($existingMap[$compositeKey])) {
@@ -207,7 +208,7 @@ class ConfigManager
$this->db->exec("DELETE FROM accounts");
$this->db->exec("DELETE FROM sqlite_sequence WHERE name='accounts'");
$insertStmt = $this->db->prepare("INSERT INTO accounts (id, access_key_id, access_key_secret, region_id, instance_id, max_traffic, schedule_enabled, start_time, stop_time, remark, traffic_used, instance_status, updated_at, last_keep_alive_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$insertStmt = $this->db->prepare("INSERT INTO accounts (id, access_key_id, access_key_secret, region_id, instance_id, max_traffic, schedule_enabled, start_time, stop_time, remark, site_type, traffic_used, instance_status, updated_at, last_keep_alive_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
$newId = 1;
foreach ($rows as $row) {
@@ -222,6 +223,7 @@ class ConfigManager
$row['start_time'],
$row['stop_time'],
$row['remark'] ?? '',
$row['site_type'] ?? 'china',
$row['traffic_used'],
$row['instance_status'],
$row['updated_at'],

View File

@@ -137,6 +137,7 @@ class Database
$this->ensureColumn('accounts', 'updated_at', 'INTEGER DEFAULT 0');
$this->ensureColumn('accounts', 'last_keep_alive_at', 'INTEGER DEFAULT 0');
$this->ensureColumn('accounts', 'remark', "TEXT DEFAULT ''");
$this->ensureColumn('accounts', 'site_type', "TEXT DEFAULT 'china'");
$this->migrateStatsToAccountId();
}

View File

@@ -801,11 +801,20 @@
</div>
</div>
<div class="mt-4 space-y-1">
<label class="text-xs font-medium text-gray-500 ml-2">备注 <span
class="text-gray-400">(可选)</span></label>
<input v-model="acc.remark" placeholder="为该实例添加备注说明"
class="w-full glass-input rounded-xl px-4 py-2 text-sm">
<div class="mt-4 grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="space-y-1">
<label class="text-xs font-medium text-gray-500 ml-2">站点类型</label>
<select v-model="acc.siteType" class="w-full glass-input rounded-xl px-4 py-2 text-sm appearance-none cursor-pointer">
<option value="china">中国站 (CNY ¥)</option>
<option value="international">国际站 (USD $)</option>
</select>
</div>
<div class="space-y-1">
<label class="text-xs font-medium text-gray-500 ml-2">备注 <span
class="text-gray-400">(可选)</span></label>
<input v-model="acc.remark" placeholder="为该实例添加备注说明"
class="w-full glass-input rounded-xl px-4 py-2 text-sm">
</div>
</div>
<div class="mt-6 pt-4 border-t border-gray-200/50">
@@ -1356,6 +1365,7 @@
if (!acc.schedule) acc.schedule = { enabled: false, startTime: '', stopTime: '' };
if (typeof acc.maxTraffic === 'undefined') acc.maxTraffic = 200;
if (typeof acc.remark === 'undefined') acc.remark = '';
if (typeof acc.siteType === 'undefined') acc.siteType = 'china';
});
if (!data.Notification) {
@@ -1468,7 +1478,7 @@
const addAccount = () => {
if (!config.value.Accounts) config.value.Accounts = [];
config.value.Accounts.push({ AccessKeyId: '', AccessKeySecret: '', maxTraffic: 200, regionId: '', instanceId: '', remark: '', schedule: { enabled: false, startTime: '', stopTime: '' } });
config.value.Accounts.push({ AccessKeyId: '', AccessKeySecret: '', maxTraffic: 200, regionId: '', instanceId: '', remark: '', siteType: 'china', schedule: { enabled: false, startTime: '', stopTime: '' } });
};
const removeAccount = (index) => { if (confirm('确定删除该账号配置?')) config.value.Accounts.splice(index, 1); };