Merge pull request #228 from NyaDoo/fix/config-timezone-and-key-dialog

fix: APP_TIMEZONE 循环导入 & 独立密钥额度编辑空白
This commit is contained in:
fawney19
2026-03-14 01:42:28 +08:00
committed by GitHub
8 changed files with 20 additions and 18 deletions

View File

@@ -207,9 +207,9 @@
@update:model-value="(v) => form.initial_balance_usd = parseNumberInput(v, { allowFloat: true, min: 0.01 })" @update:model-value="(v) => form.initial_balance_usd = parseNumberInput(v, { allowFloat: true, min: 0.01 })"
/> />
<span <span
v-else-if="form.unlimited_balance" v-else
class="flex h-10 w-full items-center rounded-lg border bg-background px-3 text-sm text-muted-foreground opacity-60" class="flex h-10 w-full items-center rounded-lg border bg-background px-3 text-sm text-muted-foreground opacity-60"
>无限制</span> >{{ form.unlimited_balance ? '无限制' : '按钱包余额限制' }}</span>
</div> </div>
<Switch <Switch
:model-value="form.unlimited_balance ?? false" :model-value="form.unlimited_balance ?? false"

View File

@@ -5,7 +5,6 @@
from __future__ import annotations from __future__ import annotations
import os
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone
from typing import Any, Literal from typing import Any, Literal
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
@@ -18,6 +17,7 @@ from sqlalchemy.orm import Session
from src.api.base.admin_adapter import AdminApiAdapter from src.api.base.admin_adapter import AdminApiAdapter
from src.api.base.context import ApiRequestContext from src.api.base.context import ApiRequestContext
from src.api.base.pipeline import ApiRequestPipeline from src.api.base.pipeline import ApiRequestPipeline
from src.config import config
from src.core.exceptions import InvalidRequestException, NotFoundException from src.core.exceptions import InvalidRequestException, NotFoundException
from src.core.logger import logger from src.core.logger import logger
from src.database import get_db, get_db_context from src.database import get_db, get_db_context
@@ -27,8 +27,7 @@ from src.services.user.apikey import ApiKeyService
from src.services.user.bulk_cleanup import pre_clean_api_key from src.services.user.bulk_cleanup import pre_clean_api_key
from src.services.wallet import WalletService from src.services.wallet import WalletService
# 应用时区配置,默认为 Asia/Shanghai APP_TIMEZONE = ZoneInfo(config.app_timezone)
APP_TIMEZONE = ZoneInfo(os.getenv("APP_TIMEZONE", "Asia/Shanghai"))
def parse_expiry_date(date_str: str | None) -> datetime | None: def parse_expiry_date(date_str: str | None) -> datetime | None:

View File

@@ -647,12 +647,12 @@ class UserDashboardStatsAdapter(DashboardAdapter):
async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override] async def handle(self, context: ApiRequestContext) -> Any: # type: ignore[override]
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from src.services.system.stats_aggregator import APP_TIMEZONE from src.config import config
db = context.db db = context.db
user = context.user user = context.user
# 使用业务时区计算日期,确保与用户感知的"今天"一致 # 使用业务时区计算日期,确保与用户感知的"今天"一致
app_tz = ZoneInfo(APP_TIMEZONE) app_tz = ZoneInfo(config.app_timezone)
now_local = datetime.now(app_tz) now_local = datetime.now(app_tz)
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0) today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
# 转换为 UTC 用于数据库查询 # 转换为 UTC 用于数据库查询
@@ -1159,9 +1159,9 @@ class DashboardDailyStatsAdapter(DashboardAdapter):
# 使用业务时区计算日期,确保每日统计与业务日期一致 # 使用业务时区计算日期,确保每日统计与业务日期一致
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
from src.services.system.stats_aggregator import APP_TIMEZONE from src.config import config
app_tz = ZoneInfo(APP_TIMEZONE) app_tz = ZoneInfo(config.app_timezone)
now_local = datetime.now(app_tz) now_local = datetime.now(app_tz)
today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0) today_local = now_local.replace(hour=0, minute=0, second=0, microsecond=0)
# 转换为 UTC 用于数据库查询 # 转换为 UTC 用于数据库查询

View File

@@ -87,6 +87,9 @@ class Config:
# 注意: allow_credentials=True 时不能使用 allow_origins=["*"] # 注意: allow_credentials=True 时不能使用 allow_origins=["*"]
self.cors_allow_credentials = os.getenv("CORS_ALLOW_CREDENTIALS", "true").lower() == "true" self.cors_allow_credentials = os.getenv("CORS_ALLOW_CREDENTIALS", "true").lower() == "true"
# 应用时区配置(用于定时任务、账单日期等业务逻辑)
self.app_timezone = os.getenv("APP_TIMEZONE", "Asia/Shanghai")
# 管理员账户配置(用于初始化) # 管理员账户配置(用于初始化)
self.admin_email = os.getenv("ADMIN_EMAIL", "admin@localhost") self.admin_email = os.getenv("ADMIN_EMAIL", "admin@localhost")
self.admin_username = os.getenv("ADMIN_USERNAME", "admin") self.admin_username = os.getenv("ADMIN_USERNAME", "admin")

View File

@@ -11,7 +11,7 @@ from src.services.system.maintenance_scheduler import (
MaintenanceScheduler, MaintenanceScheduler,
get_maintenance_scheduler, get_maintenance_scheduler,
) )
from src.services.system.scheduler import APP_TIMEZONE, TaskScheduler, get_scheduler from src.services.system.scheduler import TaskScheduler, get_scheduler
from src.services.system.sync_stats import SyncStatsService from src.services.system.sync_stats import SyncStatsService
__all__ = [ __all__ = [
@@ -23,5 +23,4 @@ __all__ = [
"SyncStatsService", "SyncStatsService",
"TaskScheduler", "TaskScheduler",
"get_scheduler", "get_scheduler",
"APP_TIMEZONE",
] ]

View File

@@ -8,7 +8,6 @@
from __future__ import annotations from __future__ import annotations
import os
from datetime import datetime from datetime import datetime
from typing import Any, Callable from typing import Any, Callable
@@ -17,10 +16,11 @@ from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.date import DateTrigger from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.interval import IntervalTrigger
from src.config import config
from src.core.logger import logger from src.core.logger import logger
# 应用时区配置,默认为 Asia/Shanghai # 统一从 config 读取,不再重复 os.getenv
APP_TIMEZONE = os.getenv("APP_TIMEZONE", "Asia/Shanghai") APP_TIMEZONE = config.app_timezone
class TaskScheduler: class TaskScheduler:

View File

@@ -5,7 +5,6 @@
from __future__ import annotations from __future__ import annotations
import os
import uuid import uuid
from dataclasses import dataclass from dataclasses import dataclass
from datetime import date, datetime, time, timedelta, timezone from datetime import date, datetime, time, timedelta, timezone
@@ -16,6 +15,7 @@ from sqlalchemy import Date, Float, and_, case, cast, func, text
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from src.config import config
from src.core.logger import logger from src.core.logger import logger
from src.models.database import ( from src.models.database import (
ApiKey, ApiKey,
@@ -36,8 +36,7 @@ from src.models.database import (
from src.models.database import User as DBUser from src.models.database import User as DBUser
from src.services.system.time_range import TimeRangeParams, split_time_range_for_hourly from src.services.system.time_range import TimeRangeParams, split_time_range_for_hourly
# App timezone (legacy defaults for dashboard) APP_TIMEZONE = config.app_timezone
APP_TIMEZONE = os.getenv("APP_TIMEZONE", "Asia/Shanghai")
MIN_PERCENTILE_SAMPLES = 10 MIN_PERCENTILE_SAMPLES = 10

View File

@@ -8,10 +8,12 @@ from zoneinfo import ZoneInfo
from sqlalchemy import func from sqlalchemy import func
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from src.config import config
from src.core.logger import logger from src.core.logger import logger
from src.models.database import Usage, WalletDailyUsageLedger from src.models.database import Usage, WalletDailyUsageLedger
from src.services.billing.precision import to_money_decimal from src.services.billing.precision import to_money_decimal
from src.services.system.scheduler import APP_TIMEZONE
APP_TIMEZONE = config.app_timezone
@dataclass(slots=True) @dataclass(slots=True)