1038 lines
56 KiB
Python
1038 lines
56 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""幂等种子数据:角色 / 权限 / 角色权限矩阵 / 区域 / 组织 / 演示用户。
|
||
|
||
在 ``app.db.init_db()`` 之后调用;仅当 ``roles`` 表为空时才写入,
|
||
避免覆盖已有数据。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
|
||
from sqlalchemy import select
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
||
from .models import (
|
||
AuditLog,
|
||
ContentItem,
|
||
FinanceRecord,
|
||
InvestmentIntent,
|
||
InvestorPreference,
|
||
Message,
|
||
Notification,
|
||
OpcProfile,
|
||
OpcTask,
|
||
Organization,
|
||
OrganizationMember,
|
||
Permission,
|
||
PortalDashboard,
|
||
PortalPage,
|
||
Region,
|
||
Roadshow,
|
||
RoadshowRegistration,
|
||
Role,
|
||
RolePermission,
|
||
ServiceProvider,
|
||
ServiceReferral,
|
||
SessionToken,
|
||
SubsidyApplication,
|
||
SystemConfig,
|
||
Task,
|
||
TaskCategory,
|
||
TrainingEnrollment,
|
||
User,
|
||
Agent,
|
||
)
|
||
from .repositories import AGENT_SEED, new_id, utcnow_iso
|
||
from .security import hash_password
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 角色
|
||
# ---------------------------------------------------------------------------
|
||
ROLES = [
|
||
# 业务角色
|
||
("opc_member", "OPC超级个体", "business"),
|
||
("carrier", "创业载体(园区)", "business"),
|
||
("enterprise", "甲方企业", "business"),
|
||
("provider", "服务商", "business"),
|
||
("government", "政务端", "business"),
|
||
("operator", "平台运营方", "business"),
|
||
# 政务子级(继承 government 通用权限)
|
||
("government|gov_province", "省级政务", "government-level"),
|
||
("government|gov_city", "市级政务", "government-level"),
|
||
("government|gov_district", "区县级政务", "government-level"),
|
||
("government|gov_org_admin", "政务组织机构管理员", "government-level"),
|
||
("government|gov_op_account", "政务操作账号", "government-level"),
|
||
# 运营方内部子角色
|
||
("operator|op_super_admin", "超级管理员", "operator-internal"),
|
||
("operator|op_admin", "运营管理员", "operator-internal"),
|
||
("operator|op_customer_service", "客服管理员", "operator-internal"),
|
||
("operator|op_finance", "财务管理员", "operator-internal"),
|
||
("operator|op_analyst", "数据分析师", "operator-internal"),
|
||
("operator|op_techops", "技术运维", "operator-internal"),
|
||
# 企业 / 载体 / 服务商 / OPC 端口内子角色
|
||
("enterprise|admin", "企业管理员", "business"),
|
||
("enterprise|operator", "企业操作者", "business"),
|
||
("carrier|admin", "园区管理员", "business"),
|
||
("carrier|operator", "园区操作者", "business"),
|
||
("provider|admin", "服务商管理员", "business"),
|
||
("provider|operator", "服务商操作者", "business"),
|
||
("opc_member|certified", "认证OPC", "business"),
|
||
("opc_member|independent", "独立OPC", "business"),
|
||
# 投资人端口内子角色
|
||
("investor", "投资人", "business"),
|
||
("investor|org_director", "机构投资总监", "business"),
|
||
("investor|org_manager", "机构投资经理", "business"),
|
||
("investor|personal", "个人投资人", "business"),
|
||
# 开放平台端口内子角色
|
||
("developer", "开发者", "business"),
|
||
("developer|dev_individual", "个人开发者", "business"),
|
||
("developer|dev_org_admin", "机构开发者管理员", "business"),
|
||
("developer|dev_member", "开发者成员", "business"),
|
||
]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 权限
|
||
# ---------------------------------------------------------------------------
|
||
PERMISSIONS = [
|
||
# 各门户菜单
|
||
("menu:opc_dashboard", "OPC 门户", "menu", "opc"),
|
||
("menu:carrier_dashboard", "载体门户", "menu", "carrier"),
|
||
("menu:enterprise_dashboard", "企业门户", "menu", "enterprise"),
|
||
("menu:provider_dashboard", "服务商门户", "menu", "provider"),
|
||
("menu:government_dashboard", "政务门户", "menu", "government"),
|
||
("menu:operator_dashboard", "运营门户", "menu", "operator"),
|
||
("menu:investor_dashboard", "投资人门户", "menu", "investor"),
|
||
("menu:investor_projects", "投资人·项目库", "menu", "investor"),
|
||
("menu:investor_roadshow", "投资人·路演活动", "menu", "investor"),
|
||
("menu:investor_training", "投资人·投融资培训", "menu", "investor"),
|
||
("menu:developer_dashboard", "开发者门户", "menu", "developer"),
|
||
("menu:developer_apps", "开发者·我的应用", "menu", "developer"),
|
||
("menu:developer_plugins", "开发者·我的插件", "menu", "developer"),
|
||
("menu:developer_skills", "开发者·技能市场", "menu", "developer"),
|
||
# 管理菜单
|
||
("menu:admin_user_mgmt", "用户管理", "menu", "admin"),
|
||
("menu:admin_role_mgmt", "角色权限管理", "menu", "admin"),
|
||
("menu:gov_data", "政务数据", "menu", "government"),
|
||
("menu:audit", "审计日志", "menu", "audit"),
|
||
("menu:settlements", "结算台账", "menu", "operator"),
|
||
# 操作
|
||
("action:user.assign_role", "分配角色", "action", "admin"),
|
||
("action:user.disable", "禁用/启用用户", "action", "admin"),
|
||
("action:role.grant_perm", "配置角色权限", "action", "admin"),
|
||
("action:org.manage", "管理组织", "action", "org"),
|
||
("action:data.export", "数据导出", "action", "data"),
|
||
("action:audit.view", "查看审计", "action", "audit"),
|
||
("action:task.manage", "任务管理(建改)", "action", "operator"),
|
||
("action:provider.manage", "服务商管理(建改)", "action", "operator"),
|
||
("action:content.manage", "内容管理(建发)", "action", "operator"),
|
||
("action:config.manage", "系统配置(修改)", "action", "operator"),
|
||
("action:settlement.manage", "结算管理", "action", "operator"),
|
||
# 平台运营(operator)功能页
|
||
("menu:admin_courses", "课程管理", "menu", "admin"),
|
||
("menu:admin_activities", "活动管理", "menu", "admin"),
|
||
("menu:admin_bookings", "报名管理", "menu", "admin"),
|
||
("menu:admin_tests", "测评管理", "menu", "admin"),
|
||
("menu:admin_surveys", "调研结果", "menu", "admin"),
|
||
("menu:admin_policies", "政策结果", "menu", "admin"),
|
||
("menu:admin_plans", "流程启动", "menu", "admin"),
|
||
("menu:admin_compute", "算力管理", "menu", "admin"),
|
||
("menu:admin_content", "资讯管理", "menu", "admin"),
|
||
("menu:admin_content_review", "资讯审核", "menu", "admin"),
|
||
("menu:admin_tasks", "任务管理", "menu", "admin"),
|
||
("menu:admin_providers", "服务商管理", "menu", "admin"),
|
||
("menu:admin_config", "系统配置", "menu", "admin"),
|
||
("menu:admin_park", "平台园区", "menu", "admin"),
|
||
("menu:admin_park_screens", "屏幕绑定", "menu", "admin"),
|
||
("menu:opc_cert", "OPC认证", "menu", "admin"),
|
||
("menu:admission", "入驻审核", "menu", "admin"),
|
||
("menu:park_transfer", "转园审核", "menu", "admin"),
|
||
# 园区(carrier)工作台
|
||
("menu:park_screens", "屏幕管理", "menu", "carrier"),
|
||
("menu:park_screen", "大屏控制台", "menu", "carrier"),
|
||
("menu:park_companies", "企业管理", "menu", "carrier"),
|
||
("menu:park_users", "用户管理", "menu", "carrier"),
|
||
("menu:park_content", "资讯管理", "menu", "carrier"),
|
||
("menu:park_kb", "园区知识库", "menu", "carrier"),
|
||
("menu:park_agent", "园区智能体", "menu", "carrier"),
|
||
("menu:park_data", "大屏数据", "menu", "carrier"),
|
||
("menu:park_vision", "视频识别", "menu", "carrier"),
|
||
("menu:park_admissions", "入园申请", "menu", "carrier"),
|
||
("menu:park_transfers", "转园申请", "menu", "carrier"),
|
||
]
|
||
|
||
# role_id -> [permission_id]
|
||
ROLE_PERMISSIONS: dict[str, list[str]] = {
|
||
"opc_member": ["menu:opc_dashboard"],
|
||
"carrier": [
|
||
"menu:carrier_dashboard", "action:org.manage",
|
||
"menu:park_screens", "menu:park_screen", "menu:park_companies", "menu:park_users", "menu:park_content",
|
||
"menu:park_kb",
|
||
"menu:park_agent", "menu:park_data", "menu:park_vision",
|
||
"menu:park_admissions", "menu:park_transfers",
|
||
],
|
||
"enterprise": ["menu:enterprise_dashboard", "action:org.manage"],
|
||
"provider": [
|
||
"menu:provider_dashboard", "action:org.manage", "action:data.export",
|
||
],
|
||
"government": ["menu:government_dashboard", "menu:gov_data"],
|
||
"government|gov_province": ["action:data.export"],
|
||
"government|gov_city": ["action:data.export"],
|
||
"government|gov_district": ["action:data.export"],
|
||
"government|gov_org_admin": ["action:org.manage"],
|
||
"government|gov_op_account": ["action:data.export"],
|
||
"operator": [
|
||
"menu:operator_dashboard",
|
||
"menu:admin_user_mgmt", "menu:admin_role_mgmt", "menu:audit", "menu:settlements",
|
||
"menu:admin_courses", "menu:admin_activities", "menu:admin_bookings", "menu:admin_tests",
|
||
"menu:admin_surveys", "menu:admin_policies", "menu:admin_plans", "menu:admin_compute",
|
||
"menu:admin_content", "menu:admin_content_review", "menu:admin_tasks", "menu:admin_providers", "menu:admin_config",
|
||
"menu:admin_park", "menu:admin_park_screens", "menu:opc_cert", "menu:admission", "menu:park_transfer",
|
||
"action:user.assign_role", "action:user.disable", "action:role.grant_perm",
|
||
"action:org.manage", "action:data.export", "action:audit.view",
|
||
"action:task.manage", "action:provider.manage", "action:content.manage",
|
||
"action:config.manage", "action:settlement.manage",
|
||
],
|
||
"operator|op_super_admin": [
|
||
"menu:admin_user_mgmt", "menu:admin_role_mgmt", "menu:audit", "menu:settlements",
|
||
"action:user.assign_role", "action:user.disable", "action:role.grant_perm",
|
||
"action:org.manage", "action:data.export", "action:audit.view",
|
||
"action:task.manage", "action:provider.manage", "action:content.manage",
|
||
"action:config.manage", "action:settlement.manage",
|
||
],
|
||
"operator|op_admin": [
|
||
"menu:admin_user_mgmt", "menu:admin_role_mgmt", "menu:audit", "menu:settlements",
|
||
"action:user.assign_role", "action:user.disable",
|
||
"action:org.manage", "action:data.export", "action:audit.view",
|
||
"action:task.manage", "action:provider.manage", "action:content.manage",
|
||
"action:config.manage", "action:settlement.manage",
|
||
],
|
||
"operator|op_customer_service": [
|
||
"action:data.export", "action:task.manage", "action:provider.manage",
|
||
"action:content.manage",
|
||
],
|
||
"operator|op_finance": [
|
||
"menu:settlements", "action:data.export", "action:settlement.manage",
|
||
],
|
||
"operator|op_analyst": ["menu:audit", "action:data.export", "action:audit.view"],
|
||
"operator|op_techops": [
|
||
"menu:admin_user_mgmt", "action:org.manage", "action:data.export",
|
||
"action:config.manage",
|
||
],
|
||
"enterprise|admin": ["menu:enterprise_dashboard", "action:org.manage"],
|
||
"enterprise|operator": ["menu:enterprise_dashboard"],
|
||
"carrier|admin": ["menu:carrier_dashboard", "action:org.manage"],
|
||
"carrier|operator": ["menu:carrier_dashboard"],
|
||
"provider|admin": [
|
||
"menu:provider_dashboard", "action:org.manage", "action:data.export",
|
||
],
|
||
"provider|operator": ["menu:provider_dashboard", "action:data.export"],
|
||
"opc_member|certified": ["menu:opc_dashboard"],
|
||
"opc_member|independent": ["menu:opc_dashboard"],
|
||
"investor": ["menu:investor_dashboard"],
|
||
"investor|org_director": [
|
||
"menu:investor_dashboard", "menu:investor_projects", "menu:investor_roadshow", "menu:investor_training",
|
||
"action:preference.manage", "action:project.view", "action:intent.manage",
|
||
"action:roadshow.publish", "action:roadshow.host", "action:invest.decide",
|
||
],
|
||
"investor|org_manager": [
|
||
"menu:investor_dashboard", "menu:investor_projects", "menu:investor_roadshow",
|
||
"action:preference.manage", "action:project.view", "action:intent.manage", "action:roadshow.attend",
|
||
],
|
||
"investor|personal": [
|
||
"menu:investor_dashboard", "menu:investor_projects", "menu:investor_roadshow", "menu:investor_training",
|
||
"action:preference.manage", "action:project.view", "action:intent.manage",
|
||
"action:roadshow.attend", "action:roadshow.register",
|
||
],
|
||
"developer": ["menu:developer_dashboard"],
|
||
"developer|dev_individual": [
|
||
"menu:developer_dashboard", "menu:developer_apps", "menu:developer_plugins", "menu:developer_skills",
|
||
"action:app.create", "action:app.publish", "action:plugin.create", "action:skill.publish",
|
||
],
|
||
"developer|dev_org_admin": [
|
||
"menu:developer_dashboard", "menu:developer_apps", "menu:developer_plugins", "menu:developer_skills",
|
||
"action:app.create", "action:app.publish", "action:app.manage", "action:plugin.create", "action:skill.publish", "action:apikey.manage",
|
||
],
|
||
"developer|dev_member": [
|
||
"menu:developer_dashboard", "menu:developer_apps",
|
||
"action:app.create",
|
||
],
|
||
}
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 区域(省/市/区县 示例树)
|
||
# ---------------------------------------------------------------------------
|
||
REGIONS = [
|
||
("r_prov_yn", "云南省", "province", None),
|
||
("r_city_km", "昆明市", "city", "r_prov_yn"),
|
||
("r_city_qj", "曲靖市", "city", "r_prov_yn"),
|
||
("r_dist_pl", "盘龙区", "district", "r_city_km"),
|
||
("r_dist_wh", "五华区", "district", "r_city_km"),
|
||
("r_dist_ql", "麒麟区", "district", "r_city_qj"),
|
||
]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 组织(甲方企业 / 创业载体 / 服务商)
|
||
# ---------------------------------------------------------------------------
|
||
ORGANIZATIONS = [
|
||
("o_ent_001", "云南某某甲方企业", "enterprise", "r_dist_pl", None),
|
||
("o_car_001", "滇池创业园", "carrier", "r_dist_wh", None),
|
||
("o_pro_001", "云超财税服务所", "provider", "r_city_km", None),
|
||
("o_ent_prov", "省级示范企业", "enterprise", "r_prov_yn", None),
|
||
]
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 演示用户(role/sub_role/org/region 各异,用于 RBAC 演示与测试)
|
||
# ---------------------------------------------------------------------------
|
||
DEMO_USERS = [
|
||
# id, username, nickname, password, role, sub_role, org_id, region_id
|
||
("u_demo_01", "pine", "云超服小助手", "123456", "operator", "op_super_admin", None, "r_prov_yn"),
|
||
("u_gov_prov", "gov_prov", "省政务账号", "123456", "government", "gov_province", None, "r_prov_yn"),
|
||
("u_gov_dist", "gov_dist", "区县政务账号", "123456", "government", "gov_district", None, "r_dist_wh"),
|
||
("u_ent_01", "ent01", "甲方企业账号", "123456", "enterprise", None, "o_ent_001", "r_dist_pl"),
|
||
("u_car_01", "car01", "园区运营账号", "123456", "carrier", None, "o_car_001", "r_dist_wh"),
|
||
("u_pro_01", "pro01", "服务商账号", "123456", "provider", None, "o_pro_001", "r_city_km"),
|
||
("u_op_an", "op_analyst", "运营数据分析", "123456", "operator", "op_analyst", None, "r_prov_yn"),
|
||
("u_op_admin", "op_admin", "运营管理员", "123456", "operator", "op_admin", None, "r_prov_yn"),
|
||
("u_op_cs", "op_cs", "运营客服", "123456", "operator", "op_customer_service", None, "r_prov_yn"),
|
||
("u_op_fin", "op_fin", "运营财务", "123456", "operator", "op_finance", None, "r_prov_yn"),
|
||
("u_op_tech", "op_tech", "运营运维", "123456", "operator", "op_techops", None, "r_prov_yn"),
|
||
("u_opc_01", "opc01", "OPC个人创业者", "123456", "opc_member", None, None, "r_dist_wh"),
|
||
("u_opc_02", "opc02", "OPC个体工商户", "123456", "opc_member", None, None, "r_dist_pl"),
|
||
("u_inv_01", "inv01", "投资人账号", "123456", "investor", "personal", None, "r_prov_yn"),
|
||
("u_inv_02", "inv02", "机构投资人", "123456", "investor", "org_director", None, "r_prov_yn"),
|
||
]
|
||
|
||
|
||
async def _add_agent(session: AsyncSession, seed: dict, user_id: str, port: str | None, now: str) -> None:
|
||
"""幂等播种单个智能体:SQLite INSERT OR IGNORE((id,user_id,port) 冲突跳过),杜绝 UNIQUE 抛错。"""
|
||
from sqlalchemy.dialects.sqlite import insert as sqlite_insert
|
||
port_val = port or "" # agents.port NOT NULL;无端口身份用 ""
|
||
stmt = sqlite_insert(Agent).values(
|
||
id=seed["id"], user_id=user_id, port=port_val, name=seed["name"],
|
||
description=seed["description"], language=seed.get("language", "zh"),
|
||
model_name=seed.get("model_name", ""), deletable=seed.get("deletable", True),
|
||
use_fixed_soul=seed.get("use_fixed_soul", False), created_at=now, updated_at=now,
|
||
).on_conflict_do_nothing(index_elements=["id", "user_id", "port"])
|
||
await session.execute(stmt)
|
||
|
||
|
||
async def seed_data(session: AsyncSession) -> None:
|
||
"""幂等种子:仅当 roles 表为空时写入全部基础数据;身份与 OPC 业务始终补种。"""
|
||
now = utcnow_iso()
|
||
existing = await session.scalar(select(Role.id).limit(1))
|
||
if existing is not None:
|
||
# 已初始化的库:仍补种 OPC 业务演示数据、账号身份与端口工作台(各自幂等)。
|
||
await _sync_permissions(session, now)
|
||
await _ensure_extra_demo_users(session, now)
|
||
await _seed_opc_business(session, now)
|
||
await _seed_task_categories(session, now)
|
||
await _seed_port_dashboards(session, now)
|
||
await _seed_market(session, now)
|
||
await _seed_port_pages(session, now)
|
||
await _seed_investor(session, now)
|
||
await _seed_ecosystem(session, now)
|
||
await _seed_org_members(session, now)
|
||
await session.commit()
|
||
return
|
||
|
||
session.add_all(
|
||
[Role(id=r[0], name=r[1], scope_type=r[2]) for r in ROLES]
|
||
)
|
||
session.add_all(
|
||
[
|
||
Permission(id=p[0], name=p[1], category=p[2], module=p[3])
|
||
for p in PERMISSIONS
|
||
]
|
||
)
|
||
for role_id, perms in ROLE_PERMISSIONS.items():
|
||
session.add_all(
|
||
[
|
||
RolePermission(role_id=role_id, permission_id=perm)
|
||
for perm in perms
|
||
]
|
||
)
|
||
session.add_all(
|
||
[
|
||
Region(id=r[0], name=r[1], level=r[2], parent_id=r[3], created_at=now)
|
||
for r in REGIONS
|
||
]
|
||
)
|
||
session.add_all(
|
||
[
|
||
Organization(
|
||
id=o[0], name=o[1], type=o[2], region_id=o[3],
|
||
parent_id=o[4], created_at=now,
|
||
)
|
||
for o in ORGANIZATIONS
|
||
]
|
||
)
|
||
|
||
for (uid, username, nickname, password, role, sub_role, org_id, region_id) in DEMO_USERS:
|
||
digest, salt = hash_password(password)
|
||
session.add(
|
||
User(
|
||
id=uid, username=username, nickname=nickname,
|
||
password_hash=digest, password_salt=salt,
|
||
role=role, sub_role=sub_role, org_id=org_id, region_id=region_id,
|
||
status="active", token_version=0, created_at=now, updated_at=now,
|
||
source="seed", auth_type="admin",
|
||
)
|
||
)
|
||
# 为每个用户播种默认 + QA 智能体(幂等按 (id,user_id,port=null) 防重)
|
||
for seed in AGENT_SEED:
|
||
await _add_agent(session, seed, uid, None, now)
|
||
|
||
await _seed_task_categories(session, now)
|
||
await _seed_operator_business(session, now)
|
||
await _seed_opc_business(session, now)
|
||
await _seed_port_dashboards(session, now)
|
||
await _seed_market(session, now)
|
||
await _seed_port_pages(session, now)
|
||
await _seed_investor(session, now)
|
||
await _seed_ecosystem(session, now)
|
||
await _seed_org_members(session, now)
|
||
await session.commit()
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 运营端业务演示数据(任务/服务商/内容/配置)
|
||
# ---------------------------------------------------------------------------
|
||
# 任务分类字典(顶层 35 类,取自 design/云超服平台/任务类别.json,幂等:表空才插)
|
||
_TASK_CATEGORY_NAMES = [
|
||
"平面设计", "移动端开发", "网站建设服务", "软件开发", "硬件开发", "知识产权",
|
||
"市场推广", "音视频", "动漫游戏设计", "UI设计", "工业设计与制造", "策划",
|
||
"写作和内容", "工程设计", "空间设计服务", "人力资源", "科技服务", "技术服务",
|
||
"AI人工智能", "VR/AR/MR", "翻译服务", "SaaS服务", "区块链", "企业后勤服务",
|
||
"企业办公服务", "文印广告", "法律服务", "工商财税", "学习培训", "源码交易",
|
||
"生产制造", "直播服务", "服装配饰设计", "摄影摄像服务", "数据服务",
|
||
]
|
||
|
||
|
||
async def _seed_task_categories(session: AsyncSession, now: str) -> None:
|
||
if await session.scalar(select(TaskCategory.id).limit(1)) is not None:
|
||
return
|
||
session.add_all([
|
||
TaskCategory(id=f"tc_{i:02d}", name=name, sort=i + 1, status="active")
|
||
for i, name in enumerate(_TASK_CATEGORY_NAMES)
|
||
])
|
||
await session.commit()
|
||
|
||
|
||
async def _seed_operator_business(session: AsyncSession, now: str) -> None:
|
||
if await session.scalar(select(Task.id).limit(1)) is not None:
|
||
return
|
||
session.add_all([
|
||
Task(id="task_001", task_code="TK-001-UI", title="电商小程序首页 UI 设计",
|
||
category="设计创意", category_id="tc_10", sub_category="UI设计",
|
||
description="为电商小程序设计首页 UI,含 5 个页面",
|
||
tags="UI,设计", mode="bid", budget_min=2000, budget_max=5000,
|
||
deadline="2026-09-01", delivery_days=7, headcount=3,
|
||
display_priority=10, published_at=now,
|
||
status="published", publisher_org_id="o_ent_001",
|
||
publisher_name="云南某某甲方企业", created_at=now, updated_at=now),
|
||
Task(id="task_002", task_code="TK-002-CT", title="品牌文案写作(月度)",
|
||
category="写作和内容", category_id="tc_13", sub_category="内容写作",
|
||
description="每月 8 篇品牌公众号文案", tags="文案,内容",
|
||
mode="assign", budget_min=3000, budget_max=6000,
|
||
deadline="2026-12-31", delivery_days=14, headcount=1,
|
||
display_priority=5, status="review", publisher_org_id="o_ent_001",
|
||
publisher_name="云南某某甲方企业", created_at=now, updated_at=now),
|
||
Task(id="task_003", task_code="TK-003-DEV", title="小程序前后端开发",
|
||
category="移动端开发", category_id="tc_02", sub_category="小程序开发",
|
||
description="点餐小程序全栈开发,3 期交付", tags="开发",
|
||
mode="bid", budget_min=30000, budget_max=60000,
|
||
deadline="2026-10-15", delivery_days=30, headcount=3,
|
||
display_priority=20, status="pending", publisher_org_id="o_ent_001",
|
||
publisher_name="云南某某甲方企业", created_at=now, updated_at=now),
|
||
Task(id="task_004", task_code="TK-004-GRAB", title="短视频剪辑(扫码即领·独占)",
|
||
category="音视频", category_id="tc_08", sub_category="视频剪辑",
|
||
description="为园区企业制作 3 条产品短视频,扫码即可接单,独占一人,2 周内交付。",
|
||
tags="短视频,剪辑", mode="grab", budget_min=1500, budget_max=3000,
|
||
deadline="2026-11-30", delivery_days=14, exclusive=True, headcount=1,
|
||
display_priority=30, published_at=now,
|
||
status="published", publisher_org_id="o_ent_001",
|
||
publisher_name="园区运营方", created_at=now, updated_at=now),
|
||
Task(id="task_005", task_code="TK-005-REC", title="农产品品牌 Logo 设计(推荐)",
|
||
category="平面设计", category_id="tc_01", sub_category="品牌设计",
|
||
description="为农产品品牌设计 Logo,推荐合适合伙人接单。",
|
||
tags="Logo,品牌设计", mode="recommend", budget_min=800, budget_max=2000,
|
||
deadline="2026-12-20", delivery_days=10, headcount=1,
|
||
display_priority=25, published_at=now,
|
||
status="published", publisher_org_id="o_ent_001",
|
||
publisher_name="园区运营方", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
ServiceProvider(id="prov_001", name="云超财税服务所", category="财税服务",
|
||
org_id="o_pro_001", level="gold", rating=4.8, order_count=320,
|
||
status="active", contact="service@yuncao.example", created_at=now, updated_at=now),
|
||
ServiceProvider(id="prov_002", name="滇峰法律咨询", category="法律服务",
|
||
org_id=None, level="premium", rating=4.6, order_count=150,
|
||
status="active", contact="law@dianfeng.example", created_at=now, updated_at=now),
|
||
ServiceProvider(id="prov_003", name="云岭工商代办", category="工商服务",
|
||
org_id=None, level="certified", rating=4.3, order_count=88,
|
||
status="pending", contact="biz@yunling.example", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
ContentItem(id="cont_001", type="policy", title="云南省一次性创业补贴政策",
|
||
summary="对首次创业且正常经营 1 年以上的 OPC 发放一次性创业补贴",
|
||
body="适用对象、申报条件、补贴标准、申报流程……", publisher_id="u_gov_prov",
|
||
status="published", created_at=now, updated_at=now),
|
||
ContentItem(id="cont_002", type="news", title="平台上线公告",
|
||
summary="云超服平台正式上线运营", body="欢迎入驻……", publisher_id="u_demo_01",
|
||
status="published", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
SystemConfig(key="platform.fee.task", value="0.05", description="任务佣金费率(5%)", updated_at=now),
|
||
SystemConfig(key="platform.fee.provider", value="0.15", description="服务商分成比例(15%)", updated_at=now),
|
||
])
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# OPC 超级个体业务演示数据(工作台聚合:档案/任务/财务/消息)
|
||
# ---------------------------------------------------------------------------
|
||
async def _seed_opc_business(session: AsyncSession, now: str) -> None:
|
||
"""OPC 个人工作台演示数据(按用户幂等)。"""
|
||
if await session.scalar(select(OpcProfile.user_id).limit(1)) is not None:
|
||
return
|
||
|
||
# 档案(信用评分)
|
||
session.add_all([
|
||
OpcProfile(user_id="u_opc_01", credit_score=88, created_at=now, updated_at=now),
|
||
OpcProfile(user_id="u_opc_02", credit_score=82, created_at=now, updated_at=now),
|
||
])
|
||
|
||
# 个人任务看板
|
||
session.add_all([
|
||
OpcTask(id="ot_001", user_id="u_opc_01", title="电商小程序首页 UI 设计",
|
||
status="in_progress", budget=4000, deadline="2026-08-20", progress=65,
|
||
created_at=now, updated_at=now),
|
||
OpcTask(id="ot_002", user_id="u_opc_01", title="品牌公众号月度文案",
|
||
status="urgent", budget=3000, deadline="2026-08-10", progress=30,
|
||
created_at=now, updated_at=now),
|
||
OpcTask(id="ot_003", user_id="u_opc_01", title="Logo 及 VI 视觉规范",
|
||
status="completed", budget=5000, deadline="2026-07-15", progress=100,
|
||
created_at=now, updated_at=now),
|
||
OpcTask(id="ot_004", user_id="u_opc_02", title="宣传视频剪辑",
|
||
status="in_progress", budget=2500, deadline="2026-08-28", progress=45,
|
||
created_at=now, updated_at=now),
|
||
])
|
||
|
||
# 财务流水(月度收入 + 少量支出)
|
||
session.add_all([
|
||
FinanceRecord(id="fin_001", user_id="u_opc_01", category="income", amount=3200,
|
||
date="2026-02-10", note="UI 设计项目款", created_at=now),
|
||
FinanceRecord(id="fin_002", user_id="u_opc_01", category="income", amount=4500,
|
||
date="2026-03-12", note="Logo 设计项目款", created_at=now),
|
||
FinanceRecord(id="fin_003", user_id="u_opc_01", category="income", amount=2800,
|
||
date="2026-04-08", note="文案代写项目款", created_at=now),
|
||
FinanceRecord(id="fin_004", user_id="u_opc_01", category="income", amount=5100,
|
||
date="2026-05-20", note="小程序 UI 项目款", created_at=now),
|
||
FinanceRecord(id="fin_005", user_id="u_opc_01", category="income", amount=3900,
|
||
date="2026-06-15", note="电商详情页设计", created_at=now),
|
||
FinanceRecord(id="fin_006", user_id="u_opc_01", category="income", amount=4600,
|
||
date="2026-07-18", note="H5 营销页设计", created_at=now),
|
||
FinanceRecord(id="fin_007", user_id="u_opc_01", category="expense", amount=600,
|
||
date="2026-07-02", note="素材版权购买", created_at=now),
|
||
])
|
||
|
||
# 站内消息
|
||
session.add_all([
|
||
Message(id="msg_001", user_id="u_opc_01", msg_type="policy",
|
||
title="政策匹配提醒", content="2 项新政策与您高度匹配,请及时查看申报",
|
||
read=False, created_at=now),
|
||
Message(id="msg_002", user_id="u_opc_01", msg_type="task",
|
||
title="任务状态更新", content="您参与的「电商小程序首页 UI 设计」进度已更新",
|
||
read=False, created_at=now),
|
||
Message(id="msg_003", user_id="u_opc_01", msg_type="service",
|
||
title="服务商回复", content="云超财税服务所已回复您的询价",
|
||
read=True, created_at=now),
|
||
Message(id="msg_004", user_id="u_opc_01", msg_type="agent",
|
||
title="智能体建议", content="您的月度收入较上月增长 18%",
|
||
read=True, created_at=now),
|
||
])
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 端口工作台聚合数据(企业/载体/服务商/政务)
|
||
# ---------------------------------------------------------------------------
|
||
_PORT_DASHBOARDS: dict[str, dict] = {
|
||
"enterprise": {
|
||
"stats": [
|
||
{"key": "postedTasks", "value": 56},
|
||
{"key": "activeTasks", "value": 12},
|
||
{"key": "completedTasks", "value": 38},
|
||
{"key": "totalSpent", "value": "¥32.0万"},
|
||
{"key": "matchedTalents", "value": 186},
|
||
{"key": "cooperationRate", "value": "92%"},
|
||
],
|
||
"list": [
|
||
{"title": "企业官网 UI 设计", "meta": "进行中 · ¥5000-8000 · 12 家投标", "status": "进行中"},
|
||
{"title": "小程序前端开发", "meta": "进行中 · ¥8000-15000 · 8 家投标", "status": "进行中"},
|
||
{"title": "农产品品牌 Logo 设计", "meta": "进行中 · ¥3000-5000 · 15 家投标", "status": "进行中"},
|
||
{"title": "商业计划书撰写", "meta": "进行中 · ¥2000-4000 · 6 家投标", "status": "进行中"},
|
||
],
|
||
},
|
||
"carrier": {
|
||
"stats": [
|
||
{"key": "residentOPCs", "value": 186},
|
||
{"key": "totalSpace", "value": "5000㎡"},
|
||
{"key": "usedSpace", "value": "4200㎡"},
|
||
{"key": "occupancyRate", "value": "84%"},
|
||
{"key": "serviceOrders", "value": 45},
|
||
{"key": "thisMonthNewOPC", "value": 12},
|
||
],
|
||
"list": [
|
||
{"title": "云创设计工作室", "meta": "入驻 · 电子信息方向 · 工位 12", "status": "已入驻"},
|
||
{"title": "滇峰数据科技", "meta": "入驻 · 软件服务方向 · 工位 8", "status": "已入驻"},
|
||
{"title": "云南新媒体中心", "meta": "待审批 · 内容创作方向 · 工位 6", "status": "待审批"},
|
||
{"title": "绿野农业电商", "meta": "入驻 · 电商方向 · 工位 10", "status": "已入驻"},
|
||
],
|
||
},
|
||
"provider": {
|
||
"stats": [
|
||
{"key": "activeServices", "value": 18},
|
||
{"key": "ongoingOrders", "value": 24},
|
||
{"key": "completedOrders", "value": 156},
|
||
{"key": "totalRevenue", "value": "¥52.6万"},
|
||
{"key": "thisMonthIncome", "value": "¥8.56万"},
|
||
{"key": "avgRating", "value": 4.7},
|
||
],
|
||
"list": [
|
||
{"title": "代理记账服务(月度)", "meta": "进行中 · 云南某某甲方企业 · ¥199/月", "status": "进行中"},
|
||
{"title": "公司注册代办", "meta": "待处理 · 个人创业者 · ¥599/次", "status": "待处理"},
|
||
{"title": "季度财务报表编制", "meta": "已完成 · 云创财税 · ¥2000-3000", "status": "已完成"},
|
||
{"title": "税务筹划咨询", "meta": "进行中 · 鼎信税务所 · ¥1999/次", "status": "进行中"},
|
||
],
|
||
},
|
||
"government": {
|
||
"stats": [
|
||
{"key": "totalOPC", "value": 45600},
|
||
{"key": "registeredCarriers", "value": 168},
|
||
{"key": "policiesPublished", "value": 245},
|
||
{"key": "policiesMatched", "value": 18200},
|
||
{"key": "tasksInRegion", "value": 12500},
|
||
{"key": "completionRate", "value": "78%"},
|
||
],
|
||
"list": [
|
||
{"region": "昆明市", "opcCount": 12500, "taskCount": 3200, "completionRate": "82%"},
|
||
{"region": "大理州", "opcCount": 6800, "taskCount": 1800, "completionRate": "76%"},
|
||
{"region": "曲靖市", "opcCount": 5200, "taskCount": 1500, "completionRate": "79%"},
|
||
{"region": "红河州", "opcCount": 4800, "taskCount": 1200, "completionRate": "74%"},
|
||
{"region": "玉溪市", "opcCount": 3500, "taskCount": 900, "completionRate": "81%"},
|
||
],
|
||
"chart": [
|
||
{"label": "1月", "value": 2400},
|
||
{"label": "2月", "value": 2800},
|
||
{"label": "3月", "value": 3100},
|
||
{"label": "4月", "value": 2900},
|
||
{"label": "5月", "value": 3450},
|
||
{"label": "6月", "value": 3820},
|
||
],
|
||
},
|
||
}
|
||
|
||
|
||
async def _seed_port_dashboards(session: AsyncSession, now: str) -> None:
|
||
"""按端口写入工作台 JSON 载荷(幂等:任一端口已存在则跳过)。"""
|
||
if await session.scalar(select(PortalDashboard.port).limit(1)) is not None:
|
||
return
|
||
session.add_all(
|
||
[
|
||
PortalDashboard(
|
||
port=port,
|
||
payload=json.dumps(payload, ensure_ascii=False),
|
||
updated_at=now,
|
||
)
|
||
for port, payload in _PORT_DASHBOARDS.items()
|
||
]
|
||
)
|
||
|
||
|
||
async def _seed_market(session: AsyncSession, now: str) -> None:
|
||
"""补充平台市场数据(任务广场/政策/服务商),幂等(以 task_mk_001 为标记)。"""
|
||
if await session.scalar(select(Task.id).where(Task.id == "task_mk_001").limit(1)) is not None:
|
||
return
|
||
session.add_all([
|
||
Task(id="task_mk_001", title="企业官网 UI 设计", category="设计创意", sub_category="UI设计",
|
||
description="为企业官网设计首页与 3 个内页 UI", mode="bid",
|
||
budget_min=5000, budget_max=8000, deadline="2026-09-10",
|
||
status="published", publisher_org_id="o_ent_001",
|
||
publisher_name="云南某某甲方企业", created_at=now, updated_at=now),
|
||
Task(id="task_mk_002", title="小程序前后端开发", category="技术开发", sub_category="小程序开发",
|
||
description="点餐小程序全栈开发,3 期交付", mode="bid",
|
||
budget_min=30000, budget_max=60000, deadline="2026-10-15",
|
||
status="published", publisher_org_id="o_ent_001",
|
||
publisher_name="云南某某甲方企业", created_at=now, updated_at=now),
|
||
Task(id="task_mk_003", title="农产品品牌 Logo 设计", category="设计创意", sub_category="Logo设计",
|
||
description="为农业合作社设计品牌 Logo", mode="grab",
|
||
budget_min=3000, budget_max=5000, deadline="2026-08-25",
|
||
status="published", publisher_org_id=None,
|
||
publisher_name="大理农业合作社", created_at=now, updated_at=now),
|
||
Task(id="task_mk_004", title="短视频剪辑与制作", category="音视频", sub_category="短视频",
|
||
description="文旅宣传短视频剪辑", mode="grab",
|
||
budget_min=1500, budget_max=3000, deadline="2026-08-20",
|
||
status="published", publisher_org_id=None,
|
||
publisher_name="文旅传媒", created_at=now, updated_at=now),
|
||
Task(id="task_mk_005", title="商业计划书撰写", category="策划/写作", sub_category="文案写作",
|
||
description="创业项目商业计划书", mode="designated",
|
||
budget_min=2000, budget_max=4000, deadline="2026-09-01",
|
||
status="published", publisher_org_id=None,
|
||
publisher_name="创业团队", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
ContentItem(id="cont_pol_001", type="policy", title="昆明市创业担保贷款政策",
|
||
summary="对符合条件的创业主体提供担保贷款支持",
|
||
body="适用对象、额度、利率与申报流程……", publisher_id="u_gov_prov",
|
||
status="published", created_at=now, updated_at=now),
|
||
ContentItem(id="cont_pol_002", type="policy", title="小微企业税收优惠减免",
|
||
summary="符合条件的小微企业可享受税收减免",
|
||
body="适用范围、减免标准与办理方式……", publisher_id="u_gov_prov",
|
||
status="published", created_at=now, updated_at=now),
|
||
ContentItem(id="cont_pol_003", type="policy", title="云南省一次性创业补贴",
|
||
summary="首次创业且正常经营 1 年以上发放一次性补贴",
|
||
body="申报条件、补贴标准与流程……", publisher_id="u_gov_prov",
|
||
status="published", created_at=now, updated_at=now),
|
||
])
|
||
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# 端口子页面演示数据(企业人才/载体OPC与服务/服务商订单与服务/政务OPC·政策·载体·数据)
|
||
# ---------------------------------------------------------------------------
|
||
_PORT_PAGES: dict[tuple[str, str], dict] = {
|
||
("enterprise", "talents"): {
|
||
"items": [
|
||
{"title": "张伟 · UI设计师", "meta": "5年经验 · Figma/PS · 认证OPC", "tag": "认证"},
|
||
{"title": "李娜 · 前端开发", "meta": "3年经验 · Vue/React · 认证OPC", "tag": "认证"},
|
||
{"title": "王强 · 文案策划", "meta": "4年经验 · 公众号/短视频文案", "tag": "独立"},
|
||
{"title": "赵敏 · 数据分析", "meta": "2年经验 · Python/SQL", "tag": "独立"},
|
||
{"title": "陈晨 · 电商运营", "meta": "3年经验 · 抖音/淘宝", "tag": "认证"},
|
||
{"title": "刘洋 · 空间设计", "meta": "6年经验 · 民宿/商业空间", "tag": "认证"},
|
||
],
|
||
},
|
||
("carrier", "opc"): {
|
||
"items": [
|
||
{"title": "云创设计工作室", "meta": "电子信息方向 · 工位12 · 2026-03 入驻", "tag": "已入驻"},
|
||
{"title": "滇峰数据科技", "meta": "软件服务方向 · 工位8 · 2026-04 入驻", "tag": "已入驻"},
|
||
{"title": "云南新媒体中心", "meta": "内容创作方向 · 工位6 · 待审批", "tag": "待审批"},
|
||
{"title": "绿野农业电商", "meta": "电商方向 · 工位10 · 2026-05 入驻", "tag": "已入驻"},
|
||
{"title": "云南文创工坊", "meta": "文化创意方向 · 工位4 · 申请中", "tag": "申请中"},
|
||
],
|
||
},
|
||
("carrier", "services"): {
|
||
"items": [
|
||
{"title": "园区创业培训", "meta": "创业辅导 · 月度课程 · 已完成", "tag": "已完成"},
|
||
{"title": "工商注册代办", "meta": "云超财税 · 本期 12 单", "tag": "合作中"},
|
||
{"title": "政策申报指导", "meta": "省市区三级补贴申报", "tag": "进行中"},
|
||
{"title": "法务顾问服务", "meta": "滇峰法律 · 入驻企业专享", "tag": "合作中"},
|
||
],
|
||
},
|
||
("provider", "orders"): {
|
||
"items": [
|
||
{"title": "代理记账服务(月度)", "meta": "云南某某甲方企业 · ¥199/月 · 2026-07 开始", "tag": "进行中"},
|
||
{"title": "公司注册代办", "meta": "个人创业者 · ¥599/次 · 待处理", "tag": "待处理"},
|
||
{"title": "季度财务报表编制", "meta": "云创财税 · ¥2000-3000 · 已完成", "tag": "已完成"},
|
||
{"title": "税务筹划咨询", "meta": "鼎信税务所 · ¥1999/次 · 进行中", "tag": "进行中"},
|
||
{"title": "年度汇算清缴", "meta": "云南某某甲方企业 · ¥1500 · 待处理", "tag": "待处理"},
|
||
],
|
||
},
|
||
("provider", "services"): {
|
||
"items": [
|
||
{"title": "代理记账服务", "meta": "财税服务 · ¥199/月起 · 在售", "tag": "在售"},
|
||
{"title": "税务筹划咨询", "meta": "财税服务 · ¥1999/次 · 在售", "tag": "在售"},
|
||
{"title": "企业年报填报", "meta": "工商服务 · ¥99/次 · 在售", "tag": "在售"},
|
||
{"title": "审计报告出具", "meta": "财税服务 · ¥3000/份 · 草稿", "tag": "草稿"},
|
||
],
|
||
},
|
||
("government", "opc"): {
|
||
"items": [
|
||
{"title": "张伟 · UI设计师", "meta": "盘龙区 · 认证OPC · 信用88", "tag": "认证"},
|
||
{"title": "李娜 · 前端开发", "meta": "五华区 · 认证OPC · 信用85", "tag": "认证"},
|
||
{"title": "王强 · 文案策划", "meta": "盘龙区 · 独立OPC · 信用80", "tag": "独立"},
|
||
{"title": "赵敏 · 数据分析", "meta": "麒麟区 · 独立OPC · 信用82", "tag": "独立"},
|
||
],
|
||
},
|
||
("government", "policies"): {
|
||
"items": [
|
||
{"title": "云南省一次性创业补贴政策", "meta": "省级 · 2026-06 发布 · 申报中", "tag": "已发布"},
|
||
{"title": "昆明市创业担保贷款政策", "meta": "市级 · 2026-05 发布 · 申报中", "tag": "已发布"},
|
||
{"title": "小微企业税收优惠减免", "meta": "省级 · 2026-04 发布 · 申报中", "tag": "已发布"},
|
||
{"title": "青年人才创业支持计划", "meta": "市级 · 起草中", "tag": "草稿"},
|
||
],
|
||
},
|
||
("government", "carriers"): {
|
||
"items": [
|
||
{"title": "滇池创业园", "meta": "五华区 · 工位500 · 入驻率84%", "tag": "正常"},
|
||
{"title": "云创空间孵化器", "meta": "盘龙区 · 工位300 · 入驻率76%", "tag": "正常"},
|
||
{"title": "曲靖高新园区", "meta": "麒麟区 · 工位400 · 入驻率68%", "tag": "正常"},
|
||
],
|
||
},
|
||
("government", "data"): {
|
||
"stats": [
|
||
{"key": "opcTotal", "value": 45600},
|
||
{"key": "taskTotal", "value": 12500},
|
||
{"key": "carrierTotal", "value": 168},
|
||
{"key": "policyTotal", "value": 245},
|
||
],
|
||
"chart": [
|
||
{"label": "1月", "value": 3200},
|
||
{"label": "2月", "value": 3600},
|
||
{"label": "3月", "value": 4100},
|
||
{"label": "4月", "value": 3900},
|
||
{"label": "5月", "value": 4500},
|
||
{"label": "6月", "value": 5200},
|
||
],
|
||
},
|
||
("investor", "projects"): {
|
||
"items": [
|
||
{"title": "云上数仓 SaaS 平台", "meta": "人工智能 · 天使轮 · 融资 300万 · 估值 2000万", "tag": "天使轮"},
|
||
{"title": "滇南文旅数字营销", "meta": "文旅创意 · A轮 · 融资 800万 · 估值 6000万", "tag": "A轮"},
|
||
{"title": "生物医药检测服务", "meta": "生物医药 · 种子轮 · 融资 150万", "tag": "种子轮"},
|
||
{"title": "智慧农业物联", "meta": "农业科技 · 天使轮 · 融资 200万 · 估值 1500万", "tag": "天使轮"},
|
||
{"title": "本地生活 AI 助手", "meta": "人工智能 · 种子轮 · 融资 100万", "tag": "种子轮"},
|
||
],
|
||
},
|
||
("investor", "trainings"): {
|
||
"items": [
|
||
{"title": "商业计划书(BP)撰写实战", "meta": "投融资基础 · 视频课 · 免费", "tag": "免费"},
|
||
{"title": "创业公司估值与投资条款", "meta": "投融资进阶 · 视频课 · 付费", "tag": "付费"},
|
||
{"title": "尽职调查实务(投资人视角)", "meta": "投融资进阶 · 直播课 · 报名中", "tag": "报名中"},
|
||
{"title": "路演技巧与打动投资人", "meta": "融资准备 · 视频课 · 免费", "tag": "免费"},
|
||
{"title": "股权结构与法律合规", "meta": "融资准备 · 视频课 · 付费", "tag": "付费"},
|
||
],
|
||
},
|
||
("investor", "portfolio"): {
|
||
"stats": [
|
||
{"key": "totalInvested", "value": "¥500万"},
|
||
{"key": "portfolioCount", "value": 6},
|
||
{"key": "activeIntents", "value": 3},
|
||
{"key": "roadshowAttended", "value": 12},
|
||
],
|
||
"items": [
|
||
{"title": "云上数仓 SaaS", "meta": "已投 · 天使轮 · 当前估值 2000万", "tag": "已投"},
|
||
{"title": "滇南文旅", "meta": "已投 · A轮 · 当前估值 6000万", "tag": "已投"},
|
||
{"title": "本地生活 AI 助手", "meta": "跟踪中 · 种子轮", "tag": "跟踪中"},
|
||
],
|
||
},
|
||
("opc", "tax"): {
|
||
"items": [
|
||
{"title": "个人所得税 · 7月申报", "meta": "申报期至 2026-08-15 · 待申报", "tag": "待申报"},
|
||
{"title": "增值税 · 7月申报", "meta": "申报期至 2026-08-15 · 待申报", "tag": "待申报"},
|
||
{"title": "企业所得税 · 二季度", "meta": "已于 2026-07-20 申报", "tag": "已申报"},
|
||
],
|
||
},
|
||
("opc", "affairs"): {
|
||
"items": [
|
||
{"title": "个体工商户注册", "meta": "工商办理 · 材料已提交 · 办理中", "tag": "办理中"},
|
||
{"title": "年报公示", "meta": "工商办理 · 已完成", "tag": "已完成"},
|
||
{"title": "一次性创业补贴申报", "meta": "政务申报 · 区县初审中", "tag": "初审中"},
|
||
],
|
||
},
|
||
("developer", "dashboard"): {
|
||
"stats": [
|
||
{"key": "appCount", "value": 3},
|
||
{"key": "pluginCount", "value": 5},
|
||
{"key": "skillCount", "value": 8},
|
||
{"key": "apiCalls", "value": "12.6万"},
|
||
],
|
||
},
|
||
("developer", "apps"): {
|
||
"items": [
|
||
{"title": "云上订单助手", "meta": "应用 · 已上架 · 调用 3.2万次", "tag": "已上架"},
|
||
{"title": "创业政策查询", "meta": "应用 · 已上架 · 调用 5.1万次", "tag": "已上架"},
|
||
{"title": "财税自动记账", "meta": "应用 · 待审核", "tag": "待审核"},
|
||
],
|
||
},
|
||
("developer", "plugins"): {
|
||
"items": [
|
||
{"title": "task-helper", "meta": "插件 · 版本 v1.2 · 已上架", "tag": "已上架"},
|
||
{"title": "policy-mcp", "meta": "插件 · MCP · 已上架", "tag": "已上架"},
|
||
{"title": "invoice-extract", "meta": "插件 · 开发中", "tag": "开发中"},
|
||
],
|
||
},
|
||
("developer", "skills"): {
|
||
"items": [
|
||
{"title": "BP 撰写助手", "meta": "技能 · 已上架 · 使用 1200次", "tag": "已上架"},
|
||
{"title": "财税问答", "meta": "技能 · 已上架 · 使用 860次", "tag": "已上架"},
|
||
{"title": "路演 PPT 生成", "meta": "技能 · 待审核", "tag": "待审核"},
|
||
],
|
||
},
|
||
}
|
||
|
||
|
||
async def _seed_port_pages(session: AsyncSession, now: str) -> None:
|
||
"""写入端口子页面演示数据(幂等:任一 (port,page) 已存在则跳过)。"""
|
||
if await session.scalar(select(PortalPage.port).limit(1)) is not None:
|
||
return
|
||
session.add_all(
|
||
[
|
||
PortalPage(
|
||
port=port, page=page,
|
||
payload=json.dumps(payload, ensure_ascii=False),
|
||
updated_at=now,
|
||
)
|
||
for (port, page), payload in _PORT_PAGES.items()
|
||
]
|
||
)
|
||
|
||
|
||
async def _seed_investor(session: AsyncSession, now: str) -> None:
|
||
"""投资人端演示数据(偏好/路演/意向),幂等(以偏好为标记)。"""
|
||
if await session.scalar(select(InvestorPreference.user_id).limit(1)) is not None:
|
||
return
|
||
session.add_all([
|
||
InvestorPreference(
|
||
user_id="u_inv_01",
|
||
industries='["人工智能","文旅","农业科技"]',
|
||
stage="angel", amount_min=50, amount_max=300, region_id="r_prov_yn",
|
||
updated_at=now,
|
||
),
|
||
InvestorPreference(
|
||
user_id="u_inv_02",
|
||
industries='["人工智能","生物医药","智能制造"]',
|
||
stage="series_a", amount_min=500, amount_max=3000, region_id="r_prov_yn",
|
||
updated_at=now,
|
||
),
|
||
])
|
||
session.add_all([
|
||
Roadshow(
|
||
id="rs_001", publisher_id="u_inv_02", publisher_role="investor",
|
||
title="云南 AI 创业项目专场路演", summary="8 个 AI 方向创业项目线上路演",
|
||
activity_type="online", scope_type="all", region_id=None,
|
||
start_at="2026-08-20T14:00:00", end_at="2026-08-20T17:00:00",
|
||
register_deadline="2026-08-18", quota=100, live_url="",
|
||
status="published", need_review=True, created_at=now, updated_at=now,
|
||
),
|
||
Roadshow(
|
||
id="rs_002", publisher_id="u_gov_prov", publisher_role="government",
|
||
title="省级创业投融资对接会", summary="省级载体与投资人对接",
|
||
activity_type="hybrid", scope_type="region", region_id="r_prov_yn",
|
||
start_at="2026-08-28T09:00:00", end_at="2026-08-28T12:00:00",
|
||
register_deadline="2026-08-25", quota=200, venue="昆明国际会展中心",
|
||
status="published", need_review=False, created_at=now, updated_at=now,
|
||
),
|
||
])
|
||
session.add_all([
|
||
InvestmentIntent(
|
||
id="intent_001", investor_id="u_inv_01", project_id="proj_001",
|
||
project_name="云上数仓 SaaS 平台", status="contacted",
|
||
message="对贵项目感兴趣,希望约谈", created_at=now, updated_at=now,
|
||
),
|
||
])
|
||
|
||
|
||
async def _sync_permissions(session: AsyncSession, now: str) -> None:
|
||
"""幂等补种权限与角色权限映射(供既有库使用)。
|
||
|
||
只插入缺失的 Permission 行与缺失的 RolePermission 链接,不删除已有
|
||
自定义授权,避免覆盖运营端后续经「角色权限配置」做的调整。
|
||
"""
|
||
for pid, name, category, module in PERMISSIONS:
|
||
if await session.get(Permission, pid) is None:
|
||
session.add(Permission(id=pid, name=name, category=category, module=module))
|
||
for role_id, perms in ROLE_PERMISSIONS.items():
|
||
if await session.get(Role, role_id) is None:
|
||
continue
|
||
existing = {
|
||
rp.permission_id
|
||
for rp in await session.scalars(
|
||
select(RolePermission).where(RolePermission.role_id == role_id)
|
||
)
|
||
}
|
||
for perm in perms:
|
||
if perm not in existing:
|
||
session.add(RolePermission(role_id=role_id, permission_id=perm))
|
||
|
||
|
||
async def _ensure_extra_demo_users(session: AsyncSession, now: str) -> None:
|
||
"""补建新增的演示用户(投资人等),供既有库使用(幂等)。"""
|
||
EXTRA = [
|
||
("u_inv_01", "inv01", "投资人账号", "investor", "personal", None, "r_prov_yn"),
|
||
("u_inv_02", "inv02", "机构投资人", "investor", "org_director", None, "r_prov_yn"),
|
||
# 运营端内部子角色演示账号
|
||
("u_op_admin", "op_admin", "运营管理员", "operator", "op_admin", None, "r_prov_yn"),
|
||
("u_op_cs", "op_cs", "运营客服", "operator", "op_customer_service", None, "r_prov_yn"),
|
||
("u_op_fin", "op_fin", "运营财务", "operator", "op_finance", None, "r_prov_yn"),
|
||
("u_op_tech", "op_tech", "运营运维", "operator", "op_techops", None, "r_prov_yn"),
|
||
# 机构子账号(企业财务/任务发布、服务商执行/财务)
|
||
("u_ent_fin", "ent_fin", "企业财务", "enterprise", "operator", "o_ent_001", "r_dist_pl"),
|
||
("u_ent_pub", "ent_pub", "企业任务发布", "enterprise", "operator", "o_ent_001", "r_dist_pl"),
|
||
("u_pro_exec", "pro_exec", "服务商执行", "provider", "operator", "o_pro_001", "r_city_km"),
|
||
("u_pro_fin", "pro_fin", "服务商财务", "provider", "operator", "o_pro_001", "r_city_km"),
|
||
# 开放平台开发者
|
||
("u_dev_01", "dev01", "个人开发者", "developer", "dev_individual", None, "r_prov_yn"),
|
||
("u_dev_02", "dev02", "机构开发者", "developer", "dev_org_admin", None, "r_prov_yn"),
|
||
]
|
||
for (uid, username, nickname, role, sub_role, org_id, region_id) in EXTRA:
|
||
if await session.get(User, uid) is not None:
|
||
continue
|
||
digest, salt = hash_password("123456")
|
||
session.add(
|
||
User(
|
||
id=uid, username=username, nickname=nickname,
|
||
password_hash=digest, password_salt=salt,
|
||
role=role, sub_role=sub_role, org_id=org_id, region_id=region_id,
|
||
status="active", token_version=0, created_at=now, updated_at=now,
|
||
source="seed", auth_type="admin",
|
||
)
|
||
)
|
||
for seed in AGENT_SEED:
|
||
await _add_agent(session, seed, uid, None, now)
|
||
|
||
|
||
async def _seed_ecosystem(session: AsyncSession, now: str) -> None:
|
||
"""生态横切演示数据(通知/补贴/引荐/培训),幂等。"""
|
||
if await session.scalar(select(Notification.id).limit(1)) is None:
|
||
session.add_all([
|
||
Notification(id="ntf_001", user_id="u_opc_01", type="task",
|
||
title="任务进度更新", content="您的任务「电商小程序首页 UI 设计」进度已更新",
|
||
read=False, created_at=now),
|
||
Notification(id="ntf_002", user_id="u_opc_01", type="policy",
|
||
title="新政策匹配", content="2 项新政策与您高度匹配", read=False, created_at=now),
|
||
Notification(id="ntf_003", user_id="u_ent_01", type="task",
|
||
title="收到投标", content="您的任务收到新的竞标", read=False, created_at=now),
|
||
])
|
||
if await session.scalar(select(SubsidyApplication.id).limit(1)) is not None:
|
||
return
|
||
session.add_all([
|
||
SubsidyApplication(id="sub_001", opc_id="u_opc_01", opc_name="OPC个人创业者",
|
||
title="云南省一次性创业补贴", amount=10000, region_id="r_dist_wh",
|
||
status="applying", created_at=now, updated_at=now),
|
||
SubsidyApplication(id="sub_002", opc_id="u_opc_02", opc_name="OPC个体工商户",
|
||
title="昆明市创业担保贷款贴息", amount=5000, region_id="r_dist_pl",
|
||
status="district_review", created_at=now, updated_at=now),
|
||
SubsidyApplication(id="sub_003", opc_id="u_opc_01", opc_name="OPC个人创业者",
|
||
title="青年人才创业支持计划", amount=20000, region_id="r_dist_wh",
|
||
status="city_review", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
ServiceReferral(id="ref_001", carrier_id="o_car_001", provider_id="o_pro_001",
|
||
provider_name="云超财税服务所", opc_id="u_opc_01", opc_name="OPC个人创业者",
|
||
status="referred", created_at=now, updated_at=now),
|
||
])
|
||
session.add_all([
|
||
TrainingEnrollment(id="treg_001", user_id="u_inv_01", training_id="商业计划书(BP)撰写实战",
|
||
training_name="商业计划书(BP)撰写实战", status="enrolled", created_at=now),
|
||
])
|
||
|
||
|
||
async def _seed_org_members(session: AsyncSession, now: str) -> None:
|
||
"""机构成员(机构主账号 + 子账号),幂等(以 organization_members 为标记)。"""
|
||
await session.flush()
|
||
if await session.scalar(select(OrganizationMember.org_id).limit(1)) is not None:
|
||
return
|
||
# 每个机构默认一个管理员主账号
|
||
members = [
|
||
("o_ent_001", "u_ent_01", "admin", True),
|
||
("o_car_001", "u_car_01", "admin", True),
|
||
("o_pro_001", "u_pro_01", "admin", True),
|
||
# 企业子账号(财务/任务发布)
|
||
("o_ent_001", "u_ent_fin", "finance", False),
|
||
("o_ent_001", "u_ent_pub", "publisher", False),
|
||
# 服务商子账号(服务执行/财务)
|
||
("o_pro_001", "u_pro_exec", "service_executor", False),
|
||
("o_pro_001", "u_pro_fin", "finance", False),
|
||
]
|
||
for org_id, user_id, role, is_admin in members:
|
||
session.add(OrganizationMember(org_id=org_id, user_id=user_id, role=role,
|
||
is_admin=is_admin, status="active", joined_at=now))
|