feat: 合并 Docker Compose、标注表格优化与部署文档
将 platform + CVAT 合并为单文件 docker-compose.yml,完善 .env 与 init/dev_up 脚本; 新增 docs/DEPLOY.md 与更新 README 以支持新机器部署;含数据湖示例、车队地图、 紧凑表格 UI、ADAS det_7cls 路径与批次台账等近期改动。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -28,7 +28,7 @@ ROLE_DEFS: dict[str, tuple[str, list[str]]] = {
|
||||
]),
|
||||
"engineer": ("算法工程师", [
|
||||
"read:catalog", "read:pending", "read:jobs", "read:audit", "read:fleet", "write:fleet",
|
||||
"write:approval_submit", "write:delivery_submit", "read:deliveries",
|
||||
"write:approval_submit", "write:approval_review", "write:delivery_submit", "read:deliveries",
|
||||
"write:labeling_vendor", "write:labeling_assign",
|
||||
]),
|
||||
"labeler": ("标注协调", [
|
||||
@@ -79,6 +79,7 @@ def init_database() -> None:
|
||||
_ensure_feishu_bitable_columns(db)
|
||||
_ensure_approval_columns(db)
|
||||
_ensure_operation_log_columns(db)
|
||||
_ensure_batch_index_columns(db)
|
||||
_seed_roles_permissions(db)
|
||||
_seed_fleet_demo(db)
|
||||
_import_jsonl_if_empty(db)
|
||||
@@ -168,18 +169,22 @@ def _import_jsonl_if_empty(db: Session) -> None:
|
||||
|
||||
|
||||
def assign_default_role(db: Session, user: User) -> None:
|
||||
"""新用户默认角色;支持 open_id / 部门白名单自动 admin。"""
|
||||
"""新用户默认角色;白名单用户每次登录也会补齐 admin。"""
|
||||
admin_role = db.query(Role).filter_by(code="admin").first()
|
||||
user_dept_ids = set(user.feishu_department_ids())
|
||||
if user.feishu_open_id and user.feishu_open_id in FEISHU_ADMIN_OPEN_IDS:
|
||||
role_code = "admin"
|
||||
elif user_dept_ids and user_dept_ids.intersection(FEISHU_ADMIN_DEPARTMENT_IDS):
|
||||
role_code = "admin"
|
||||
elif not user.roles:
|
||||
role_code = "engineer"
|
||||
else:
|
||||
if admin_role and admin_role not in user.roles:
|
||||
user.roles.append(admin_role)
|
||||
return
|
||||
if user_dept_ids and user_dept_ids.intersection(FEISHU_ADMIN_DEPARTMENT_IDS):
|
||||
if admin_role and admin_role not in user.roles:
|
||||
user.roles.append(admin_role)
|
||||
return
|
||||
if user.roles:
|
||||
return
|
||||
role_code = "engineer"
|
||||
role = db.query(Role).filter_by(code=role_code).first()
|
||||
if role and role not in user.roles:
|
||||
if role:
|
||||
user.roles.append(role)
|
||||
|
||||
|
||||
@@ -325,6 +330,10 @@ def _ensure_approval_columns(db: Session) -> None:
|
||||
_ensure_table_columns(db, "approvals", {"rejection_category": "VARCHAR(32) DEFAULT ''"})
|
||||
|
||||
|
||||
def _ensure_batch_index_columns(db: Session) -> None:
|
||||
_ensure_table_columns(db, "batch_index", {"archived": "BOOLEAN DEFAULT FALSE"})
|
||||
|
||||
|
||||
def _ensure_operation_log_columns(db: Session) -> None:
|
||||
"""确保 operation_logs 表存在并包含所有列。"""
|
||||
inspector_args = {}
|
||||
|
||||
@@ -319,6 +319,67 @@ class BatchDelivery(Base):
|
||||
}
|
||||
|
||||
|
||||
class BatchIndex(Base):
|
||||
"""批次列表索引:由扫盘/登记/阶段变更写入,列表 API 只读此表。"""
|
||||
|
||||
__tablename__ = "batch_index"
|
||||
|
||||
campaign_id = Column(String(64), primary_key=True)
|
||||
project = Column(String(32), nullable=False, index=True)
|
||||
task = Column(String(64), nullable=True, index=True)
|
||||
mode = Column(String(64), nullable=True)
|
||||
batch = Column(String(128), nullable=False, index=True)
|
||||
pack = Column(String(64), nullable=True)
|
||||
location = Column(String(32), nullable=False, default="inbox")
|
||||
stage = Column(String(32), nullable=False, index=True)
|
||||
batch_path = Column(String(1024), nullable=True)
|
||||
scope_key = Column(String(128), nullable=True)
|
||||
engineer = Column(String(128), nullable=True)
|
||||
format = Column(String(32), nullable=True)
|
||||
image_count = Column(Integer, nullable=False, default=0)
|
||||
label_count = Column(Integer, nullable=False, default=0)
|
||||
has_meta = Column(Boolean, nullable=False, default=False)
|
||||
registry_only = Column(Boolean, nullable=False, default=False)
|
||||
next_cli = Column(String(512), nullable=True)
|
||||
domain = Column(String(32), nullable=True)
|
||||
domain_label = Column(String(64), nullable=True)
|
||||
task_label = Column(String(128), nullable=True)
|
||||
mode_label = Column(String(128), nullable=True)
|
||||
labeling_profile = Column(String(128), nullable=True)
|
||||
export_default = Column(String(128), nullable=True)
|
||||
ml_adapter = Column(String(128), nullable=True)
|
||||
indexed_at = Column(DateTime(timezone=True), nullable=False)
|
||||
archived = Column(Boolean, nullable=False, default=False, index=True)
|
||||
|
||||
def to_list_row(self) -> dict:
|
||||
return {
|
||||
"project": self.project,
|
||||
"task": self.task,
|
||||
"mode": self.mode,
|
||||
"batch": self.batch,
|
||||
"pack": self.pack,
|
||||
"stage": self.stage,
|
||||
"location": self.location,
|
||||
"path": self.batch_path,
|
||||
"engineer": self.engineer,
|
||||
"format": self.format,
|
||||
"counts": {"images": self.image_count, "labels": self.label_count},
|
||||
"has_meta": self.has_meta,
|
||||
"next_cli": self.next_cli,
|
||||
"scope_key": self.scope_key,
|
||||
"domain": self.domain,
|
||||
"domain_label": self.domain_label,
|
||||
"task_label": self.task_label,
|
||||
"mode_label": self.mode_label,
|
||||
"labeling_profile": self.labeling_profile,
|
||||
"export_default": self.export_default,
|
||||
"ml_adapter": self.ml_adapter,
|
||||
"campaign_id": self.campaign_id,
|
||||
"registry_only": self.registry_only,
|
||||
"indexed_at": self.indexed_at.isoformat() if self.indexed_at else None,
|
||||
}
|
||||
|
||||
|
||||
class FeishuBitableLink(Base):
|
||||
"""HSAP 批次与飞书多维表格行的对应关系。"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user