This commit is contained in:
MarkLo127 2026-03-11 17:46:07 +08:00
parent cccf02b8dc
commit a45bd56ad0
4 changed files with 25 additions and 37 deletions

View File

@ -38,6 +38,7 @@ class ReportCreate(BaseModel):
market_type: str # us, twse, tpex
analysis_date: str
result: dict
language: Optional[str] = None
class ReportResponse(BaseModel):
@ -47,6 +48,7 @@ class ReportResponse(BaseModel):
market_type: str
analysis_date: str
result: dict
language: Optional[str] = None
created_at: str
@ -166,6 +168,7 @@ async def get_reports(
market_type=r.market_type,
analysis_date=r.analysis_date,
result=r.result,
language=r.language,
created_at=r.created_at.isoformat() + "Z"
)
for r in reports
@ -184,7 +187,8 @@ async def create_report(
ticker=report_data.ticker,
market_type=report_data.market_type,
analysis_date=report_data.analysis_date,
result=report_data.result
result=report_data.result,
language=report_data.language
)
db.add(report)
await db.commit()
@ -223,6 +227,7 @@ async def get_report(
market_type=report.market_type,
analysis_date=report.analysis_date,
result=report.result,
language=report.language,
created_at=report.created_at.isoformat() + "Z"
)

View File

@ -62,6 +62,16 @@ async def init_db():
async with engine.begin() as conn:
# Create all tables
await conn.run_sync(Base.metadata.create_all)
# Manual migrations for existing databases
try:
# Add language column if it doesn't exist
await conn.execute(text("ALTER TABLE reports ADD COLUMN IF NOT EXISTS language VARCHAR(10);"))
# Add indexes to optimize queries
await conn.execute(text("CREATE INDEX IF NOT EXISTS ix_reports_user_id ON reports (user_id);"))
await conn.execute(text("CREATE INDEX IF NOT EXISTS ix_reports_created_at ON reports (created_at);"))
except Exception as e:
print(f"Skipping manual migration (might be SQLite or syntax not supported): {e}")
print("Database tables initialized successfully")

View File

@ -85,17 +85,20 @@ class Report(Base):
user_id: Mapped[uuid.UUID] = mapped_column(
UUID(as_uuid=True),
ForeignKey("users.id", ondelete="CASCADE"),
nullable=False
nullable=False,
index=True
)
ticker: Mapped[str] = mapped_column(String(20), nullable=False)
market_type: Mapped[str] = mapped_column(String(10), nullable=False) # us, twse, tpex
analysis_date: Mapped[str] = mapped_column(String(10), nullable=False) # YYYY-MM-DD
# Store full result as JSONB
result: Mapped[dict] = mapped_column(JSON, nullable=False)
language: Mapped[Optional[str]] = mapped_column(String(10), nullable=True)
created_at: Mapped[datetime] = mapped_column(
DateTime,
default=datetime.utcnow,
nullable=False
nullable=False,
index=True
)
# Relationship

View File

@ -574,43 +574,18 @@ export default function HistoryPage() {
new Date(b.saved_at).getTime() - new Date(a.saved_at).getTime(),
);
// Filter by current language
const languageFiltered = merged.filter((report) => {
// Use stored language if available
if (report.language) {
return report.language === locale;
}
// Fallback: detect from content for old reports without language field
return detectReportLanguage(report.result?.reports) === locale;
});
setReports(languageFiltered);
setReports(merged);
setIsCloudData(true);
return;
}
}
// If no cloud data or not authenticated, use local only
// Filter by current language
const languageFiltered = localData.filter((report) => {
if (report.language) {
return report.language === locale;
}
return detectReportLanguage(report.result?.reports) === locale;
});
setReports(languageFiltered);
setReports(localData);
setIsCloudData(false);
} catch (error) {
console.error("Failed to load reports:", error);
// Fall back to local on error
const data = await getReportsByMarketType(activeTab);
const languageFiltered = data.filter((report) => {
if (report.language) {
return report.language === locale;
}
return detectReportLanguage(report.result?.reports) === locale;
});
setReports(languageFiltered);
setReports(data as SavedReport[]);
setIsCloudData(false);
} finally {
setLoading(false);
@ -621,12 +596,7 @@ export default function HistoryPage() {
try {
// Helper to filter reports by language
const filterByLanguage = (reports: SavedReport[]) => {
return reports.filter(report => {
if (report.language) {
return report.language === locale;
}
return detectReportLanguage(report.result?.reports) === locale;
});
return reports;
};
if (isAuthenticated && isCloudSyncEnabled()) {