feat: initial commit

This commit is contained in:
qzl
2026-03-31 13:32:22 +08:00
commit 695adb7d6f
49 changed files with 2990 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
from . import user, divination, payment, notification, feedback, version, log, violation
__all__ = [
"user",
"divination",
"payment",
"notification",
"feedback",
"version",
"log",
"violation",
]
+41
View File
@@ -0,0 +1,41 @@
from __future__ import annotations
from core.db.base import Base, TimestampMixin
from sqlalchemy import BigInteger, DateTime, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class DivinationRecord(TimestampMixin, Base):
__tablename__ = "user_divination_records"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
trace_id: Mapped[str] = mapped_column(String(64), nullable=False)
question: Mapped[str] = mapped_column(Text, nullable=False)
question_type: Mapped[str] = mapped_column(String(50), nullable=False)
divination_data: Mapped[str] = mapped_column(Text, nullable=False)
deepseek_request: Mapped[str] = mapped_column(Text, nullable=False)
deepseek_response: Mapped[str | None] = mapped_column(Text, nullable=True)
interpretation_result: Mapped[str | None] = mapped_column(Text, nullable=True)
api_success: Mapped[bool] = mapped_column(Integer, nullable=False, default=0)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
api_duration_ms: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
phone_number: Mapped[str | None] = mapped_column(String(20), nullable=True)
class DivinationHistory(TimestampMixin, Base):
__tablename__ = "user_divination_history"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
phone_number: Mapped[str] = mapped_column(String(20), nullable=False)
local_record_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
json_data: Mapped[str] = mapped_column(Text, nullable=False)
ai_result: Mapped[str] = mapped_column(Text, nullable=False)
question_type: Mapped[str] = mapped_column(String(50), nullable=False)
question: Mapped[str] = mapped_column(Text, nullable=False)
timestamp: Mapped[int] = mapped_column(BigInteger, nullable=False)
is_active: Mapped[bool] = mapped_column(Integer, nullable=False, default=1)
sync_time: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
+17
View File
@@ -0,0 +1,17 @@
from __future__ import annotations
from core.db.base import Base
from sqlalchemy import BigInteger, DateTime, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class UserFeedback(Base):
__tablename__ = "user_feedback"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
phone_number: Mapped[str] = mapped_column(String(20), nullable=False)
content: Mapped[str] = mapped_column(Text, nullable=False)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
+39
View File
@@ -0,0 +1,39 @@
from __future__ import annotations
from core.db.base import Base
from sqlalchemy import BigInteger, DateTime, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class NetworkAccessLog(Base):
__tablename__ = "network_access_logs"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
phone_number: Mapped[str | None] = mapped_column(String(20), nullable=True)
client_ip: Mapped[str] = mapped_column(String(45), nullable=False)
client_port: Mapped[int | None] = mapped_column(Integer, nullable=True)
server_ip: Mapped[str] = mapped_column(String(45), nullable=False)
server_port: Mapped[int] = mapped_column(Integer, nullable=False)
http_method: Mapped[str] = mapped_column(String(10), nullable=False)
request_path: Mapped[str] = mapped_column(String(500), nullable=False)
request_url: Mapped[str] = mapped_column(String(1000), nullable=False)
user_agent: Mapped[str | None] = mapped_column(String(1000), nullable=True)
device_info: Mapped[str | None] = mapped_column(Text, nullable=True)
response_status: Mapped[int | None] = mapped_column(Integer, nullable=True)
processing_time_ms: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
request_size: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
response_size: Mapped[int | None] = mapped_column(BigInteger, nullable=True)
x_forwarded_for: Mapped[str | None] = mapped_column(String(500), nullable=True)
x_real_ip: Mapped[str | None] = mapped_column(String(45), nullable=True)
referer: Mapped[str | None] = mapped_column(String(1000), nullable=True)
operation_type: Mapped[str | None] = mapped_column(String(50), nullable=True)
operation_result: Mapped[str | None] = mapped_column(String(20), nullable=True)
error_message: Mapped[str | None] = mapped_column(Text, nullable=True)
session_id: Mapped[str | None] = mapped_column(String(100), nullable=True)
access_time: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
+14
View File
@@ -0,0 +1,14 @@
from __future__ import annotations
from core.db.base import Base
from sqlalchemy import BigInteger, String, Text
from sqlalchemy.orm import Mapped, mapped_column
class Notification(Base):
__tablename__ = "notification"
id: Mapped[str] = mapped_column(String(64), primary_key=True)
title: Mapped[str] = mapped_column(String(255), nullable=False)
content: Mapped[str] = mapped_column(Text, nullable=False)
timestamp: Mapped[int] = mapped_column(BigInteger, nullable=False)
+40
View File
@@ -0,0 +1,40 @@
from __future__ import annotations
from core.db.base import Base, TimestampMixin
from sqlalchemy import BigInteger, DateTime, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class PaymentOrder(TimestampMixin, Base):
__tablename__ = "payment_order"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
order_no: Mapped[str] = mapped_column(String(64), unique=True, nullable=False)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
amount: Mapped[str] = mapped_column(String(20), nullable=False)
coin_count: Mapped[int] = mapped_column(Integer, nullable=False)
subject: Mapped[str] = mapped_column(String(256), nullable=False)
body: Mapped[str | None] = mapped_column(String(512), nullable=True)
channel: Mapped[str] = mapped_column(String(16), nullable=False)
status: Mapped[str] = mapped_column(String(16), nullable=False, default="CREATED")
trade_no: Mapped[str | None] = mapped_column(String(64), nullable=True)
payment_time: Mapped[str | None] = mapped_column(DateTime, nullable=True)
class PaymentRecord(Base):
__tablename__ = "payment_record"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
order_no: Mapped[str] = mapped_column(String(64), nullable=False)
trade_no: Mapped[str] = mapped_column(String(64), nullable=False)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
channel: Mapped[str] = mapped_column(String(16), nullable=False)
notify_type: Mapped[str] = mapped_column(String(16), nullable=False)
trade_status: Mapped[str] = mapped_column(String(32), nullable=False)
notify_data: Mapped[str] = mapped_column(Text, nullable=False)
process_status: Mapped[str] = mapped_column(String(16), nullable=False)
process_message: Mapped[str | None] = mapped_column(String(512), nullable=True)
coin_added: Mapped[bool] = mapped_column(Integer, nullable=False, default=0)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
+52
View File
@@ -0,0 +1,52 @@
from __future__ import annotations
from core.db.base import Base, TimestampMixin
from sqlalchemy import BigInteger, DateTime, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class User(TimestampMixin, Base):
__tablename__ = "user_profile"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
phone_number: Mapped[str] = mapped_column(String(20), unique=True, nullable=False)
nickname: Mapped[str] = mapped_column(String(50), nullable=False, default="")
gender: Mapped[str] = mapped_column(String(10), nullable=False, default="")
birthday: Mapped[str] = mapped_column(
String(20), nullable=False, default="2000-01-01"
)
signature: Mapped[str] = mapped_column(String(255), nullable=False, default="")
class UserToken(Base):
__tablename__ = "user_tokens"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
token: Mapped[str] = mapped_column(String(255), nullable=False)
expire_time: Mapped[str] = mapped_column(DateTime, nullable=False)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
class VerificationCode(Base):
__tablename__ = "verification_codes"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
phone_number: Mapped[str] = mapped_column(String(20), nullable=False)
code: Mapped[str] = mapped_column(String(6), nullable=False)
expiration_time: Mapped[str] = mapped_column(DateTime, nullable=False)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
used: Mapped[bool] = mapped_column(Integer, nullable=False, default=0)
class UserCoin(Base):
__tablename__ = "user_coin"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False, unique=True)
phone_number: Mapped[str] = mapped_column(String(20), nullable=False)
coin_balance: Mapped[int] = mapped_column(Integer, nullable=False, default=3)
+19
View File
@@ -0,0 +1,19 @@
from __future__ import annotations
from core.db.base import Base, TimestampMixin
from sqlalchemy import BigInteger, Integer, String, Text
from sqlalchemy.orm import Mapped, mapped_column
class AppVersion(TimestampMixin, Base):
__tablename__ = "app_version"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
version_name: Mapped[str] = mapped_column(String(20), unique=True, nullable=False)
version_code: Mapped[int] = mapped_column(Integer, unique=True, nullable=False)
min_supported_version: Mapped[str] = mapped_column(String(20), nullable=False)
min_supported_code: Mapped[int] = mapped_column(Integer, nullable=False)
is_force_update: Mapped[bool] = mapped_column(Integer, nullable=False, default=0)
update_message: Mapped[str | None] = mapped_column(Text, nullable=True)
download_url: Mapped[str | None] = mapped_column(String(500), nullable=True)
is_active: Mapped[bool] = mapped_column(Integer, nullable=False, default=1)
+30
View File
@@ -0,0 +1,30 @@
from __future__ import annotations
from core.db.base import Base
from sqlalchemy import BigInteger, DateTime, Float, Integer, String, Text, func
from sqlalchemy.orm import Mapped, mapped_column
class SensitiveWordViolation(Base):
__tablename__ = "sensitive_word_violations"
id: Mapped[int] = mapped_column(BigInteger, primary_key=True, autoincrement=True)
user_id: Mapped[int] = mapped_column(BigInteger, nullable=False)
content_type: Mapped[str] = mapped_column(String(20), nullable=False)
original_content: Mapped[str] = mapped_column(Text, nullable=False)
violation_type: Mapped[str] = mapped_column(String(30), nullable=False)
detection_service: Mapped[str] = mapped_column(
String(20), nullable=False, default="LOCAL"
)
risk_level: Mapped[str | None] = mapped_column(String(50), nullable=True)
confidence: Mapped[float | None] = mapped_column(Float, nullable=True)
aliyun_response: Mapped[str | None] = mapped_column(Text, nullable=True)
matched_words: Mapped[str] = mapped_column(Text, nullable=False)
client_ip: Mapped[str | None] = mapped_column(String(45), nullable=True)
user_agent: Mapped[str | None] = mapped_column(Text, nullable=True)
violation_time: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)
created_at: Mapped[str] = mapped_column(
DateTime, nullable=False, server_default=func.now()
)