| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369 |
- import json
- import re
- from typing import Optional, List
- from fastapi import APIRouter, Depends, Query, Request
- from pydantic import BaseModel, ConfigDict
- from pydantic.alias_generators import to_camel
- from sqlalchemy.orm import Session
- from sqlalchemy import text
- from app.database import get_db
- from app.models.system import SysUser, SysDept, SysDictData, SysOss
- from app.schemas import R, TableDataInfo, PageQuery
- from app.middleware import get_current_user
- from app.utils.redis_client import get_redis
- router = APIRouter()
- def _is_http(s: str) -> bool:
- return s.startswith("http://") or s.startswith("https://")
- def _capitalize(s: str) -> str:
- return s[0].upper() + s[1:] if s else ""
- def _build_router_tree(menus: list, parent_id: int) -> list:
- children_menus = [m for m in menus if m["parent_id"] == parent_id]
- result = []
- for menu in children_menus:
- menu_type = menu["menu_type"]
- path = menu["path"] or ""
- component = menu["component"] or ""
- is_frame = str(menu.get("is_frame", 1))
- is_cache = str(menu.get("is_cache", 0))
- visible = str(menu.get("visible", "0"))
- menu_id = menu["menu_id"]
- pid = menu["parent_id"]
- is_menu_frame = pid == 0 and menu_type == "C" and is_frame == "1"
- is_inner_link = is_frame == "1" and _is_http(path)
- is_parent_view = pid != 0 and menu_type == "M"
- route_name = ""
- if not is_menu_frame:
- route_name = _capitalize(path)
- router_path = path
- if pid != 0 and is_inner_link:
- router_path = re.sub(r'^https?://|www\.|[.:]', '', path)
- elif pid == 0 and menu_type == "M" and is_frame == "1":
- router_path = path if path.startswith("/") else "/" + path
- elif is_menu_frame:
- router_path = path if path.startswith("/") else "/" + path
- component_info = "Layout"
- if component and not is_menu_frame:
- component_info = component
- elif not component and pid != 0 and is_inner_link:
- component_info = "InnerLink"
- elif not component and is_parent_view:
- component_info = "ParentView"
- router = {
- "name": route_name + str(menu_id),
- "path": router_path,
- "hidden": visible == "1",
- "component": component_info,
- "query": menu.get("query_param", ""),
- "menuType": menu_type,
- "isFrame": is_frame,
- "meta": {
- "title": menu["menu_name"],
- "icon": menu.get("icon", ""),
- "noCache": is_cache == "1",
- "link": path if is_inner_link else None,
- },
- }
- sub_children = _build_router_tree(menus, menu_id)
- if sub_children and menu_type == "M":
- router["alwaysShow"] = True
- router["redirect"] = "noRedirect"
- router["children"] = sub_children
- elif is_menu_frame:
- frame_name = _capitalize(path) + str(menu_id)
- router["children"] = [{
- "path": path,
- "component": component,
- "name": frame_name,
- "meta": {
- "title": menu["menu_name"],
- "icon": menu.get("icon", ""),
- "noCache": is_cache == "1",
- "link": None,
- },
- "query": menu.get("query_param", ""),
- }]
- elif pid == 0 and is_inner_link:
- inner_path = re.sub(r'^https?://|www\.|[.:]', '', path)
- inner_name = _capitalize(inner_path) + str(menu_id)
- router["path"] = "/"
- router["children"] = [{
- "path": inner_path,
- "component": "InnerLink",
- "name": inner_name,
- "meta": {
- "title": menu["menu_name"],
- "icon": menu.get("icon", ""),
- "link": path,
- },
- }]
- router["meta"] = {
- "title": menu["menu_name"],
- "icon": menu.get("icon", ""),
- }
- result.append(router)
- return result
- @router.get("/user/getInfo")
- def get_user_info(current_user: dict = Depends(get_current_user), db: Session = Depends(get_db)):
- user_id = current_user.get("user_id")
- tenant_id = current_user.get("tenant_id", "000000")
- redis = get_redis()
- session_key = f"login:session:{user_id}:{tenant_id}"
- session_data = redis.get(session_key)
- permissions = []
- roles = []
- if session_data:
- import json
- data = json.loads(session_data)
- permissions = data.get("permissions", [])
- roles = data.get("roles", [])
- user = db.query(SysUser).filter(SysUser.user_id == user_id, SysUser.del_flag == "0").first()
- if not user:
- return R.fail("用户不存在")
- user_data = {
- "userId": user.user_id,
- "userName": user.user_name,
- "nickName": user.nick_name,
- "deptId": user.dept_id,
- "email": user.email or "",
- "phonenumber": user.phonenumber or "",
- "sex": user.sex,
- "avatar": user.avatar or "",
- "status": user.status,
- "accountType": getattr(user, "account_type", "1"),
- }
- return R.ok(data={
- "user": user_data,
- "permissions": permissions,
- "roles": roles,
- })
- class UserQuery(PageQuery):
- model_config = ConfigDict(populate_by_name=True, alias_generator=to_camel)
- user_name: Optional[str] = None
- status: Optional[str] = None
- dept_id: Optional[int] = None
- @router.get("/user/list")
- def list_users(query: UserQuery = Depends(), db: Session = Depends(get_db)):
- q = db.query(SysUser).filter(SysUser.del_flag == "0")
- if query.user_name:
- q = q.filter(SysUser.user_name.like(f"%{query.user_name}%"))
- if query.status:
- q = q.filter(SysUser.status == query.status)
- if query.dept_id:
- q = q.filter(SysUser.dept_id == query.dept_id)
- total = q.count()
- users = q.order_by(SysUser.create_time.desc()).offset(query.offset).limit(query.limit).all()
- rows = [
- {
- "userId": u.user_id,
- "userName": u.user_name,
- "nickName": u.nick_name,
- "deptId": u.dept_id,
- "email": u.email or "",
- "phonenumber": u.phonenumber or "",
- "sex": u.sex,
- "avatar": u.avatar or "",
- "status": u.status,
- "accountType": getattr(u, "account_type", "1"),
- "createTime": u.create_time.strftime("%Y-%m-%d %H:%M:%S") if u.create_time else None,
- }
- for u in users
- ]
- return TableDataInfo.build(rows, total)
- @router.get("/user/deptTree")
- def dept_tree(db: Session = Depends(get_db)):
- depts = db.query(SysDept).filter(SysDept.del_flag == "0", SysDept.status == "0").all()
- dept_map = {d.dept_id: d for d in depts}
- def build_tree(parent_id=0):
- children = []
- for d in depts:
- if d.parent_id == parent_id:
- node = {
- "id": d.dept_id,
- "label": d.dept_name,
- "parentId": d.parent_id,
- "children": build_tree(d.dept_id),
- }
- children.append(node)
- return children
- return R.ok(data=build_tree(0))
- @router.get("/user/list-by-permission")
- def list_users_by_permission(
- permission: str = Query(...),
- db: Session = Depends(get_db),
- ):
- return list_users(UserQuery(), db)
- @router.get("/dict/data/type/{dict_type}")
- def dict_data_by_type(dict_type: str, db: Session = Depends(get_db)):
- redis = get_redis()
- cache_key = f"dict:data:{dict_type}"
- cached = redis.get(cache_key)
- if cached:
- return R.ok(data=json.loads(cached))
- items = (
- db.query(SysDictData)
- .filter(SysDictData.dict_type == dict_type)
- .order_by(SysDictData.dict_sort)
- .all()
- )
- data = [
- {
- "dictCode": d.dict_code,
- "dictSort": d.dict_sort,
- "dictLabel": d.dict_label,
- "dictValue": d.dict_value,
- "dictType": d.dict_type,
- "cssClass": d.css_class or "",
- "listClass": d.list_class or "",
- "isDefault": d.is_default,
- "remark": d.remark or "",
- }
- for d in items
- ]
- redis.setex(cache_key, 3600, json.dumps(data, ensure_ascii=False))
- return R.ok(data=data)
- @router.get("/dept/list")
- def dept_list(
- parent_id: Optional[int] = Query(None),
- status: Optional[str] = Query(None),
- db: Session = Depends(get_db),
- ):
- q = db.query(SysDept).filter(SysDept.del_flag == "0")
- if status:
- q = q.filter(SysDept.status == status)
- depts = q.order_by(SysDept.order_num).all()
- return R.ok(data=[
- {
- "deptId": d.dept_id,
- "parentId": d.parent_id,
- "ancestors": d.ancestors,
- "deptName": d.dept_name,
- "deptCategory": d.dept_category or "",
- "orderNum": d.order_num,
- "leader": d.leader,
- "phone": d.phone or "",
- "email": d.email or "",
- "status": d.status,
- }
- for d in depts
- ])
- @router.get("/dept/treeselect")
- def dept_treeselect(db: Session = Depends(get_db)):
- return dept_tree(db)
- @router.post("/oss/upload")
- def upload_file(request: Request, db: Session = Depends(get_db)):
- return R.fail("OSS upload not yet implemented - use existing Java backend for file uploads")
- @router.get("/oss/{oss_id}")
- def get_oss(oss_id: int, db: Session = Depends(get_db)):
- oss = db.query(SysOss).filter(SysOss.oss_id == oss_id).first()
- if not oss:
- return R.fail("文件不存在")
- return R.ok(data={
- "ossId": oss.oss_id,
- "fileName": oss.file_name,
- "originalName": oss.original_name,
- "fileSuffix": oss.file_suffix,
- "url": oss.url,
- })
- @router.get("/menu/getRouters")
- def get_routers(current_user: dict = Depends(get_current_user), db: Session = Depends(get_db)):
- user_id = current_user.get("user_id")
- rows = db.execute(text("""
- SELECT m.menu_id, m.menu_name, m.parent_id, m.order_num, m.path, m.component,
- m.query_param, m.is_frame, m.is_cache, m.menu_type, m.visible, m.status, m.icon, m.perms
- FROM sys_menu m
- WHERE m.menu_type IN ('M', 'C') AND m.status = '0'
- ORDER BY m.parent_id, m.order_num
- """)).fetchall()
- menus = []
- for r in rows:
- menus.append({
- "menu_id": r[0],
- "menu_name": r[1],
- "parent_id": r[2],
- "order_num": r[3],
- "path": r[4] or "",
- "component": r[5] or "",
- "query_param": r[6] or "",
- "is_frame": r[7],
- "is_cache": r[8],
- "menu_type": r[9],
- "visible": r[10],
- "status": r[11],
- "icon": r[12] or "",
- "perms": r[13] or "",
- })
- routers = _build_router_tree(menus, 0)
- return R.ok(data=routers)
- @router.get("/oss/listByIds/{oss_id}")
- def list_oss_by_ids(oss_id: str, db: Session = Depends(get_db)):
- ids = []
- for part in str(oss_id).split(","):
- part = part.strip()
- if part.isdigit():
- ids.append(int(part))
- if not ids:
- return R.ok(data=[])
- rows = db.query(SysOss).filter(SysOss.oss_id.in_(ids)).all()
- return R.ok(data=[{
- "ossId": o.oss_id,
- "fileName": o.file_name,
- "originalName": o.original_name,
- "fileSuffix": o.file_suffix,
- "url": o.url,
- "size": o.size if hasattr(o, "size") else "",
- } for o in rows])
|