Files
server-core/app/infrastructure/models.py
T

966 lines
50 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""SQLAlchemy ORM 模型(auth/RBAC 域)+ Pydantic 请求/响应模型。
- ORM 模型对应 SQLite 各表(users/roles/permissions/organizations/regions/
sessions/audit_logs/agents)。
- Pydantic 模型与 PineAgents 主后端 ``src/pineagents/app/routers/auth.py``
中的请求/响应模型一一对应,转发层透传时不会丢字段。
"""
from __future__ import annotations
from pydantic import BaseModel, Field
from sqlalchemy import (
Boolean,
Float,
ForeignKey,
Integer,
PrimaryKeyConstraint,
String,
Text,
)
from sqlalchemy.orm import Mapped, mapped_column
from .db import Base
# ===========================================================================
# SQLAlchemy ORM 模型
# ===========================================================================
class User(Base):
__tablename__ = "users"
__table_args__ = {"sqlite_autoincrement": True}
id: Mapped[str] = mapped_column(String, primary_key=True)
username: Mapped[str] = mapped_column(String, unique=True, nullable=False)
password_hash: Mapped[str] = mapped_column(String, nullable=False)
password_salt: Mapped[str] = mapped_column(String, nullable=False)
# 统一登录:微信 openid(登录即建 opc_member 身份);phone 与 username(手机号)对齐
wx_openid: Mapped[str] = mapped_column(String, default="", index=True) # 公众号/网页开放平台
wx_unionid: Mapped[str] = mapped_column(String, default="", index=True) # 微信 unionid(跨应用统一)
wx_mini_openid: Mapped[str] = mapped_column(String, default="", index=True) # 小程序 openid(与网页不同)
phone: Mapped[str] = mapped_column(String, default="")
email: Mapped[str] = mapped_column(String, default="")
nickname: Mapped[str] = mapped_column(String, default="")
account: Mapped[str] = mapped_column(String, default="")
company: Mapped[str] = mapped_column(String, default="")
room: Mapped[str] = mapped_column(String, default="")
avatar: Mapped[str] = mapped_column(String, default="")
company_avatar: Mapped[str] = mapped_column(String, default="")
gender: Mapped[str] = mapped_column(String, default="") # male|female|unknown
birthday: Mapped[str] = mapped_column(String, default="") # YYYY-MM-DD
# 用户详细资料(参考入园申请表 §一 申请人信息)
id_card: Mapped[str] = mapped_column(String, default="") # 身份证号
ethnicity: Mapped[str] = mapped_column(String, default="") # 民族
grad_school_major: Mapped[str] = mapped_column(String, default="") # 毕业院校及专业
grad_time: Mapped[str] = mapped_column(String, default="") # 毕业时间
# RBAC
role: Mapped[str] = mapped_column(String, default="opc_member") # 业务角色
sub_role: Mapped[str] = mapped_column(String, nullable=True) # 政务级/运营方内部
org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
status: Mapped[str] = mapped_column(String, default="active") # active | disabled
token_version: Mapped[int] = mapped_column(Integer, default=0) # revoke-all 递增
# ── 来源与登录跟踪(全局用户统一,记录准确来源) ──
source: Mapped[str] = mapped_column(String, default="") # mini_program|web|desktop|park|admin|seed|wx|phone|unknown
auth_type: Mapped[str] = mapped_column(String, default="") # password|phone|wx_openid|admin
register_ip: Mapped[str] = mapped_column(String, default="")
last_login_ip: Mapped[str] = mapped_column(String, default="")
last_login_at: Mapped[str] = mapped_column(String, default="")
# ── 算力(引擎用户镜像,全局一致) ──
compute_provisioned: Mapped[bool] = mapped_column(Boolean, default=False) # 是否已在算力引擎建号
compute_username: Mapped[str] = mapped_column(String, default="") # 引擎用户名(= username)
compute_quota: Mapped[int] = mapped_column(Integer, default=0) # 缓存引擎可用额度
compute_used_quota: Mapped[int] = mapped_column(Integer, default=0) # 缓存引擎已用额度
# ── 状态与身份分类 ──
certification_status: Mapped[str] = mapped_column(String, default="uncertified") # uncertified|pending|certified|rejected
certification_time: Mapped[str] = mapped_column(String, default="")
affiliation: Mapped[str] = mapped_column(String, default="independent") # independent:独立OPC | park:所属园区
park_id: Mapped[str] = mapped_column(String, default="") # 所属园区(id)
park_name: Mapped[str] = mapped_column(String, default="") # 所属园区(名)
park_company_id: Mapped[str | None] = mapped_column(String, nullable=True) # 所属园区企业(id),成员归属一家企业
account_type: Mapped[str] = mapped_column(String, default="opc_default") # opc_default|park_staff|platform_staff|provider|enterprise
# 小程序/网页「报名资料」字段(现状标签 + 关注主题 JSON)
opc_status: Mapped[str] = mapped_column(String, default="")
topics: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class Role(Base):
__tablename__ = "roles"
id: Mapped[str] = mapped_column(String, primary_key=True) # 角色码
name: Mapped[str] = mapped_column(String, nullable=False) # 展示名
scope_type: Mapped[str] = mapped_column(String, default="business") # business|operator-internal|government-level
description: Mapped[str] = mapped_column(String, default="")
class Permission(Base):
__tablename__ = "permissions"
id: Mapped[str] = mapped_column(String, primary_key=True) # 权限码 menu:xx / action:xx
name: Mapped[str] = mapped_column(String, nullable=False)
category: Mapped[str] = mapped_column(String, default="action") # menu | action
module: Mapped[str] = mapped_column(String, default="") # admin|government|...
description: Mapped[str] = mapped_column(String, default="")
class RolePermission(Base):
__tablename__ = "role_permissions"
role_id: Mapped[str] = mapped_column(
ForeignKey("roles.id", ondelete="CASCADE"), primary_key=True,
)
permission_id: Mapped[str] = mapped_column(
ForeignKey("permissions.id", ondelete="CASCADE"), primary_key=True,
)
class Organization(Base):
__tablename__ = "organizations"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, nullable=False)
type: Mapped[str] = mapped_column(String, default="enterprise") # enterprise|carrier|provider
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
parent_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
status: Mapped[str] = mapped_column(String, default="active")
created_at: Mapped[str] = mapped_column(String, default="")
class OrganizationMember(Base):
"""机构成员(机构主账号 + 机构内子账号):一个账号可挂多个机构。"""
__tablename__ = "organization_members"
org_id: Mapped[str] = mapped_column(
ForeignKey("organizations.id", ondelete="CASCADE"), primary_key=True,
)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
)
role: Mapped[str] = mapped_column(String, default="member") # admin/finance/publisher/service_executor/service_deliverer/clerk/...
is_admin: Mapped[bool] = mapped_column(Boolean, default=False) # 机构主账号/管理员
status: Mapped[str] = mapped_column(String, default="active")
joined_at: Mapped[str] = mapped_column(String, default="")
class Region(Base):
__tablename__ = "regions"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, nullable=False)
level: Mapped[str] = mapped_column(String, default="district") # province|city|district
parent_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
created_at: Mapped[str] = mapped_column(String, default="")
class SessionToken(Base):
__tablename__ = "sessions"
id: Mapped[str] = mapped_column(String, primary_key=True)
jti: Mapped[str] = mapped_column(String, unique=True, nullable=False)
token: Mapped[str] = mapped_column(String, default="") # 完整 JWT(调试用)
user_id: Mapped[str] = mapped_column(ForeignKey("users.id", ondelete="CASCADE"), nullable=False)
username: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
expires_at: Mapped[str] = mapped_column(String, default="")
revoked: Mapped[bool] = mapped_column(Boolean, default=False)
class AuditLog(Base):
__tablename__ = "audit_logs"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True)
action: Mapped[str] = mapped_column(String, default="") # login|role.assign|data.view|...
resource: Mapped[str] = mapped_column(String, default="") # user|role|enterprise|region|...
resource_id: Mapped[str] = mapped_column(String, default="")
detail: Mapped[str] = mapped_column(Text, default="")
ip: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Agent(Base):
__tablename__ = "agents"
# id + user_id + port 复合主键:每个用户在每个端口持有独立的默认/QA 智能体(多端口彻底隔离)
__table_args__ = (PrimaryKeyConstraint("id", "user_id", "port"),)
id: Mapped[str] = mapped_column(String)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
port: Mapped[str] = mapped_column(String, default="opc") # opc/operator/government/... 端口隔离
name: Mapped[str] = mapped_column(String, default="")
description: Mapped[str] = mapped_column(Text, default="")
language: Mapped[str] = mapped_column(String, default="zh")
model_name: Mapped[str] = mapped_column(String, default="")
deletable: Mapped[bool] = mapped_column(Boolean, default=True)
use_fixed_soul: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
# ── 运营端业务模型(平台运营/任务/服务商/内容/配置)────────────────────────
class Task(Base):
"""平台任务(运营端可审核/下架;后续各端口接入)。
状态机(扩展支持扫码接单):draft/pending/review/published/claimed/doing/completed/cancelled。
扫码接单流转:published → claimed(claimed_by/claimed_at) → doing(doing_at) → completed。
历史接单流水见 TaskClaimclaim 记录 claimed_by/claimed_at/doing_at。
"""
__tablename__ = "tasks"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_code: Mapped[str] = mapped_column(String, default="", index=True) # 展示/扫码短码(唯一)
title: Mapped[str] = mapped_column(String, default="")
category: Mapped[str] = mapped_column(String, default="") # 分类字典 name(见 TaskCategory
category_id: Mapped[str | None] = mapped_column(ForeignKey("task_categories.id"), nullable=True)
sub_category: Mapped[str] = mapped_column(String, default="")
description: Mapped[str] = mapped_column(Text, default="")
tags: Mapped[str] = mapped_column(String, default="") # 逗号分隔展示标签
mode: Mapped[str] = mapped_column(String, default="grab") # grab/bid/assign/recommend(旧 designated→assign/dispatch→recommend)
budget_min: Mapped[int] = mapped_column(Integer, default=0)
budget_max: Mapped[int] = mapped_column(Integer, default=0)
deadline: Mapped[str] = mapped_column(String, default="") # 报名/接单截止时间
delivery_days: Mapped[int] = mapped_column(Integer, default=0) # 交付时限(接单后 N 天)
headcount: Mapped[int] = mapped_column(Integer, default=0) # 限制接单人数(0=不限)
exclusive: Mapped[bool] = mapped_column(Boolean, default=False) # 是否独占(仅一人可接)
display_priority: Mapped[int] = mapped_column(Integer, default=0) # 大屏展示排序(越大越前)
status: Mapped[str] = mapped_column(String, default="draft") # draft/pending/review/published/claimed/doing/completed/cancelled
published_at: Mapped[str] = mapped_column(String, default="") # 发布时间(→published 时)
claimed_by: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True)
claimed_at: Mapped[str] = mapped_column(String, default="")
doing_at: Mapped[str] = mapped_column(String, default="")
publisher_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True) # 发包方(用户)
publisher_org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
publisher_name: Mapped[str] = mapped_column(String, default="")
# ── 多端任务体系扩展字段 ──
publisher_role: Mapped[str] = mapped_column(String, default="") # enterprise/operator/park
visibility: Mapped[str] = mapped_column(String, default="public") # public/assigned_only/c_visible
c_visible: Mapped[bool] = mapped_column(Boolean, default=True) # 是否进 C 端任务广场
park_public: Mapped[bool] = mapped_column(Boolean, default=False) # 是否公有任务(各园区大屏可见/本园可接)
assign_type: Mapped[str] = mapped_column(String, default="") # opc/park(指派模式)
assign_park_id: Mapped[str | None] = mapped_column(String, nullable=True) # 指派给某园区
assign_opc_id: Mapped[str | None] = mapped_column(String, nullable=True) # 指派给某 OPC
park_id: Mapped[str | None] = mapped_column(String, nullable=True) # 归属园区(园区发布/专属)
park_released: Mapped[bool] = mapped_column(Boolean, default=False) # 园区内已发单(园区企业可抢)
bid_quota: Mapped[int] = mapped_column(Integer, default=0) # 竞标报名人数上限(0=不限)
win_quota: Mapped[int] = mapped_column(Integer, default=0) # 竞标中标人数(默认1)
eligibility: Mapped[str] = mapped_column(Text, default="{}") # 接单资格条件(JSON 集)
settle_mode: Mapped[str] = mapped_column(String, default="operator_escrow") # 资金托管方式
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class TaskClaim(Base):
"""任务接单流水(扫码/抢单/投标/指派/推荐),rich 记录任务状态流转历史。"""
__tablename__ = "task_claims"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False, index=True,
)
claimer_user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="SET NULL"), nullable=True,
)
claimer_name: Mapped[str] = mapped_column(String, default="")
claim_source: Mapped[str] = mapped_column(String, default="scan") # scan/grab/bid/assign/recommend
claimed_at: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="claimed") # claimed/doing/completed/withdrawn/assigned/recommended
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class TaskCategory(Base):
"""任务分类字典(顶层 35 类,取自 任务类别.json)。"""
__tablename__ = "task_categories"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, default="", index=True)
sort: Mapped[int] = mapped_column(Integer, default=0)
modes: Mapped[str] = mapped_column(String, default="") # 兼容位掩码 hint(逗号分隔,可选)
status: Mapped[str] = mapped_column(String, default="active") # active/disabled
class ServiceProvider(Base):
"""服务商(运营端审核/评级/考核)。"""
__tablename__ = "service_providers"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, default="")
category: Mapped[str] = mapped_column(String, default="") # 财税/工商/法务/知识产权/云服务...
org_id: Mapped[str | None] = mapped_column(ForeignKey("organizations.id"), nullable=True)
level: Mapped[str] = mapped_column(String, default="certified") # certified/premium/gold/official
rating: Mapped[float] = mapped_column(Float, default=5.0)
order_count: Mapped[int] = mapped_column(Integer, default=0)
status: Mapped[str] = mapped_column(String, default="pending") # pending/active/blacklisted
contact: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ContentItem(Base):
"""平台内容(政策/课程/资讯/公告/活动)。"""
__tablename__ = "content_items"
id: Mapped[str] = mapped_column(String, primary_key=True)
type: Mapped[str] = mapped_column(String, default="news") # policy/course/news/notice/activity
title: Mapped[str] = mapped_column(String, default="")
summary: Mapped[str] = mapped_column(String, default="")
body: Mapped[str] = mapped_column(Text, default="")
publisher_id: Mapped[str | None] = mapped_column(ForeignKey("users.id"), nullable=True)
# 资讯富字段:封面/图集/视频/外链/发布人
cover: Mapped[str] = mapped_column(String, default="") # 加宽封面图 URL3.35:1
cover_small: Mapped[str] = mapped_column(String, default="") # 小封面图 URL1:1,可选)
images_json: Mapped[str] = mapped_column(Text, default="[]") # 图集(JSON url 数组)
video: Mapped[str] = mapped_column(String, default="") # 视频 URL
video_cover: Mapped[str] = mapped_column(String, default="") # 视频封面
link: Mapped[str] = mapped_column(String, default="") # 外链
publisher_name: Mapped[str] = mapped_column(String, default="") # 发布人昵称快照
publisher_avatar: Mapped[str] = mapped_column(String, default="") # 发布人头像快照
read_count: Mapped[int] = mapped_column(Integer, default=0) # 阅读数
card_mode: Mapped[str] = mapped_column(String, default="big") # big 大图 | small 小图(运营端设)
is_public: Mapped[bool] = mapped_column(Boolean, default=True) # 是否公开(公开=C端,否则仅园区大屏)
source: Mapped[str] = mapped_column(String, default="operator") # operator 运营端 | carrier 园区端
tenant_id: Mapped[str] = mapped_column(String, default="") # 园区端发布所属园区
priority: Mapped[int] = mapped_column(Integer, default=0) # 优先级 0-999 越大越靠前(C端排序)
status: Mapped[str] = mapped_column(String, default="draft") # draft/pending/published/offlinepending=待审核)
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ContentComment(Base):
"""资讯留言。"""
__tablename__ = "content_comments"
id: Mapped[str] = mapped_column(String, primary_key=True)
content_id: Mapped[str] = mapped_column(String, default="", index=True)
user_id: Mapped[str] = mapped_column(String, default="")
username: Mapped[str] = mapped_column(String, default="")
nickname: Mapped[str] = mapped_column(String, default="")
avatar: Mapped[str] = mapped_column(String, default="")
content: Mapped[str] = mapped_column(Text, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class SystemConfig(Base):
"""平台系统配置(键值)。"""
__tablename__ = "system_configs"
key: Mapped[str] = mapped_column(String, primary_key=True)
value: Mapped[str] = mapped_column(String, default="")
description: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class PortalDashboard(Base):
"""端口工作台聚合数据(按端口存 JSON 载荷,全部由服务端提供)。"""
__tablename__ = "portal_dashboards"
port: Mapped[str] = mapped_column(String, primary_key=True)
payload: Mapped[str] = mapped_column(Text, default="{}")
updated_at: Mapped[str] = mapped_column(String, default="")
class PortalPage(Base):
"""端口子页面数据(按 端口+页面 存 JSON 载荷,全部由服务端提供)。"""
__tablename__ = "portal_pages"
port: Mapped[str] = mapped_column(String, primary_key=True)
page: Mapped[str] = mapped_column(String, primary_key=True)
payload: Mapped[str] = mapped_column(Text, default="{}")
updated_at: Mapped[str] = mapped_column(String, default="")
# ── 投资人端(投融资 · 路演 · 培训)──────────────────────────────────────
class InvestorPreference(Base):
"""投资人投资方向偏好。"""
__tablename__ = "investor_preferences"
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
)
industries: Mapped[str] = mapped_column(String, default="[]") # JSON list
stage: Mapped[str] = mapped_column(String, default="") # seed/angel/series_a/...
amount_min: Mapped[int] = mapped_column(Integer, default=0)
amount_max: Mapped[int] = mapped_column(Integer, default=0)
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
updated_at: Mapped[str] = mapped_column(String, default="")
class Roadshow(Base):
"""投融资路演活动(线上/线下/混合),支持按发布主体与范围审核。"""
__tablename__ = "roadshows"
id: Mapped[str] = mapped_column(String, primary_key=True)
publisher_id: Mapped[str] = mapped_column(String, default="")
publisher_role: Mapped[str] = mapped_column(String, default="investor") # investor/government/operator/carrier/enterprise
title: Mapped[str] = mapped_column(String, default="")
summary: Mapped[str] = mapped_column(String, default="")
activity_type: Mapped[str] = mapped_column(String, default="online") # online/offline/hybrid
scope_type: Mapped[str] = mapped_column(String, default="all") # all/region/org
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
start_at: Mapped[str] = mapped_column(String, default="")
end_at: Mapped[str] = mapped_column(String, default="")
register_deadline: Mapped[str] = mapped_column(String, default="")
quota: Mapped[int] = mapped_column(Integer, default=0)
venue: Mapped[str] = mapped_column(String, default="") # 线下地点/直播间
live_url: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="draft") # draft/submitted/reviewing/published/registering/ongoing/ended/archived/rejected/cancelled
review_comment: Mapped[str] = mapped_column(String, default="")
need_review: Mapped[bool] = mapped_column(Boolean, default=True)
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class RoadshowRegistration(Base):
"""路演活动报名(项目方/投资人)。"""
__tablename__ = "roadshow_registrations"
id: Mapped[str] = mapped_column(String, primary_key=True)
roadshow_id: Mapped[str] = mapped_column(
ForeignKey("roadshows.id", ondelete="CASCADE"), nullable=False,
)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
role: Mapped[str] = mapped_column(String, default="investor") # investor/project
status: Mapped[str] = mapped_column(String, default="applying") # applying/approved/attended/absent
note: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class InvestmentIntent(Base):
"""投资意向/约谈/尽调。"""
__tablename__ = "investment_intents"
id: Mapped[str] = mapped_column(String, primary_key=True)
investor_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
project_id: Mapped[str] = mapped_column(String, default="")
project_name: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="interested") # interested/contacted/meeting/term_sheet/invested/declined
message: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class Bid(Base):
"""任务竞标(企业端竞标模式发标)。"""
__tablename__ = "bids"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
)
opc_id: Mapped[str] = mapped_column(String, default="")
opc_name: Mapped[str] = mapped_column(String, default="")
quote: Mapped[int] = mapped_column(Integer, default=0)
plan: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="submitted") # submitted/win/lost
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class SubsidyApplication(Base):
"""补贴申报(政务三级审批:区县→市→省→发放)。"""
__tablename__ = "subsidy_applications"
id: Mapped[str] = mapped_column(String, primary_key=True)
opc_id: Mapped[str] = mapped_column(String, default="")
opc_name: Mapped[str] = mapped_column(String, default="")
title: Mapped[str] = mapped_column(String, default="")
amount: Mapped[int] = mapped_column(Integer, default=0)
region_id: Mapped[str | None] = mapped_column(ForeignKey("regions.id"), nullable=True)
status: Mapped[str] = mapped_column(String, default="applying") # applying/district_review/city_review/province_review/approved/paid/rejected
comment: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ServiceReferral(Base):
"""载体-服务商引荐(三方绑定:载体引荐服务商→服务园区内 OPC)。"""
__tablename__ = "service_referrals"
id: Mapped[str] = mapped_column(String, primary_key=True)
carrier_id: Mapped[str] = mapped_column(String, default="")
provider_id: Mapped[str] = mapped_column(String, default="")
provider_name: Mapped[str] = mapped_column(String, default="")
opc_id: Mapped[str] = mapped_column(String, default="")
opc_name: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="referred") # referred/accepted/completed/declined
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class TrainingEnrollment(Base):
"""投融资培训报名/证书。"""
__tablename__ = "training_enrollments"
id: Mapped[str] = mapped_column(String, primary_key=True)
training_id: Mapped[str] = mapped_column(String, default="")
training_name: Mapped[str] = mapped_column(String, default="")
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
status: Mapped[str] = mapped_column(String, default="applying") # applying/enrolled/completed/certificate
created_at: Mapped[str] = mapped_column(String, default="")
# ── 横切能力:结算/合同/争议/评价/通知 ────────────────────────────────────
class Escrow(Base):
"""任务资金托管/结算。"""
__tablename__ = "escrows"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
)
task_title: Mapped[str] = mapped_column(String, default="")
amount: Mapped[int] = mapped_column(Integer, default=0)
commission: Mapped[int] = mapped_column(Integer, default=0) # 平台佣金
status: Mapped[str] = mapped_column(String, default="deposited") # deposited/frozen/released/refunded
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class Contract(Base):
"""任务电子合同。"""
__tablename__ = "contracts"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
)
task_title: Mapped[str] = mapped_column(String, default="")
enterprise_id: Mapped[str] = mapped_column(String, default="")
opc_id: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="signed") # draft/signed/terminated
content: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Dispute(Base):
"""任务争议。"""
__tablename__ = "disputes"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
)
task_title: Mapped[str] = mapped_column(String, default="")
initiator: Mapped[str] = mapped_column(String, default="")
reason: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="opened") # opened/mediating/resolved/closed
resolution: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Rating(Base):
"""任务互评。"""
__tablename__ = "ratings"
id: Mapped[str] = mapped_column(String, primary_key=True)
task_id: Mapped[str] = mapped_column(
ForeignKey("tasks.id", ondelete="CASCADE"), nullable=False,
)
from_id: Mapped[str] = mapped_column(String, default="")
to_id: Mapped[str] = mapped_column(String, default="")
score: Mapped[int] = mapped_column(Integer, default=5) # 1..5
comment: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Notification(Base):
"""站内通知。"""
__tablename__ = "notifications"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
type: Mapped[str] = mapped_column(String, default="system") # task/policy/order/subsidy/system
title: Mapped[str] = mapped_column(String, default="")
content: Mapped[str] = mapped_column(String, default="")
read: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[str] = mapped_column(String, default="")
# ── OPC 超级个体业务模型(工作台/我的任务/财务/消息)────────────────────
class OpcProfile(Base):
"""OPC 超级个体档案(信用评分等)。"""
__tablename__ = "opc_profiles"
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), primary_key=True,
)
credit_score: Mapped[int] = mapped_column(Integer, default=80)
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class FinanceRecord(Base):
"""OPC 财务流水(收入/支出)。"""
__tablename__ = "finance_records"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
category: Mapped[str] = mapped_column(String, default="income") # income | expense
amount: Mapped[int] = mapped_column(Integer, default=0)
date: Mapped[str] = mapped_column(String, default="") # YYYY-MM-DD
note: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class Message(Base):
"""OPC 站内消息。"""
__tablename__ = "messages"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
msg_type: Mapped[str] = mapped_column(String, default="system") # task/policy/service/agent/system
title: Mapped[str] = mapped_column(String, default="")
content: Mapped[str] = mapped_column(String, default="")
read: Mapped[bool] = mapped_column(Boolean, default=False)
created_at: Mapped[str] = mapped_column(String, default="")
class OpcTask(Base):
"""OPC 个人任务看板(「我的任务」:进行中/已完成/紧急)。"""
__tablename__ = "opc_tasks"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(
ForeignKey("users.id", ondelete="CASCADE"), nullable=False,
)
title: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="in_progress") # in_progress/completed/urgent
budget: Mapped[int] = mapped_column(Integer, default=0)
deadline: Mapped[str] = mapped_column(String, default="")
progress: Mapped[int] = mapped_column(Integer, default=0)
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
# ===========================================================================
# 培训业务子应用(原 app/training 独立 opc.db → 并入唯一总库)
# ===========================================================================
class TrainingAccount(Base):
"""培训站账号(原 accounts,含手机/微信登录)。"""
__tablename__ = "accounts"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
username: Mapped[str | None] = mapped_column(String, unique=True, nullable=False)
wxid: Mapped[str | None] = mapped_column(String, default="")
phone: Mapped[str | None] = mapped_column(String, default="")
contact: Mapped[str | None] = mapped_column(String, default="")
name: Mapped[str | None] = mapped_column(String, default="")
avatar: Mapped[str | None] = mapped_column(String, default="")
password: Mapped[str | None] = mapped_column(String, default="")
phone_bound: Mapped[int | None] = mapped_column(Integer, default=0)
identities: Mapped[str | None] = mapped_column(Text, default="[]")
status_label: Mapped[str | None] = mapped_column(String, default="")
topics: Mapped[str | None] = mapped_column(Text, default="")
source: Mapped[str | None] = mapped_column(String, default="")
created_at: Mapped[str | None] = mapped_column(String, default="")
class Event(Base):
__tablename__ = "events"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
type: Mapped[str | None] = mapped_column(String, default="")
mode: Mapped[str | None] = mapped_column(String, default="offline")
title: Mapped[str | None] = mapped_column(String, default="")
subtitle: Mapped[str | None] = mapped_column(String, default="")
desc: Mapped[str | None] = mapped_column(Text, default="")
location: Mapped[str | None] = mapped_column(String, default="")
host: Mapped[str | None] = mapped_column(String, default="")
image: Mapped[str | None] = mapped_column(String, default="")
link: Mapped[str | None] = mapped_column(String, default="")
start_at: Mapped[str | None] = mapped_column(String, default="")
end_at: Mapped[str | None] = mapped_column(String, default="")
checkin_at: Mapped[str | None] = mapped_column(String, default="")
duration_min: Mapped[int | None] = mapped_column(Integer, default=90)
capacity: Mapped[int | None] = mapped_column(Integer, default=0)
show_capacity: Mapped[int | None] = mapped_column(Integer, default=0)
audit_mode: Mapped[str | None] = mapped_column(String, default="auto")
status: Mapped[str | None] = mapped_column(String, default="open")
class Booking(Base):
__tablename__ = "bookings"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
created_at: Mapped[str | None] = mapped_column(String, default="")
status: Mapped[str | None] = mapped_column(String, default="pending")
audit_status: Mapped[str | None] = mapped_column(String, default="pending")
username: Mapped[str | None] = mapped_column(String, default="")
name: Mapped[str | None] = mapped_column(String, default="")
contact: Mapped[str | None] = mapped_column(String, default="")
status_label: Mapped[str | None] = mapped_column(String, default="")
want: Mapped[str | None] = mapped_column(Text, default="")
event_id: Mapped[str | None] = mapped_column(String, default="")
event_title: Mapped[str | None] = mapped_column(String, default="")
event_start: Mapped[str | None] = mapped_column(String, default="")
topics: Mapped[str | None] = mapped_column(Text, default="")
question: Mapped[str | None] = mapped_column(Text, default="")
source: Mapped[str | None] = mapped_column(String, default="")
checkin_at: Mapped[str | None] = mapped_column(String, default="")
class Test(Base):
__tablename__ = "tests"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
created_at: Mapped[str | None] = mapped_column(String, default="")
username: Mapped[str | None] = mapped_column(String, default="")
type_code: Mapped[str | None] = mapped_column(String, default="")
persona: Mapped[str | None] = mapped_column(String, default="")
adapt_index: Mapped[int | None] = mapped_column(Integer, default=0)
adapt_level: Mapped[str | None] = mapped_column(String, default="")
tracks: Mapped[str | None] = mapped_column(Text, default="")
version: Mapped[str | None] = mapped_column(String, default="")
class Course(Base):
__tablename__ = "courses"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
category: Mapped[str | None] = mapped_column(String, default="")
level: Mapped[str | None] = mapped_column(String, default="")
title: Mapped[str | None] = mapped_column(String, default="")
subtitle: Mapped[str | None] = mapped_column(String, default="")
desc: Mapped[str | None] = mapped_column(Text, default="")
price: Mapped[float | None] = mapped_column(Float, default=0.0)
status: Mapped[str | None] = mapped_column(String, default="draft")
start_at: Mapped[str | None] = mapped_column(String, default="")
end_at: Mapped[str | None] = mapped_column(String, default="")
venue: Mapped[str | None] = mapped_column(String, default="")
quota: Mapped[int | None] = mapped_column(Integer, default=0)
image: Mapped[str | None] = mapped_column(String, default="")
host: Mapped[str | None] = mapped_column(String, default="")
created_at: Mapped[str | None] = mapped_column(String, default="")
class PolicyLog(Base):
__tablename__ = "policy_logs"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
created_at: Mapped[str | None] = mapped_column(String, default="")
username: Mapped[str | None] = mapped_column(String, default="")
answers: Mapped[str | None] = mapped_column(Text, default="")
policies_count: Mapped[int | None] = mapped_column(Integer, default=0)
subsidies_count: Mapped[int | None] = mapped_column(Integer, default=0)
loans_count: Mapped[int | None] = mapped_column(Integer, default=0)
summary: Mapped[str | None] = mapped_column(Text, default="")
class PlanLog(Base):
__tablename__ = "plan_logs"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
created_at: Mapped[str | None] = mapped_column(String, default="")
username: Mapped[str | None] = mapped_column(String, default="")
region: Mapped[str | None] = mapped_column(String, default="")
status: Mapped[str | None] = mapped_column(String, default="")
need_park: Mapped[int | None] = mapped_column(Integer, default=0)
has_staff: Mapped[int | None] = mapped_column(Integer, default=0)
steps_count: Mapped[int | None] = mapped_column(Integer, default=0)
class SurveyLog(Base):
__tablename__ = "survey_logs"
id: Mapped[str | None] = mapped_column(String, primary_key=True)
created_at: Mapped[str | None] = mapped_column(String, default="")
username: Mapped[str | None] = mapped_column(String, default="")
source: Mapped[str | None] = mapped_column(String, default="")
answers: Mapped[str | None] = mapped_column(Text, default="")
# ===========================================================================
# 园区子应用(原 app/park 独立 park.db → 并入唯一总库)
# ===========================================================================
class ParkTenant(Base):
__tablename__ = "park_tenants"
id: Mapped[str] = mapped_column(String, primary_key=True)
name: Mapped[str] = mapped_column(String, default="")
intro_json: Mapped[str] = mapped_column(Text, default="[]")
username: Mapped[str] = mapped_column(String, default="")
salt: Mapped[str] = mapped_column(String, default="")
password_hash: Mapped[str] = mapped_column(String, default="")
admin_username: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="active")
data_json: Mapped[str] = mapped_column(Text, default="{}")
agent_json: Mapped[str] = mapped_column(Text, default="{}")
operator_user_id: Mapped[str] = mapped_column(String, default="") # 园区归属载体账号,园区端据此只审本园区
created_at: Mapped[str] = mapped_column(String, default="")
class ParkCompany(Base):
__tablename__ = "park_companies"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
name: Mapped[str] = mapped_column(String, default="")
zone: Mapped[str] = mapped_column(String, default="")
room: Mapped[str] = mapped_column(String, default="")
industry: Mapped[str] = mapped_column(String, default="")
bio: Mapped[str] = mapped_column(Text, default="")
founder: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="applying")
employees: Mapped[int | None] = mapped_column(Integer, nullable=True)
# 企业丰富资料(参考入园申请表 §二 企业信息)
legal_person: Mapped[str] = mapped_column(String, default="") # 法定代表人
legal_phone: Mapped[str] = mapped_column(String, default="") # 法人联系电话
registered_capital: Mapped[str] = mapped_column(String, default="") # 注册资本(万元)
company_type: Mapped[str] = mapped_column(String, default="") # 企业类型/性质
honors: Mapped[str] = mapped_column(Text, default="") # 所获政策/荣誉
address: Mapped[str] = mapped_column(String, default="") # 企业地址
contact_phone: Mapped[str] = mapped_column(String, default="") # 企业联系人电话
founded_at: Mapped[str] = mapped_column(String, default="") # 成立时间
emp_total: Mapped[int | None] = mapped_column(Integer, nullable=True) # 职工总数
emp_grad: Mapped[int | None] = mapped_column(Integer, nullable=True) # 毕业大学生
emp_layoff: Mapped[int | None] = mapped_column(Integer, nullable=True) # 失业人员
emp_veteran: Mapped[int | None] = mapped_column(Integer, nullable=True) # 退役军人
emp_migrant: Mapped[int | None] = mapped_column(Integer, nullable=True) # 返乡农民工
# 企业算力(只增不减):折扣% off 模型价;配额为发放给成员的算力额度
compute_discount: Mapped[int] = mapped_column(Integer, default=0) # 折扣%0-100,单调非降)
compute_quota: Mapped[int] = mapped_column(Integer, default=0) # 企业算力配额(单调非降/增量)
compute_quota_used: Mapped[int] = mapped_column(Integer, default=0) # 已分配/已用配额(统计)
engine_group: Mapped[str] = mapped_column(String, default="") # 引擎用户组名(折扣倍率载体)
owner_user_id: Mapped[str] = mapped_column(String, default="") # 负责人/管理员账号id(必填)
created_at: Mapped[str] = mapped_column(String, default="")
class ParkKbDoc(Base):
__tablename__ = "park_kb_docs"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=False, index=True)
grp: Mapped[str] = mapped_column(String, default="general")
title: Mapped[str] = mapped_column(String, default="")
content_md: Mapped[str] = mapped_column(Text, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class ParkSetting(Base):
"""园区全局配置 kv(如视频识别开关/地址),admin 经 /park/admin/* 读写,运行时不建表/不灌种子。"""
__tablename__ = "park_settings"
key: Mapped[str] = mapped_column(String, primary_key=True)
value: Mapped[str] = mapped_column(Text, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ParkAdmission(Base):
"""园区入驻申请(C端 小程序/网页提交,园区/运营端审核)。
表单字段以 JSON 存入 form_json(申请人/企业/项目/入驻需求),
上传资料 URL 存 docs_json(创业计划书/身份证/学历/执照/资质等)。
"""
__tablename__ = "park_admissions"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str] = mapped_column(String, default="") # 所选园区 id
tenant_name: Mapped[str] = mapped_column(String, default="") # 冗余园区名(展示)
user_id: Mapped[str] = mapped_column(String, default="", index=True) # 申请人平台用户 id
username: Mapped[str] = mapped_column(String, default="") # 申请人登录名
applicant_name: Mapped[str] = mapped_column(String, default="") # 申请人姓名(快速列表展示)
contact_phone: Mapped[str] = mapped_column(String, default="") # 联系电话(列表展示)
status: Mapped[str] = mapped_column(String, default="pending") # pending/reviewing/approved/rejected
form_json: Mapped[str] = mapped_column(Text, default="{}") # 结构化表单(申请人/企业/项目/需求)
docs_json: Mapped[str] = mapped_column(Text, default="{}") # 上传资料 URL 集合
source: Mapped[str] = mapped_column(String, default="miniprogram") # miniprogram|web
review_comment: Mapped[str] = mapped_column(String, default="")
reviewed_by: Mapped[str] = mapped_column(String, default="")
reviewed_at: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ParkScreen(Base):
__tablename__ = "park_screens"
id: Mapped[str] = mapped_column(String, primary_key=True)
tenant_id: Mapped[str | None] = mapped_column(ForeignKey("park_tenants.id", ondelete="CASCADE"), nullable=True, index=True)
device_id: Mapped[str] = mapped_column(String, default="", index=True)
name: Mapped[str] = mapped_column(String, default="")
role: Mapped[str] = mapped_column(String, default="main")
location: Mapped[str] = mapped_column(String, default="")
status: Mapped[str] = mapped_column(String, default="unbound") # unbound | bound
code: Mapped[str] = mapped_column(String, default="") # 待绑定连接码
code_expires: Mapped[str] = mapped_column(String, default="") # 码过期时间(ISO)
bound_at: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
class OpcCertification(Base):
"""OPC 认证申请表(用户提交资料 → 运营方审核)。"""
__tablename__ = "opc_certifications"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(String, default="", index=True)
username: Mapped[str] = mapped_column(String, default="")
real_name: Mapped[str] = mapped_column(String, default="")
gender: Mapped[str] = mapped_column(String, default="")
address: Mapped[str] = mapped_column(String, default="")
industry: Mapped[str] = mapped_column(String, default="")
ability: Mapped[str] = mapped_column(Text, default="")
phone: Mapped[str] = mapped_column(String, default="")
docs_json: Mapped[str] = mapped_column(Text, default="{}")
status: Mapped[str] = mapped_column(String, default="pending")
review_comment: Mapped[str] = mapped_column(String, default="")
reviewed_by: Mapped[str] = mapped_column(String, default="")
reviewed_at: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")
class ParkTransfer(Base):
"""OPC 转园申请表(园区 OPC 发起 → 园区/平台审核)。"""
__tablename__ = "park_transfers"
id: Mapped[str] = mapped_column(String, primary_key=True)
user_id: Mapped[str] = mapped_column(String, default="", index=True)
username: Mapped[str] = mapped_column(String, default="")
from_park_id: Mapped[str] = mapped_column(String, default="")
from_park_name: Mapped[str] = mapped_column(String, default="")
to_park_id: Mapped[str] = mapped_column(String, default="")
to_park_name: Mapped[str] = mapped_column(String, default="")
reason: Mapped[str] = mapped_column(Text, default="")
status: Mapped[str] = mapped_column(String, default="pending")
review_comment: Mapped[str] = mapped_column(String, default="")
reviewed_by: Mapped[str] = mapped_column(String, default="")
reviewed_at: Mapped[str] = mapped_column(String, default="")
created_at: Mapped[str] = mapped_column(String, default="")
updated_at: Mapped[str] = mapped_column(String, default="")