企迹(qiji) 政企周报管理系统 — v0.1

后端: FastAPI + SQLAlchemy 2.0 (async) + Alembic + MinIO + Casdoor + 企微
前端: Vue 3 + Vite + TypeScript + Element Plus + Pinia

功能清单:
- 8 张数据表自动建表 / Casdoor OIDC 登录 / 企微静默登录
- 双布局: 移动端(填报) + PC端(汇总管理)
- 拜访记录 CRUD + MinIO 照片直传 + 缩略图预览 + 同访人草稿
- 今日纪要 (6 分类) / 工作计划 / 小微商机 / 要客拜访 CRUD
- 客户档案: 备注/收支费用/联系人/归属分配/批量转移
- 客户导入导出 + 模板下载 + 搜索/分页/筛选
- 仪表盘: 四卡统计 + 填报进度 (拜访+纪要双维度)
- 周报详情: 五 Tab + 按人/客户筛选 + 时间轴
- 用户管理 / 客户经理 PC 端工作台
- 企微: 催办/公告/定时提醒 / 时区修正
- Docker 部署配置

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-06-23 01:35:46 +08:00
parent 2a8225c31f
commit a1886074dd
97 changed files with 8830 additions and 0 deletions
+58
View File
@@ -0,0 +1,58 @@
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
from app.database import engine, Base
from app.api import router as api_router
from app.api import auth, users, customers, visits, work_plans, mini_business, key_visits
from app.api import dashboard, upload, export, import_data, wecom, daily_notes
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: create tables if not exists (for dev convenience)
async with engine.begin() as conn:
await conn.run_sync(Base.metadata.create_all)
# Add columns that may be missing from older tables
await conn.run_sync(lambda c: c.exec_driver_sql(
"ALTER TABLE customers ADD COLUMN IF NOT EXISTS remarks TEXT DEFAULT ''"
))
yield
# Shutdown
await engine.dispose()
app = FastAPI(
title=settings.APP_NAME,
version="0.1.0",
lifespan=lifespan,
)
# CORS
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Mount all routers
app.include_router(auth.router, prefix="/api")
app.include_router(users.router, prefix="/api")
app.include_router(customers.router, prefix="/api")
app.include_router(visits.router, prefix="/api")
app.include_router(work_plans.router, prefix="/api")
app.include_router(mini_business.router, prefix="/api")
app.include_router(key_visits.router, prefix="/api")
app.include_router(dashboard.router, prefix="/api")
app.include_router(upload.router, prefix="/api")
app.include_router(export.router, prefix="/api")
app.include_router(import_data.router, prefix="/api")
app.include_router(wecom.router, prefix="/api")
app.include_router(daily_notes.router, prefix="/api")
@app.get("/health")
async def health_check():
return {"status": "ok", "app": settings.APP_NAME}