提交
This commit is contained in:
1 parent
afd517ce10
commit
eec61cb5dd
82 files changed
+16585
-9026
No files matched your search
+1
-1
@@ -1 +1 @@
|
||||
91519
|
||||
88694
|
||||
+146
-26
@@ -1,7 +1,8 @@
|
||||
"""公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线)"""
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request, UploadFile, File
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
@@ -22,16 +23,21 @@ from app.core.auth import (
|
||||
)
|
||||
from app.core.response import success_response, error_response
|
||||
from app.core.config import settings
|
||||
from app.core.storage import storage
|
||||
from app.core.avatar_url import extract_avatar_storage_key
|
||||
from app.models.models import SysUser
|
||||
from app.crud.user import user_crud
|
||||
from app.core.utils import generate_uuid
|
||||
from app.core import login_crypto
|
||||
from app.services.web_auth_roles import iter_user_menu_perm_codes, resolve_web_role_for_user
|
||||
from app.schemas.auth import ProfileUpdateRequest
|
||||
from app.crud.user import update_user, change_password
|
||||
|
||||
router = APIRouter(prefix="", tags=["公共接口"])
|
||||
|
||||
|
||||
def _avatar_url_field(user: SysUser) -> Optional[str]:
|
||||
"""返回库中原始头像路径,由前端按 VITE_MINIO_BASE_URL 拼展示 URL。"""
|
||||
raw = getattr(user, "avatar", None)
|
||||
if not raw:
|
||||
return None
|
||||
@@ -48,6 +54,8 @@ def _build_user_info_payload(user: SysUser, web_role: str) -> dict:
|
||||
"realName": user.nick_name,
|
||||
"phone": phone,
|
||||
"email": (getattr(user, "email", None) or "").strip() or None,
|
||||
"sex": getattr(user, "sex", None) or "0",
|
||||
"remark": (getattr(user, "remark", None) or "").strip() or None,
|
||||
"role": web_role,
|
||||
"regionId": user.dept_id,
|
||||
"regionName": None,
|
||||
@@ -55,6 +63,36 @@ def _build_user_info_payload(user: SysUser, web_role: str) -> dict:
|
||||
}
|
||||
|
||||
|
||||
def _build_current_user_payload(current_user: dict) -> dict:
|
||||
"""组装 current-user 接口响应。"""
|
||||
au = current_user.get("avatar_url")
|
||||
avatar_url = str(au).strip() if au else None
|
||||
return {
|
||||
"id": current_user.get("user_id"),
|
||||
"username": current_user.get("username"),
|
||||
"realName": current_user.get("real_name"),
|
||||
"phone": current_user.get("phone"),
|
||||
"email": current_user.get("email"),
|
||||
"sex": current_user.get("sex") or "0",
|
||||
"remark": current_user.get("remark"),
|
||||
"role": current_user.get("role"),
|
||||
"isSuperAdmin": current_user.get("role") == "super_admin",
|
||||
"regionId": current_user.get("region_id"),
|
||||
"regionName": None,
|
||||
"regionIds": [],
|
||||
"isActive": current_user.get("is_active"),
|
||||
"avatarUrl": avatar_url if avatar_url else None,
|
||||
}
|
||||
|
||||
|
||||
async def _resolve_current_user_from_request(request: Request, db: Session) -> dict:
|
||||
authorization = request.headers.get("Authorization", "")
|
||||
if not authorization.startswith("Bearer "):
|
||||
raise HTTPException(status_code=401, detail="未授权")
|
||||
token = authorization.replace("Bearer ", "")
|
||||
return await get_current_user_by_token(token=token, db=db)
|
||||
|
||||
|
||||
def _jwt_user_payload(user: SysUser, web_role: str) -> dict:
|
||||
return {
|
||||
"sub": user.id,
|
||||
@@ -214,36 +252,118 @@ async def logout(request: Request):
|
||||
@router.get("/web/auth/current-user", response_model=dict)
|
||||
async def get_current_user_profile(request: Request, db: Session = Depends(get_db)):
|
||||
"""获取当前用户信息(与 sys_user 字段对应)。"""
|
||||
authorization = request.headers.get("Authorization", "")
|
||||
if not authorization.startswith("Bearer "):
|
||||
return error_response(401, "未授权")
|
||||
|
||||
token = authorization.replace("Bearer ", "")
|
||||
try:
|
||||
current_user = await get_current_user_by_token(token=token, db=db)
|
||||
|
||||
au = current_user.get("avatar_url")
|
||||
avatar_url = str(au).strip() if au else None
|
||||
return success_response(
|
||||
{
|
||||
"id": current_user.get("user_id"),
|
||||
"username": current_user.get("username"),
|
||||
"realName": current_user.get("real_name"),
|
||||
"phone": current_user.get("phone"),
|
||||
"email": current_user.get("email"),
|
||||
"role": current_user.get("role"),
|
||||
"isSuperAdmin": current_user.get("role") == "super_admin",
|
||||
"regionId": current_user.get("region_id"),
|
||||
"regionName": None,
|
||||
"regionIds": [],
|
||||
"isActive": current_user.get("is_active"),
|
||||
"avatarUrl": avatar_url if avatar_url else None,
|
||||
}
|
||||
)
|
||||
current_user = await _resolve_current_user_from_request(request, db)
|
||||
return success_response(_build_current_user_payload(current_user))
|
||||
except HTTPException:
|
||||
return error_response(401, "Token无效或已过期")
|
||||
|
||||
|
||||
@router.put("/web/auth/profile", response_model=dict)
|
||||
async def update_current_user_profile(
|
||||
request: Request,
|
||||
body: ProfileUpdateRequest,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""当前用户更新个人信息(手机号、邮箱、性别、备注)。"""
|
||||
try:
|
||||
current_user = await _resolve_current_user_from_request(request, db)
|
||||
user_id = current_user.get("user_id")
|
||||
if not user_id:
|
||||
return error_response(401, "未授权")
|
||||
|
||||
payload = body.model_dump(exclude_unset=True, by_alias=False)
|
||||
update_user(
|
||||
db,
|
||||
user_id,
|
||||
phone_no=payload.get("phone_no"),
|
||||
email=payload.get("email"),
|
||||
sex=payload.get("sex"),
|
||||
remark=payload.get("remark"),
|
||||
avatar=payload.get("avatar"),
|
||||
user_id_updater=user_id,
|
||||
)
|
||||
|
||||
user = user_crud.get(db, user_id)
|
||||
if not user:
|
||||
return error_response(404, "用户不存在")
|
||||
web_role = resolve_web_role_for_user(db, user.id)
|
||||
return success_response(_build_user_info_payload(user, web_role))
|
||||
except HTTPException:
|
||||
return error_response(401, "Token无效或已过期")
|
||||
except ValueError as exc:
|
||||
return error_response(400, str(exc))
|
||||
|
||||
|
||||
@router.post("/web/auth/change-password", response_model=dict)
|
||||
async def change_current_user_password(
|
||||
request: Request,
|
||||
body: dict,
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""当前用户修改密码。"""
|
||||
try:
|
||||
current_user = await _resolve_current_user_from_request(request, db)
|
||||
user_id = current_user.get("user_id")
|
||||
if not user_id:
|
||||
return error_response(401, "未授权")
|
||||
|
||||
old_password = (body.get("oldPassword") or body.get("old_password") or "").strip()
|
||||
new_password = (body.get("newPassword") or body.get("new_password") or "").strip()
|
||||
if not old_password:
|
||||
return error_response(400, "请输入原密码")
|
||||
if len(new_password) < 6:
|
||||
return error_response(400, "新密码长度不能少于6位")
|
||||
|
||||
change_password(db, user_id, old_password, new_password)
|
||||
return success_response({"message": "密码修改成功"})
|
||||
except HTTPException:
|
||||
return error_response(401, "Token无效或已过期")
|
||||
except ValueError as exc:
|
||||
return error_response(400, str(exc))
|
||||
|
||||
|
||||
_AVATAR_MAX_BYTES = 2 * 1024 * 1024
|
||||
_AVATAR_ALLOWED_EXT = {".jpg", ".jpeg", ".png", ".gif", ".webp", ".bmp"}
|
||||
|
||||
|
||||
@router.post("/web/auth/upload-avatar", response_model=dict)
|
||||
async def upload_current_user_avatar(
|
||||
request: Request,
|
||||
file: UploadFile = File(...),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""当前用户上传头像(仅图片,最大 2MB)。"""
|
||||
try:
|
||||
await _resolve_current_user_from_request(request, db)
|
||||
except HTTPException:
|
||||
return error_response(401, "Token无效或已过期")
|
||||
|
||||
if not file or not file.filename:
|
||||
return error_response(400, "请选择图片")
|
||||
|
||||
ext = os.path.splitext(file.filename)[1].lower()
|
||||
if ext not in _AVATAR_ALLOWED_EXT:
|
||||
return error_response(400, "仅支持 JPG、PNG、GIF、WEBP、BMP 格式")
|
||||
|
||||
content_type = (file.content_type or "").lower()
|
||||
if content_type and not content_type.startswith("image/"):
|
||||
return error_response(400, "仅支持上传图片文件")
|
||||
|
||||
try:
|
||||
file_content = await file.read()
|
||||
if not file_content:
|
||||
return error_response(400, "文件内容为空")
|
||||
if len(file_content) > _AVATAR_MAX_BYTES:
|
||||
return error_response(400, "头像大小不能超过 2MB")
|
||||
|
||||
url = storage.upload_file(file_content, file.filename, "avatar")
|
||||
stored_url = extract_avatar_storage_key(url)
|
||||
return success_response({"url": stored_url})
|
||||
except Exception as exc:
|
||||
return error_response(500, f"上传失败: {str(exc)}")
|
||||
|
||||
|
||||
@router.get("/web/auth/menu-codes", response_model=dict)
|
||||
async def get_web_auth_menu_codes(request: Request, db: Session = Depends(get_db)):
|
||||
"""获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。"""
|
||||
|
||||
@@ -225,7 +225,11 @@ async def get_current_user_by_token(
|
||||
|
||||
phone = (getattr(user, "phone_no", None) or "").strip() or None
|
||||
email = (getattr(user, "email", None) or "").strip() or None
|
||||
avatar = getattr(user, "avatar", None)
|
||||
avatar_raw = getattr(user, "avatar", None)
|
||||
avatar_stored = None
|
||||
if avatar_raw is not None:
|
||||
s = str(avatar_raw).strip()
|
||||
avatar_stored = s if s else None
|
||||
|
||||
current_user_dept_id.set(user.dept_id or "")
|
||||
|
||||
@@ -237,7 +241,9 @@ async def get_current_user_by_token(
|
||||
"region_id": user.dept_id,
|
||||
"phone": phone,
|
||||
"email": email,
|
||||
"avatar_url": avatar,
|
||||
"sex": getattr(user, "sex", None) or "0",
|
||||
"remark": (getattr(user, "remark", None) or "").strip() or None,
|
||||
"avatar_url": avatar_stored,
|
||||
"is_active": user.status == "1",
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
"""用户头像 URL 解析(sys_user.avatar 可能存 MinIO 相对路径或完整 URL)"""
|
||||
from typing import Optional
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.storage import storage
|
||||
|
||||
|
||||
def resolve_avatar_display_url(raw: Optional[str]) -> Optional[str]:
|
||||
"""服务端内部拼完整 URL(邮件等);Web API 应返回库中原始路径。"""
|
||||
if raw is None:
|
||||
return None
|
||||
s = str(raw).strip()
|
||||
if not s:
|
||||
return None
|
||||
lower = s.lower()
|
||||
if lower.startswith("http://") or lower.startswith("https://") or s.startswith("/"):
|
||||
return s
|
||||
try:
|
||||
return storage.get_url(s.lstrip("/"))
|
||||
except Exception:
|
||||
base = (settings.MINIO_BASE_URL or settings.LOCAL_STORAGE_URL or "").rstrip("/")
|
||||
if base:
|
||||
return f"{base}/{s.lstrip('/')}"
|
||||
return s
|
||||
|
||||
|
||||
def extract_avatar_storage_key(full_url: str) -> str:
|
||||
"""从 upload 返回值或历史完整 URL 中提取 avatar/ 相对路径。"""
|
||||
u = (full_url or "").strip()
|
||||
if not u:
|
||||
return ""
|
||||
base_url = (settings.MINIO_BASE_URL or "").rstrip("/")
|
||||
if base_url and u.startswith(base_url + "/"):
|
||||
return u[len(base_url) + 1 :].lstrip("/")
|
||||
marker = "/avatar/"
|
||||
idx = u.lower().find(marker)
|
||||
if idx >= 0:
|
||||
return f"avatar/{u[idx + len(marker) :].lstrip('/')}"
|
||||
if not u.lower().startswith("http") and not u.startswith("/"):
|
||||
return u.lstrip("/")
|
||||
return u
|
||||
@@ -138,6 +138,7 @@ class Settings(BaseSettings):
|
||||
"/api/web/admin/products/upload-image,"
|
||||
"/api/web/admin/categories/upload-image,"
|
||||
"/api/web/admin/users/upload-avatar,"
|
||||
"/api/web/auth/upload-avatar,"
|
||||
"/api/invoice/download"
|
||||
)
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ from app.crud.protocol_donation_convert import (
|
||||
assert_biz_no_available,
|
||||
get_partner_sample_codes,
|
||||
)
|
||||
from app.services.protocol_payment_installment import calc_fq_installment_due_date
|
||||
from app.services.protocol_pay_mode_switch import validate_payment_details_for_save
|
||||
from app.models.research_donation import BizResearchDonation, BizResearchDonationSample
|
||||
from app.models.models import (
|
||||
BizAttachment,
|
||||
@@ -350,7 +352,7 @@ def _payment_to_dict(p: BizProtocolPayment) -> Dict[str, Any]:
|
||||
"payMode": p.pay_mode or "",
|
||||
"contractAmount": _dec(p.contract_amount),
|
||||
"installmentCount": p.installment_count,
|
||||
"installmentIntervalMonths": p.installment_interval_months,
|
||||
"installmentIntervalMonths": _dec(p.installment_interval_months),
|
||||
"lumpSumDeadline": (p.lump_sum_deadline or "").strip() if p.lump_sum_deadline else "",
|
||||
"installmentStartDate": (p.installment_start_date or "").strip() if p.installment_start_date else "",
|
||||
"tenantNo": p.tenant_no,
|
||||
@@ -2537,7 +2539,8 @@ def align_fq_payment_details_payload(
|
||||
|
||||
amounts = _calc_installment_due_amounts(pay.contract_amount, count)
|
||||
start = (pay.installment_start_date or "").strip()
|
||||
interval = int(pay.installment_interval_months or 0)
|
||||
interval = pay.installment_interval_months
|
||||
interval_val = float(interval) if interval is not None else 0
|
||||
result: List[Dict[str, Any]] = []
|
||||
for i in range(count):
|
||||
no = i + 1
|
||||
@@ -2547,11 +2550,13 @@ def align_fq_payment_details_payload(
|
||||
if i < len(unnumbered):
|
||||
raw = dict(unnumbered[i])
|
||||
raw["installment_no"] = no
|
||||
if not raw.get("installment_due_date") and start and interval:
|
||||
raw["installment_due_date"] = _add_months_yyyymmdd(start, i * interval)
|
||||
if not raw.get("installment_due_date") and start and interval_val:
|
||||
raw["installment_due_date"] = calc_fq_installment_due_date(start, i, interval_val)
|
||||
result.append(raw)
|
||||
continue
|
||||
due_date = _add_months_yyyymmdd(start, i * interval) if start and interval else ""
|
||||
due_date = (
|
||||
calc_fq_installment_due_date(start, i, interval_val) if start and interval_val else ""
|
||||
)
|
||||
due = amounts[i] if i < len(amounts) else None
|
||||
result.append(
|
||||
{
|
||||
@@ -2601,8 +2606,8 @@ def upsert_payment(
|
||||
obj = get_payment_by_protocol_id(db, collection_protocol_id, tenant_no)
|
||||
_STR_FIELDS = ["pay_mode"]
|
||||
_STR_DATE_FIELDS = ["lump_sum_deadline", "installment_start_date"]
|
||||
_DEC_FIELDS = ["contract_amount"]
|
||||
_INT_FIELDS = ["installment_count", "installment_interval_months"]
|
||||
_DEC_FIELDS = ["contract_amount", "installment_interval_months"]
|
||||
_INT_FIELDS = ["installment_count"]
|
||||
|
||||
def _apply(target: BizProtocolPayment) -> None:
|
||||
for k in _STR_FIELDS:
|
||||
@@ -2658,6 +2663,26 @@ def save_payment_details(
|
||||
user_id: Optional[str],
|
||||
details: list,
|
||||
) -> List[BizProtocolPaymentDetail]:
|
||||
pay = (
|
||||
db.query(BizProtocolPayment)
|
||||
.filter(
|
||||
and_(
|
||||
BizProtocolPayment.id == payment_id,
|
||||
BizProtocolPayment.tenant_no == tenant_no,
|
||||
BizProtocolPayment.del_flag == 0,
|
||||
)
|
||||
)
|
||||
.first()
|
||||
)
|
||||
if pay:
|
||||
normalized = [_normalize_fields(dict(d)) for d in (details or [])]
|
||||
validate_payment_details_for_save(
|
||||
pay.pay_mode or "",
|
||||
pay.contract_amount,
|
||||
pay.installment_count,
|
||||
normalized,
|
||||
)
|
||||
|
||||
existing = list_payment_details(db, payment_id, tenant_no)
|
||||
for d in existing:
|
||||
d.del_flag = 1
|
||||
|
||||
@@ -418,6 +418,25 @@ def reset_password(db: Session, user_id: str, new_password: str) -> None:
|
||||
db.commit()
|
||||
|
||||
|
||||
def change_password(db: Session, user_id: str, old_password: str, new_password: str) -> None:
|
||||
from app.core.security import verify_password
|
||||
|
||||
obj = get_user(db, user_id)
|
||||
if not obj:
|
||||
raise ValueError("用户不存在")
|
||||
pwd_hash = getattr(obj, "password", None) or ""
|
||||
if not verify_password(old_password, pwd_hash):
|
||||
raise ValueError("原密码不正确")
|
||||
new_pw = (new_password or "").strip()
|
||||
if len(new_pw) < 6:
|
||||
raise ValueError("新密码长度不能少于6位")
|
||||
obj.password = _hash_password(new_pw)
|
||||
obj.update_by = user_id
|
||||
obj.update_time = datetime.now()
|
||||
db.add(obj)
|
||||
db.commit()
|
||||
|
||||
|
||||
def total_pages(total: int, page_size: int) -> int:
|
||||
if total <= 0:
|
||||
return 0
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "label": "avatar_url.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1"}, {"id": "core_avatar_url_resolve_avatar_display_url", "label": "resolve_avatar_display_url()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L8"}, {"id": "core_avatar_url_rationale_1", "label": "\u7528\u6237\u5934\u50cf URL \u89e3\u6790\uff08sys_user.avatar \u53ef\u80fd\u5b58 MinIO \u76f8\u5bf9\u8def\u5f84\u6216\u5b8c\u6574 URL\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "app_core_config", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "app_core_storage", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "core_avatar_url_resolve_avatar_display_url", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L8", "weight": 1.0}, {"source": "core_avatar_url_rationale_1", "target": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1", "weight": 1.0}], "raw_calls": [{"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "strip", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L11"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "str", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L11"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "lower", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L14"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "startswith", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L15"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "startswith", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L15"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "startswith", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L15"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "get_url", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L18"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "lstrip", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L18"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "rstrip", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L20"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "lstrip", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L22"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "label": "auth.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L1"}, {"id": "schemas_auth_loginrequest", "label": "LoginRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "schemas_auth_loginresponse", "label": "LoginResponse", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13"}, {"id": "schemas_auth_usercreate", "label": "UserCreate", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23"}, {"id": "schemas_auth_userresponse", "label": "UserResponse", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L33"}, {"id": "schemas_auth_config", "label": "Config", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L44"}, {"id": "schemas_auth_changepasswordrequest", "label": "ChangePasswordRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L48"}, {"id": "schemas_auth_profileupdaterequest", "label": "ProfileUpdateRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L54"}, {"id": "schemas_auth_resetpasswordrequest", "label": "ResetPasswordRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L65"}, {"id": "schemas_auth_rationale_1", "label": "Pydantic schemas - \u7528\u6237\u8ba4\u8bc1", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L1"}, {"id": "schemas_auth_rationale_55", "label": "\u5f53\u524d\u7528\u6237\u4e2a\u4eba\u4fe1\u606f\u66f4\u65b0\uff08\u4ec5\u5141\u8bb8\u81ea\u52a9\u4fee\u6539\u7684\u5b57\u6bb5\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L55"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "pydantic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_loginrequest", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7", "weight": 1.0}, {"source": "schemas_auth_loginrequest", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_loginresponse", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13", "weight": 1.0}, {"source": "schemas_auth_loginresponse", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_usercreate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23", "weight": 1.0}, {"source": "schemas_auth_usercreate", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_userresponse", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/bLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "label": "auth.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L1"}, {"id": "schemas_auth_loginrequest", "label": "LoginRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "schemas_auth_loginresponse", "label": "LoginResponse", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13"}, {"id": "schemas_auth_usercreate", "label": "UserCreate", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23"}, {"id": "schemas_auth_userresponse", "label": "UserResponse", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L33"}, {"id": "schemas_auth_config", "label": "Config", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L44"}, {"id": "schemas_auth_changepasswordrequest", "label": "ChangePasswordRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L48"}, {"id": "schemas_auth_profileupdaterequest", "label": "ProfileUpdateRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L54"}, {"id": "schemas_auth_resetpasswordrequest", "label": "ResetPasswordRequest", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L64"}, {"id": "schemas_auth_rationale_1", "label": "Pydantic schemas - \u7528\u6237\u8ba4\u8bc1", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L1"}, {"id": "schemas_auth_rationale_55", "label": "\u5f53\u524d\u7528\u6237\u4e2a\u4eba\u4fe1\u606f\u66f4\u65b0\uff08\u4ec5\u5141\u8bb8\u81ea\u52a9\u4fee\u6539\u7684\u5b57\u6bb5\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L55"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "pydantic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_loginrequest", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7", "weight": 1.0}, {"source": "schemas_auth_loginrequest", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_loginresponse", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13", "weight": 1.0}, {"source": "schemas_auth_loginresponse", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L13", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_usercreate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23", "weight": 1.0}, {"source": "schemas_auth_usercreate", "target": "basemodel", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py", "source_location": "L23", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_schemas_auth_py", "target": "schemas_auth_userresponse", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/bLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_public_py", "label": "public.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_avatar_url_field", "label": "_avatar_url_field()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L39"}, {"id": "api_public_build_user_info_payload", "label": "_build_user_info_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L43"}, {"id": "api_public_build_current_user_payload", "label": "_build_current_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L61"}, {"id": "api_public_resolve_current_user_from_request", "label": "_resolve_current_user_from_request()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L83"}, {"id": "api_public_jwt_user_payload", "label": "_jwt_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L91"}, {"id": "api_public_web_login_rsa_public_key", "label": "web_login_rsa_public_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L102"}, {"id": "api_public_web_login", "label": "web_login()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L109"}, {"id": "api_public_refresh_token", "label": "refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L167"}, {"id": "api_public_logout", "label": "logout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L229"}, {"id": "api_public_get_current_user_profile", "label": "get_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L248"}, {"id": "api_public_update_current_user_profile", "label": "update_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L258"}, {"id": "api_public_change_current_user_password", "label": "change_current_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L294"}, {"id": "api_public_upload_current_user_avatar", "label": "upload_current_user_avatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L326"}, {"id": "api_public_get_web_auth_menu_codes", "label": "get_web_auth_menu_codes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L362"}, {"id": "api_public_rationale_1", "label": "\u516c\u5171\u63a5\u53e3\uff08Web \u767b\u5f55\u3001\u5237\u65b0 Token\u3001\u767b\u51fa\uff1b\u7528\u6237\u6a21\u578b\u5bf9\u9f50 docs/sql/zkxw.sql \u57fa\u7ebf\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_rationale_44", "label": "\u4e0e web-admin `userInfo` \u5b57\u6bb5\u7ea6\u5b9a\u4e00\u81f4\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L44"}, {"id": "api_public_rationale_62", "label": "\u7ec4\u88c5 current-user \u63a5\u53e3\u54cd\u5e94\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L62"}, {"id": "api_public_rationale_103", "label": "Web \u7aef\u767b\u5f55\u7528 RSA \u516c\u94a5\uff08PKCS#1 v1.5\uff0c\u4e0e JSEncrypt \u4e00\u81f4\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L103"}, {"id": "api_public_rationale_114", "label": "Web \u7aef\u767b\u5f55\uff1a\u8d26\u53f7\u4e3a sys_user.user_no\uff0c\u5bc6\u7801\u4e3a sys_user.password\uff08bcrypt\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L114"}, {"id": "api_public_rationale_230", "label": "\u767b\u51fa\uff1a\u540a\u9500 Redis \u4f1a\u8bdd\uff08\u82e5\u5df2\u914d\u7f6e REDIS_HOST\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L230"}, {"id": "api_public_rationale_249", "label": "\u83b7\u53d6\u5f53\u524d\u7528\u6237\u4fe1\u606f\uff08\u4e0e sys_user \u5b57\u6bb5\u5bf9\u5e94\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilongLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_user_py", "label": "user.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L1"}, {"id": "crud_user_hash_password", "label": "_hash_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L18"}, {"id": "crud_user_usercrudcompat", "label": "_UserCRUDCompat", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L22"}, {"id": "crud_user_usercrudcompat_get_by_user_no", "label": ".get_by_user_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L23"}, {"id": "crud_user_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L38"}, {"id": "crud_user_list_users", "label": "list_users()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L58"}, {"id": "crud_user_get_user", "label": "get_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L109"}, {"id": "crud_user_list_post_ids_for_user", "label": "list_post_ids_for_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L117"}, {"id": "crud_user_set_user_post_ids_only", "label": "set_user_post_ids_only()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L127"}, {"id": "crud_user_list_user_ids_bound_to_post", "label": "list_user_ids_bound_to_post()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L159"}, {"id": "crud_user_sync_post_user_bindings", "label": "sync_post_user_bindings()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L174"}, {"id": "crud_user_get_user_with_relations", "label": "get_user_with_relations()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L202"}, {"id": "crud_user_user_no_exists", "label": "user_no_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L227"}, {"id": "crud_user_replace_associations", "label": "_replace_associations()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L236"}, {"id": "crud_user_create_user", "label": "create_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L287"}, {"id": "crud_user_update_user", "label": "update_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L346"}, {"id": "crud_user_soft_delete_user", "label": "soft_delete_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L401"}, {"id": "crud_user_reset_password", "label": "reset_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L411"}, {"id": "crud_user_change_password", "label": "change_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L421"}, {"id": "crud_user_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L440"}, {"id": "crud_user_rationale_1", "label": "\u7528\u6237 CRUD\uff08sys_user + sys_user_role + sys_user_post\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L1"}, {"id": "crud_user_rationale_134", "label": "\u4ec5\u66ff\u6362 sys_user_post\uff0c\u4e0d\u5f71\u54cd sys_user_role\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L134"}, {"id": "crud_user_rationale_181", "label": "\u5c06\u672c\u804c\u4f4d\u7ed1\u5b9a\u7684\u7528\u6237\u96c6\u5408\u8bbe\u4e3a user_ids\uff08\u53ea\u589e\u5220\u672c\u804c\u4f4d\uff0c\u4fdd\u7559\u7528\u6237\u5176\u5b83\u804c\u4f4d\u4e0e\u89d2\u8272\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py", "source_location": "L181"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_user_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.pyLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "label": "avatar_url.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1"}, {"id": "core_avatar_url_resolve_avatar_display_url", "label": "resolve_avatar_display_url()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L8"}, {"id": "core_avatar_url_extract_avatar_storage_key", "label": "extract_avatar_storage_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L27"}, {"id": "core_avatar_url_rationale_1", "label": "\u7528\u6237\u5934\u50cf URL \u89e3\u6790\uff08sys_user.avatar \u53ef\u80fd\u5b58 MinIO \u76f8\u5bf9\u8def\u5f84\u6216\u5b8c\u6574 URL\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1"}, {"id": "core_avatar_url_rationale_9", "label": "\u670d\u52a1\u7aef\u5185\u90e8\u62fc\u5b8c\u6574 URL\uff08\u90ae\u4ef6\u7b49\uff09\uff1bWeb API \u5e94\u8fd4\u56de\u5e93\u4e2d\u539f\u59cb\u8def\u5f84\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L9"}, {"id": "core_avatar_url_rationale_28", "label": "\u4ece upload \u8fd4\u56de\u503c\u6216\u5386\u53f2\u5b8c\u6574 URL \u4e2d\u63d0\u53d6 avatar/ \u76f8\u5bf9\u8def\u5f84\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L28"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "app_core_config", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "app_core_storage", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "core_avatar_url_resolve_avatar_display_url", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "target": "core_avatar_url_extract_avatar_storage_key", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L27", "weight": 1.0}, {"source": "core_avatar_url_rationale_1", "target": "users_wuzilong_work_00code_zkxw_backend_app_core_avatar_url_py", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L1", "weight": 1.0}, {"source": "core_avatar_url_rationale_9", "target": "core_avatar_url_resolve_avatar_display_url", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L9", "weight": 1.0}, {"source": "core_avatar_url_rationale_28", "target": "core_avatar_url_extract_avatar_storage_key", "relation": "rationale_for", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L28", "weight": 1.0}], "raw_calls": [{"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "strip", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L12"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "str", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L12"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "lower", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L15"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "startswith", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L16"}, {"caller_nid": "core_avatar_url_resolve_avatar_display_url", "callee": "startswith", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py", "source_location": "L16"}, {"caller_nid": "core_avatar_url_resolve_avataLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "label": "auth.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L1"}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L30"}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L35"}, {"id": "core_auth_session_key", "label": "_session_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L52"}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L56"}, {"id": "core_auth_store_session", "label": "store_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L60"}, {"id": "core_auth_revoke_session", "label": "revoke_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L68"}, {"id": "core_auth_extend_session", "label": "extend_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L76"}, {"id": "core_auth_is_session_valid", "label": "is_session_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L92"}, {"id": "core_auth_store_refresh_token", "label": "store_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L107"}, {"id": "core_auth_is_refresh_token_valid", "label": "is_refresh_token_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L115"}, {"id": "core_auth_revoke_refresh_token", "label": "revoke_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L127"}, {"id": "core_auth_create_access_token", "label": "create_access_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L134"}, {"id": "core_auth_create_refresh_token", "label": "create_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L158"}, {"id": "core_auth_decode_token", "label": "decode_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L174"}, {"id": "core_auth_get_current_user_by_token", "label": "get_current_user_by_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L187"}, {"id": "core_auth_get_current_user", "label": "get_current_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L248"}, {"id": "core_auth_get_current_user_simple", "label": "get_current_user_simple()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L256"}, {"id": "core_auth_get_client_ip", "label": "get_client_ip()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L275"}, {"id": "core_auth_rationale_77", "label": "\u5237\u65b0\u4f1a\u8bdd TTL\uff08refreshToken \u7eed\u671f\uff1b\u5df2\u767b\u5f55\u7528\u6237\u6bcf\u6b21 API \u6821\u9a8c\u901a\u8fc7\u540e\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L77"}, {"id": "core_auth_rationale_108", "label": "\u5199\u5165 refreshToken\uff08\u7528\u4e8e one-time \u4f7f\u7528/\u540a\u9500\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L108"}, {"id": "core_auth_rationale_191", "label": "\u6839\u636e token \u83b7\u53d6\u5f53\u524d\u7528\u6237\uff08\u5305\u542b Redis \u4f1a\u8bdd\u6821\u9a8c\uff1b\u4f1a\u8bdd\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L191"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "target": "asyncio", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_pLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_public_py", "label": "public.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_avatar_url_field", "label": "_avatar_url_field()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L36"}, {"id": "api_public_build_user_info_payload", "label": "_build_user_info_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L44"}, {"id": "api_public_build_current_user_payload", "label": "_build_current_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L62"}, {"id": "api_public_resolve_current_user_from_request", "label": "_resolve_current_user_from_request()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L84"}, {"id": "api_public_jwt_user_payload", "label": "_jwt_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L92"}, {"id": "api_public_web_login_rsa_public_key", "label": "web_login_rsa_public_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L103"}, {"id": "api_public_web_login", "label": "web_login()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L110"}, {"id": "api_public_refresh_token", "label": "refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L168"}, {"id": "api_public_logout", "label": "logout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L230"}, {"id": "api_public_get_current_user_profile", "label": "get_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L249"}, {"id": "api_public_update_current_user_profile", "label": "update_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L259"}, {"id": "api_public_change_current_user_password", "label": "change_current_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L294"}, {"id": "api_public_get_web_auth_menu_codes", "label": "get_web_auth_menu_codes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L322"}, {"id": "api_public_rationale_1", "label": "\u516c\u5171\u63a5\u53e3\uff08Web \u767b\u5f55\u3001\u5237\u65b0 Token\u3001\u767b\u51fa\uff1b\u7528\u6237\u6a21\u578b\u5bf9\u9f50 docs/sql/zkxw.sql \u57fa\u7ebf\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_rationale_45", "label": "\u4e0e web-admin `userInfo` \u5b57\u6bb5\u7ea6\u5b9a\u4e00\u81f4\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L45"}, {"id": "api_public_rationale_63", "label": "\u7ec4\u88c5 current-user \u63a5\u53e3\u54cd\u5e94\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L63"}, {"id": "api_public_rationale_104", "label": "Web \u7aef\u767b\u5f55\u7528 RSA \u516c\u94a5\uff08PKCS#1 v1.5\uff0c\u4e0e JSEncrypt \u4e00\u81f4\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L104"}, {"id": "api_public_rationale_115", "label": "Web \u7aef\u767b\u5f55\uff1a\u8d26\u53f7\u4e3a sys_user.user_no\uff0c\u5bc6\u7801\u4e3a sys_user.password\uff08bcrypt\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L115"}, {"id": "api_public_rationale_231", "label": "\u767b\u51fa\uff1a\u540a\u9500 Redis \u4f1a\u8bdd\uff08\u82e5\u5df2\u914d\u7f6e REDIS_HOST\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L231"}, {"id": "api_public_rationale_250", "label": "\u83b7\u53d6\u5f53\u524d\u7528\u6237\u4fe1\u606f\uff08\u4e0e sys_user \u5b57\u6bb5\u5bf9\u5e94\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L250"}, {"id": "api_public_rationale_264", "label": "\u5f53\u524d\u7528\u6237\u66f4\u65b0\u4e2a\u4eba\u4fe1\u606f\uff08\u624b\u673a\u53f7\u3001\u90aeLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_collection_protocol_py", "label": "collection_protocol.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L1"}, {"id": "crud_collection_protocol_get_protocol_nos_used_in_protocols", "label": "get_protocol_nos_used_in_protocols()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L52"}, {"id": "crud_collection_protocol_get_sample_codes_used_in_protocol_samples", "label": "get_sample_codes_used_in_protocol_samples()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L86"}, {"id": "crud_collection_protocol_validate_sample_codes_not_used", "label": "validate_sample_codes_not_used()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L120"}, {"id": "crud_collection_protocol_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L153"}, {"id": "crud_collection_protocol_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L159"}, {"id": "crud_collection_protocol_dec", "label": "_dec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L163"}, {"id": "crud_collection_protocol_optional_decimal", "label": "_optional_decimal()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L171"}, {"id": "crud_collection_protocol_today_yyyymmdd", "label": "_today_yyyymmdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L177"}, {"id": "crud_collection_protocol_normalize_yyyymmdd_date", "label": "_normalize_yyyymmdd_date()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L181"}, {"id": "crud_collection_protocol_normalize_fields", "label": "_normalize_fields()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L200"}, {"id": "crud_collection_protocol_pop_attachment_urls", "label": "_pop_attachment_urls()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L211"}, {"id": "crud_collection_protocol_attachments_to_urls", "label": "attachments_to_urls()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L222"}, {"id": "crud_collection_protocol_normalize_attachment_url_key", "label": "_normalize_attachment_url_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L241"}, {"id": "crud_collection_protocol_format_attachment_file_size", "label": "_format_attachment_file_size()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L250"}, {"id": "crud_collection_protocol_lookup_attachment_by_url", "label": "_lookup_attachment_by_url()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L258"}, {"id": "crud_collection_protocol_urls_to_attachment_list", "label": "urls_to_attachment_list()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L282"}, {"id": "crud_collection_protocol_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L314"}, {"id": "crud_collection_protocol_protocol_to_dict", "label": "_protocol_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L322"}, {"id": "crud_collection_protocol_payment_to_dict", "label": "_payment_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L347"}, {"id": "crud_collection_protocol_detail_to_dict", "label": "_detail_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py", "source_location": "L365"}, {"id": "crud_collection_protocol_audit_to_dict", "label": "_audit_to_dict()", "file_type": "code", "source_Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "label": "auth.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L1"}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L29"}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L34"}, {"id": "core_auth_session_key", "label": "_session_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L51"}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L55"}, {"id": "core_auth_store_session", "label": "store_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L59"}, {"id": "core_auth_revoke_session", "label": "revoke_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L67"}, {"id": "core_auth_extend_session", "label": "extend_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L75"}, {"id": "core_auth_is_session_valid", "label": "is_session_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L91"}, {"id": "core_auth_store_refresh_token", "label": "store_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L106"}, {"id": "core_auth_is_refresh_token_valid", "label": "is_refresh_token_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L114"}, {"id": "core_auth_revoke_refresh_token", "label": "revoke_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L126"}, {"id": "core_auth_create_access_token", "label": "create_access_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L133"}, {"id": "core_auth_create_refresh_token", "label": "create_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L157"}, {"id": "core_auth_decode_token", "label": "decode_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L173"}, {"id": "core_auth_get_current_user_by_token", "label": "get_current_user_by_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L186"}, {"id": "core_auth_get_current_user", "label": "get_current_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L251"}, {"id": "core_auth_get_current_user_simple", "label": "get_current_user_simple()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L259"}, {"id": "core_auth_get_client_ip", "label": "get_client_ip()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L278"}, {"id": "core_auth_rationale_76", "label": "\u5237\u65b0\u4f1a\u8bdd TTL\uff08refreshToken \u7eed\u671f\uff1b\u5df2\u767b\u5f55\u7528\u6237\u6bcf\u6b21 API \u6821\u9a8c\u901a\u8fc7\u540e\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L76"}, {"id": "core_auth_rationale_107", "label": "\u5199\u5165 refreshToken\uff08\u7528\u4e8e one-time \u4f7f\u7528/\u540a\u9500\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L107"}, {"id": "core_auth_rationale_190", "label": "\u6839\u636e token \u83b7\u53d6\u5f53\u524d\u7528\u6237\uff08\u5305\u542b Redis \u4f1a\u8bdd\u6821\u9a8c\uff1b\u4f1a\u8bdd\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L190"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "target": "asyncio", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_pLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "label": "auth.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L1"}, {"id": "core_auth_redis_session_enabled", "label": "_redis_session_enabled()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L29"}, {"id": "core_auth_get_redis_client", "label": "_get_redis_client()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L34"}, {"id": "core_auth_session_key", "label": "_session_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L51"}, {"id": "core_auth_refresh_key", "label": "_refresh_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L55"}, {"id": "core_auth_store_session", "label": "store_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L59"}, {"id": "core_auth_revoke_session", "label": "revoke_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L67"}, {"id": "core_auth_extend_session", "label": "extend_session()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L75"}, {"id": "core_auth_is_session_valid", "label": "is_session_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L91"}, {"id": "core_auth_store_refresh_token", "label": "store_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L106"}, {"id": "core_auth_is_refresh_token_valid", "label": "is_refresh_token_valid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L114"}, {"id": "core_auth_revoke_refresh_token", "label": "revoke_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L126"}, {"id": "core_auth_create_access_token", "label": "create_access_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L133"}, {"id": "core_auth_create_refresh_token", "label": "create_refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L157"}, {"id": "core_auth_decode_token", "label": "decode_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L173"}, {"id": "core_auth_get_current_user_by_token", "label": "get_current_user_by_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L186"}, {"id": "core_auth_get_current_user", "label": "get_current_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L247"}, {"id": "core_auth_get_current_user_simple", "label": "get_current_user_simple()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L255"}, {"id": "core_auth_get_client_ip", "label": "get_client_ip()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L274"}, {"id": "core_auth_rationale_76", "label": "\u5237\u65b0\u4f1a\u8bdd TTL\uff08refreshToken \u7eed\u671f\uff1b\u5df2\u767b\u5f55\u7528\u6237\u6bcf\u6b21 API \u6821\u9a8c\u901a\u8fc7\u540e\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L76"}, {"id": "core_auth_rationale_107", "label": "\u5199\u5165 refreshToken\uff08\u7528\u4e8e one-time \u4f7f\u7528/\u540a\u9500\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L107"}, {"id": "core_auth_rationale_190", "label": "\u6839\u636e token \u83b7\u53d6\u5f53\u524d\u7528\u6237\uff08\u5305\u542b Redis \u4f1a\u8bdd\u6821\u9a8c\uff1b\u4f1a\u8bdd\u6ed1\u52a8\u7eed\u671f\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L190"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_py", "target": "asyncio", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_auth_pLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L220"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L240"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L259"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L278"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L297"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L320"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L341"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L359"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L378"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L400"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L420"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L448"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L467"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "label": "protocol_payment_installment.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L1"}, {"id": "services_protocol_payment_installment_add_days_yyyymmdd", "label": "add_days_yyyymmdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L15"}, {"id": "services_protocol_payment_installment_add_months_yyyymmdd", "label": "add_months_yyyymmdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L28"}, {"id": "services_protocol_payment_installment_add_interval_months_yyyymmdd", "label": "add_interval_months_yyyymmdd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L43"}, {"id": "services_protocol_payment_installment_calc_fq_installment_due_date", "label": "calc_fq_installment_due_date()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L63"}, {"id": "services_protocol_payment_installment_rationale_1", "label": "\u5206\u671f\u7f34\u8d39\uff1a\u5e94\u7f34\u65e5\u8ba1\u7b97\uff08\u6574\u6570\u6708\u6309\u65e5\u5386\u9012\u589e\uff0c\u5c0f\u6570\u6708\u6309 30 \u5929/\u6708\u6362\u7b97\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L1"}, {"id": "services_protocol_payment_installment_rationale_44", "label": "\u6574\u6570\u90e8\u5206\u6309\u65e5\u5386\u52a0\u6708\uff0c\u5c0f\u6570\u90e8\u5206\u6309 30 \u5929/\u6708\u6362\u7b97\u4e3a\u5929\u6570\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L44"}, {"id": "services_protocol_payment_installment_rationale_68", "label": "\u7b2c 1 \u671f=\u5f00\u59cb\u65f6\u95f4\uff1b\u7b2c 2 \u671f\u8d77\u5728\u95f4\u9694\u9012\u589e\u57fa\u7840\u4e0a\u63d0\u524d 10 \u5929\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L68"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "calendar", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "services_protocol_payment_installment_add_days_yyyymmdd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "services_protocol_payment_installment_add_months_yyyymmdd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L28", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "services_protocol_payment_installment_add_interval_months_yyyymmdd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L43", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_services_protocol_payment_installment_py", "target": "services_protocol_payment_installment_calc_fq_installment_due_date", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py", "source_location": "L63", "weight": 1.0}, {"source": "services_protocol_payment_instalLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "label": "config.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L1"}, {"id": "core_config_settings", "label": "Settings", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L7"}, {"id": "basesettings", "label": "BaseSettings", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "core_config_config", "label": "Config", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L145"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "pydantic_settings", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "pathlib", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "os", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "core_config_settings", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L7", "weight": 1.0}, {"source": "core_config_settings", "target": "basesettings", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_core_config_py", "target": "core_config_config", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py", "source_location": "L145", "weight": 1.0}], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_public_py", "label": "public.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_avatar_url_field", "label": "_avatar_url_field()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L38"}, {"id": "api_public_build_user_info_payload", "label": "_build_user_info_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L46"}, {"id": "api_public_build_current_user_payload", "label": "_build_current_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L64"}, {"id": "api_public_resolve_current_user_from_request", "label": "_resolve_current_user_from_request()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L86"}, {"id": "api_public_jwt_user_payload", "label": "_jwt_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L94"}, {"id": "api_public_web_login_rsa_public_key", "label": "web_login_rsa_public_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L105"}, {"id": "api_public_web_login", "label": "web_login()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L112"}, {"id": "api_public_refresh_token", "label": "refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L170"}, {"id": "api_public_logout", "label": "logout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L232"}, {"id": "api_public_get_current_user_profile", "label": "get_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L251"}, {"id": "api_public_update_current_user_profile", "label": "update_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L261"}, {"id": "api_public_change_current_user_password", "label": "change_current_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L297"}, {"id": "api_public_upload_current_user_avatar", "label": "upload_current_user_avatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L329"}, {"id": "api_public_get_web_auth_menu_codes", "label": "get_web_auth_menu_codes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L365"}, {"id": "api_public_rationale_1", "label": "\u516c\u5171\u63a5\u53e3\uff08Web \u767b\u5f55\u3001\u5237\u65b0 Token\u3001\u767b\u51fa\uff1b\u7528\u6237\u6a21\u578b\u5bf9\u9f50 docs/sql/zkxw.sql \u57fa\u7ebf\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_rationale_47", "label": "\u4e0e web-admin `userInfo` \u5b57\u6bb5\u7ea6\u5b9a\u4e00\u81f4\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L47"}, {"id": "api_public_rationale_65", "label": "\u7ec4\u88c5 current-user \u63a5\u53e3\u54cd\u5e94\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L65"}, {"id": "api_public_rationale_106", "label": "Web \u7aef\u767b\u5f55\u7528 RSA \u516c\u94a5\uff08PKCS#1 v1.5\uff0c\u4e0e JSEncrypt \u4e00\u81f4\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L106"}, {"id": "api_public_rationale_117", "label": "Web \u7aef\u767b\u5f55\uff1a\u8d26\u53f7\u4e3a sys_user.user_no\uff0c\u5bc6\u7801\u4e3a sys_user.password\uff08bcrypt\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L117"}, {"id": "api_public_rationale_233", "label": "\u767b\u51fa\uff1a\u540a\u9500 Redis \u4f1a\u8bdd\uff08\u82e5\u5df2\u914d\u7f6e REDIS_HOST\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L233"}, {"id": "api_public_rationale_252", "label": "\u83b7\u53d6\u5f53\u524d\u7528\u6237\u4fe1\u606f\uff08\u4e0e sys_user \u5b57\u6bb5\u5bf9\u5e94\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilongLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_public_py", "label": "public.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_avatar_url_field", "label": "_avatar_url_field()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L39"}, {"id": "api_public_build_user_info_payload", "label": "_build_user_info_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L48"}, {"id": "api_public_build_current_user_payload", "label": "_build_current_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L66"}, {"id": "api_public_resolve_current_user_from_request", "label": "_resolve_current_user_from_request()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L88"}, {"id": "api_public_jwt_user_payload", "label": "_jwt_user_payload()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L96"}, {"id": "api_public_web_login_rsa_public_key", "label": "web_login_rsa_public_key()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L107"}, {"id": "api_public_web_login", "label": "web_login()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L114"}, {"id": "api_public_refresh_token", "label": "refresh_token()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L172"}, {"id": "api_public_logout", "label": "logout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L234"}, {"id": "api_public_get_current_user_profile", "label": "get_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L253"}, {"id": "api_public_update_current_user_profile", "label": "update_current_user_profile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L263"}, {"id": "api_public_change_current_user_password", "label": "change_current_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L299"}, {"id": "api_public_upload_current_user_avatar", "label": "upload_current_user_avatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L331"}, {"id": "api_public_get_web_auth_menu_codes", "label": "get_web_auth_menu_codes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L368"}, {"id": "api_public_rationale_1", "label": "\u516c\u5171\u63a5\u53e3\uff08Web \u767b\u5f55\u3001\u5237\u65b0 Token\u3001\u767b\u51fa\uff1b\u7528\u6237\u6a21\u578b\u5bf9\u9f50 docs/sql/zkxw.sql \u57fa\u7ebf\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_rationale_40", "label": "\u8fd4\u56de\u5e93\u4e2d\u539f\u59cb\u5934\u50cf\u8def\u5f84\uff0c\u7531\u524d\u7aef\u6309 VITE_MINIO_BASE_URL \u62fc\u5c55\u793a URL\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L40"}, {"id": "api_public_rationale_49", "label": "\u4e0e web-admin `userInfo` \u5b57\u6bb5\u7ea6\u5b9a\u4e00\u81f4\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L49"}, {"id": "api_public_rationale_67", "label": "\u7ec4\u88c5 current-user \u63a5\u53e3\u54cd\u5e94\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L67"}, {"id": "api_public_rationale_108", "label": "Web \u7aef\u767b\u5f55\u7528 RSA \u516c\u94a5\uff08PKCS#1 v1.5\uff0c\u4e0e JSEncrypt \u4e00\u81f4\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L108"}, {"id": "api_public_rationale_119", "label": "Web \u7aef\u767b\u5f55\uff1a\u8d26\u53f7\u4e3a sys_user.user_no\uff0c\u5bc6\u7801\u4e3a sys_user.password\uff08bcrypt\uff09\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py", "source_location": "L119"}, {"id": "api_public_rationale_235", "label": "\u767b\u51fa\uff1a\u540a\u9500 Redis \u4f1a\u8bdd\uff08\u82e5\u5df2\u914d\u7f6e REDIS_HOST\uff09\u3002", "file_type": "rationale", Line truncated
|
||||
@@ -824,7 +824,7 @@ class BizProtocolPayment(Base):
|
||||
pay_mode = Column(String(8), nullable=False, comment="dj趸交 fq分期")
|
||||
contract_amount = Column(Numeric(18, 2), nullable=True, comment="合同金额")
|
||||
installment_count = Column(Integer, nullable=True, comment="分期期数")
|
||||
installment_interval_months = Column(Integer, nullable=True, comment="每期间隔(月)")
|
||||
installment_interval_months = Column(Numeric(10, 2), nullable=True, comment="每期间隔(月)")
|
||||
lump_sum_deadline = Column(CHAR(8), nullable=True, comment="趸交截止时间YYYYMMDD")
|
||||
installment_start_date = Column(CHAR(8), nullable=True, comment="分期开始YYYYMMDD")
|
||||
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
"""Pydantic schemas - 用户认证"""
|
||||
from pydantic import BaseModel, Field
|
||||
from pydantic import BaseModel, Field, ConfigDict
|
||||
from typing import Optional
|
||||
from datetime import datetime
|
||||
|
||||
@@ -51,6 +51,17 @@ class ChangePasswordRequest(BaseModel):
|
||||
new_password: str = Field(..., min_length=6)
|
||||
|
||||
|
||||
class ProfileUpdateRequest(BaseModel):
|
||||
"""当前用户个人信息更新(仅允许自助修改的字段)"""
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
phone_no: Optional[str] = Field(None, alias="phoneNo", max_length=11)
|
||||
email: Optional[str] = Field(None, max_length=50)
|
||||
sex: Optional[str] = Field(None, pattern=r"^[012]$")
|
||||
remark: Optional[str] = Field(None, max_length=512)
|
||||
avatar: Optional[str] = Field(None, alias="avatarUrl", max_length=512)
|
||||
|
||||
|
||||
class ResetPasswordRequest(BaseModel):
|
||||
"""重置密码请求(运营操作)"""
|
||||
user_id: int
|
||||
@@ -0,0 +1,84 @@
|
||||
"""缴费模式切换校验(与前端 protocol-pay-mode-switch.ts 规则一致)"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
LOCKED_STATUSES = frozenset({"jfqrz", "yjf", "tfqrz", "ytf"})
|
||||
BLOCKING_STATUSES = frozenset({"jfqrz", "tfqrz", "ytf"})
|
||||
|
||||
|
||||
def _dec(v: Any) -> float:
|
||||
if v is None:
|
||||
return 0.0
|
||||
return float(Decimal(str(v)))
|
||||
|
||||
|
||||
def validate_payment_details_for_save(
|
||||
pay_mode: str,
|
||||
contract_amount: Optional[Any],
|
||||
installment_count: Optional[int],
|
||||
details: Optional[list],
|
||||
) -> None:
|
||||
"""保存缴费明细前的 P0 校验。"""
|
||||
rows = [dict(d) for d in (details or [])]
|
||||
contract = _dec(contract_amount)
|
||||
|
||||
for r in rows:
|
||||
status = (r.get("pay_status") or r.get("payStatus") or "dfj").strip()
|
||||
if status in BLOCKING_STATUSES:
|
||||
raise ValueError("存在缴费确认中或退费处理中的明细,无法保存")
|
||||
|
||||
paid_sum = sum(
|
||||
_dec(r.get("due_amount") if r.get("due_amount") is not None else r.get("dueAmount"))
|
||||
for r in rows
|
||||
if (r.get("pay_status") or r.get("payStatus")) == "yjf"
|
||||
)
|
||||
dfj_rows = [
|
||||
r
|
||||
for r in rows
|
||||
if (r.get("pay_status") or r.get("payStatus") or "dfj") == "dfj"
|
||||
]
|
||||
yjf_rows = [r for r in rows if (r.get("pay_status") or r.get("payStatus")) == "yjf"]
|
||||
|
||||
if pay_mode == "dj":
|
||||
if len(dfj_rows) > 1:
|
||||
raise ValueError("趸交模式仅允许一条待缴费明细")
|
||||
remaining = round(contract - paid_sum, 2)
|
||||
if dfj_rows:
|
||||
due = _dec(
|
||||
dfj_rows[0].get("due_amount")
|
||||
if dfj_rows[0].get("due_amount") is not None
|
||||
else dfj_rows[0].get("dueAmount")
|
||||
)
|
||||
expected = remaining if yjf_rows else contract
|
||||
if abs(due - expected) > 0.015:
|
||||
raise ValueError(
|
||||
f"趸交待缴金额应为 {expected:.2f},当前为 {due:.2f}"
|
||||
)
|
||||
|
||||
elif pay_mode == "fq":
|
||||
count = int(installment_count or 0)
|
||||
if count < 1:
|
||||
raise ValueError("分期模式须填写分期期数")
|
||||
if len(rows) != count:
|
||||
raise ValueError(f"分期明细条数应等于分期期数({count})")
|
||||
fq_forbidden = frozenset({"jfqrz", "tfqrz", "ytf"})
|
||||
for r in rows:
|
||||
status = (r.get("pay_status") or r.get("payStatus") or "dfj").strip()
|
||||
if status in fq_forbidden:
|
||||
raise ValueError("分期模式下存在不可保存的缴费状态")
|
||||
total_due = sum(
|
||||
_dec(r.get("due_amount") if r.get("due_amount") is not None else r.get("dueAmount"))
|
||||
for r in rows
|
||||
)
|
||||
if contract and abs(total_due - contract) > 0.015:
|
||||
raise ValueError("分期各期应缴金额之和应等于合同金额")
|
||||
if yjf_rows:
|
||||
max_paid_no = max(
|
||||
int(r.get("installment_no") or r.get("installmentNo") or 0)
|
||||
for r in yjf_rows
|
||||
)
|
||||
if max_paid_no > count:
|
||||
raise ValueError("分期期数不能少于已缴费的最大期次")
|
||||
@@ -0,0 +1,73 @@
|
||||
"""分期缴费:应缴日计算(整数月按日历递增,小数月按 30 天/月换算)"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import calendar
|
||||
from decimal import Decimal, ROUND_DOWN
|
||||
from typing import Union
|
||||
|
||||
Number = Union[int, float, Decimal, str]
|
||||
|
||||
DAYS_PER_MONTH = 30
|
||||
FQ_ADVANCE_DAYS = 10
|
||||
|
||||
|
||||
def add_days_yyyymmdd(date_str: str, days: int) -> str:
|
||||
raw = (date_str or "").strip().replace("-", "")
|
||||
if len(raw) != 8:
|
||||
return ""
|
||||
from datetime import date, timedelta
|
||||
|
||||
y = int(raw[0:4])
|
||||
m = int(raw[4:6])
|
||||
d = int(raw[6:8])
|
||||
dt = date(y, m, d) + timedelta(days=days)
|
||||
return f"{dt.year:04d}{dt.month:02d}{dt.day:02d}"
|
||||
|
||||
|
||||
def add_months_yyyymmdd(date_str: str, months: int) -> str:
|
||||
raw = (date_str or "").strip().replace("-", "")
|
||||
if len(raw) != 8:
|
||||
return ""
|
||||
y = int(raw[0:4])
|
||||
m = int(raw[4:6])
|
||||
d = int(raw[6:8])
|
||||
month_index = m - 1 + months
|
||||
ny = y + month_index // 12
|
||||
nm = month_index % 12 + 1
|
||||
last_day = calendar.monthrange(ny, nm)[1]
|
||||
nd = min(d, last_day)
|
||||
return f"{ny:04d}{nm:02d}{nd:02d}"
|
||||
|
||||
|
||||
def add_interval_months_yyyymmdd(date_str: str, total_months: Number) -> str:
|
||||
"""整数部分按日历加月,小数部分按 30 天/月换算为天数。"""
|
||||
raw = (date_str or "").strip().replace("-", "")
|
||||
if len(raw) != 8:
|
||||
return ""
|
||||
total = Decimal(str(total_months))
|
||||
if total == 0:
|
||||
return raw
|
||||
whole = int(total.to_integral_value(rounding=ROUND_DOWN))
|
||||
frac = total - Decimal(whole)
|
||||
result = raw
|
||||
if whole:
|
||||
result = add_months_yyyymmdd(result, whole)
|
||||
if frac:
|
||||
days = int(round(float(frac) * DAYS_PER_MONTH))
|
||||
if days:
|
||||
result = add_days_yyyymmdd(result, days)
|
||||
return result
|
||||
|
||||
|
||||
def calc_fq_installment_due_date(
|
||||
start_date: str,
|
||||
index: int,
|
||||
interval_months: Number,
|
||||
) -> str:
|
||||
"""第 1 期=开始时间;第 2 期起在间隔递增基础上提前 10 天。"""
|
||||
total_months = Decimal(str(index)) * Decimal(str(interval_months))
|
||||
base = add_interval_months_yyyymmdd(start_date, total_months)
|
||||
if index >= 1:
|
||||
return add_days_yyyymmdd(base, -FQ_ADVANCE_DAYS)
|
||||
return base
|
||||
File diff suppressed because it is too large.
Load diff
+2380
-1391
File diff suppressed because it is too large.
Load diff
@@ -1,12 +1,12 @@
|
||||
# Graph Report - app (2026-06-03)
|
||||
# Graph Report - app (2026-06-04)
|
||||
|
||||
## Corpus Check
|
||||
- 179 files · ~187,032 words
|
||||
- 181 files · ~187,864 words
|
||||
- Verdict: corpus is large enough that graph structure adds value.
|
||||
|
||||
## Summary
|
||||
- 3386 nodes · 15106 edges · 40 communities detected
|
||||
- Extraction: 37% EXTRACTED · 63% INFERRED · 0% AMBIGUOUS · INFERRED: 9448 edges (avg confidence: 0.61)
|
||||
- 3412 nodes · 15181 edges · 55 communities detected
|
||||
- Extraction: 38% EXTRACTED · 62% INFERRED · 0% AMBIGUOUS · INFERRED: 9487 edges (avg confidence: 0.61)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
@@ -44,17 +44,32 @@
|
||||
- [[_COMMUNITY_Community 31|Community 31]]
|
||||
- [[_COMMUNITY_Community 32|Community 32]]
|
||||
- [[_COMMUNITY_Community 33|Community 33]]
|
||||
- [[_COMMUNITY_Community 34|Community 34]]
|
||||
- [[_COMMUNITY_Community 35|Community 35]]
|
||||
- [[_COMMUNITY_Community 36|Community 36]]
|
||||
- [[_COMMUNITY_Community 37|Community 37]]
|
||||
- [[_COMMUNITY_Community 38|Community 38]]
|
||||
- [[_COMMUNITY_Community 39|Community 39]]
|
||||
- [[_COMMUNITY_Community 40|Community 40]]
|
||||
- [[_COMMUNITY_Community 41|Community 41]]
|
||||
- [[_COMMUNITY_Community 42|Community 42]]
|
||||
- [[_COMMUNITY_Community 43|Community 43]]
|
||||
- [[_COMMUNITY_Community 44|Community 44]]
|
||||
- [[_COMMUNITY_Community 45|Community 45]]
|
||||
- [[_COMMUNITY_Community 46|Community 46]]
|
||||
- [[_COMMUNITY_Community 47|Community 47]]
|
||||
- [[_COMMUNITY_Community 48|Community 48]]
|
||||
- [[_COMMUNITY_Community 51|Community 51]]
|
||||
- [[_COMMUNITY_Community 52|Community 52]]
|
||||
- [[_COMMUNITY_Community 53|Community 53]]
|
||||
- [[_COMMUNITY_Community 54|Community 54]]
|
||||
- [[_COMMUNITY_Community 55|Community 55]]
|
||||
- [[_COMMUNITY_Community 56|Community 56]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
1. `success_response()` - 524 edges
|
||||
2. `error_response()` - 424 edges
|
||||
3. `SysUser` - 359 edges
|
||||
1. `success_response()` - 527 edges
|
||||
2. `error_response()` - 427 edges
|
||||
3. `SysUser` - 363 edges
|
||||
4. `BizQcTaskResult` - 272 edges
|
||||
5. `BizQcMaterialUsage` - 264 edges
|
||||
6. `BizQcMaterial` - 262 edges
|
||||
@@ -68,215 +83,275 @@
|
||||
core/api_request_log_middleware.py → models/models.py
|
||||
- `get_menu_list()` --calls--> `success_response()` [INFERRED]
|
||||
api/menu.py → core/response.py
|
||||
- `公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线)` --uses--> `SysUser` [INFERRED]
|
||||
api/public.py → models/models.py
|
||||
- `与 web-admin `userInfo` 字段约定一致。` --uses--> `SysUser` [INFERRED]
|
||||
api/public.py → models/models.py
|
||||
- `Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致)` --uses--> `SysUser` [INFERRED]
|
||||
api/public.py → models/models.py
|
||||
- `中试服务交付管理 API(交付信息、交付物料、交付方式)` --uses--> `SysUser` [INFERRED]
|
||||
api/pilot_delivery.py → models/models.py
|
||||
- `保留匹配节点及其全部上级,供关键词检索后仍能正确组树。` --uses--> `SysDept` [INFERRED]
|
||||
crud/dept.py → models/models.py
|
||||
- `物品单位 CRUD(biz_item_unit)` --uses--> `BizItemUnit` [INFERRED]
|
||||
crud/item_unit.py → models/models.py
|
||||
|
||||
## Communities
|
||||
|
||||
### Community 0 - "Community 0"
|
||||
Cohesion: 0.01
|
||||
Nodes (633): attachment_download_url(), AttachmentDownloadUrlBody, create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu() (+625 more)
|
||||
Nodes (596): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+588 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.01
|
||||
Nodes (463): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+455 more)
|
||||
Nodes (523): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+515 more)
|
||||
|
||||
### Community 2 - "Community 2"
|
||||
Cohesion: 0.05
|
||||
Nodes (285): 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, Base (+277 more)
|
||||
Nodes (387): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+379 more)
|
||||
|
||||
### Community 3 - "Community 3"
|
||||
Cohesion: 0.02
|
||||
Nodes (205): generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status() (+197 more)
|
||||
Nodes (214): list_collection_regions(), list_protocol_nos(), _ensure_customer_for_mother(), _persist_protocol_sub_resources(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id() (+206 more)
|
||||
|
||||
### Community 4 - "Community 4"
|
||||
Cohesion: 0.07
|
||||
Nodes (223): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+215 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (178): generate_uuid(), _deduct_fee_on_delivery(), 创建交付时扣减费用。 流程: 1. schedule → plan → application 2. application.chan, activate_channel_agreement(), _apply_gmcp_order_quotas(), _apply_purchase_txn_holdings(), _apply_unsubscribe_txn_holdings(), _batch_gmcp_current_holding_amounts() (+170 more)
|
||||
|
||||
### Community 5 - "Community 5"
|
||||
Cohesion: 0.02
|
||||
Nodes (157): get_designer_data(), delete(), get_multi_with_filters(), create_cell_sample_type(), get_cell_sample_type(), list_cell_sample_types(), 细胞样本类型 CRUD(biz_cell_sample_type), _row_to_dict() (+149 more)
|
||||
Cohesion: 0.03
|
||||
Nodes (167): _format_attachment_file_size(), urls_to_attachment_list(), list_production_tasks(), apply_task_result(), complete_task(), _conclusion_label(), create_qc_task_manual(), create_task_for_line() (+159 more)
|
||||
|
||||
### Community 6 - "Community 6"
|
||||
Cohesion: 0.03
|
||||
Nodes (161): api_create_outbound_qc(), _format_attachment_file_size(), urls_to_attachment_list(), batch_review(), _fmt_dt(), get_schedule_detail(), _get_user_name(), list_reviews_paginated() (+153 more)
|
||||
Nodes (103): _avatar_url_field(), _build_current_user_payload(), _build_user_info_payload(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线) (+95 more)
|
||||
|
||||
### Community 7 - "Community 7"
|
||||
Cohesion: 0.03
|
||||
Nodes (144): api_save_application(), eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci(), _apply_submit_receipt() (+136 more)
|
||||
Nodes (108): get_protocol_nos_used_in_protocols(), create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), 字典类型 CRUD(sys_dict_type), _row_to_dict(), soft_delete_dict_type() (+100 more)
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.03
|
||||
Nodes (128): _persist_protocol_sub_resources(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), 数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3, 根据用户角色的数据权限过滤查询。 Args: query: SQLAlchemy query 对象 model: 查询, 从 SysUser 读取用户的 dept_id。 (+120 more)
|
||||
Nodes (63): _error_json(), 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, sqlalchemy_exception_handler(), unhandled_exception_handler(), BaseHTTPMiddleware, ApiCryptoError, _b64url_decode() (+55 more)
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.03
|
||||
Nodes (67): _error_json(), lifespan(), 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, sqlalchemy_exception_handler(), unhandled_exception_handler(), BaseHTTPMiddleware, ApiCryptoError (+59 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (94): api_save_application(), eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci(), auto_generate_schedules() (+86 more)
|
||||
|
||||
### Community 10 - "Community 10"
|
||||
Cohesion: 0.03
|
||||
Nodes (89): generate_id(), camel_to_snake(), CRUDBase, get_model_attr(), HistoryCRUD, get_protocol_nos_used_in_protocols(), create_dict_type(), dict_type_code_exists() (+81 more)
|
||||
Cohesion: 0.05
|
||||
Nodes (82): get_next_cell_product_code(), _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes() (+74 more)
|
||||
|
||||
### Community 11 - "Community 11"
|
||||
Cohesion: 0.06
|
||||
Nodes (87): AccessLogCreateBody, AccessLogUpdateBody, batch_create_storage_slots(), CleanRoomCreateBody, CleanRoomUpdateBody, create_access_log(), create_storage_slot(), delete_access_log() (+79 more)
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.35
|
||||
Nodes (61): BatchStockInBody, BatchStockInItem, BatchStockOutBody, BatchStockOutItem, ConsumableCreateBody, ConsumablePackCreateBody, ConsumablePackUpdateBody, ConsumableUpdateBody (+53 more)
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.07
|
||||
Nodes (62): batch_delete_research_donations(), change_donation_status(), convert_from_storage(), convert_to_storage(), create_research_donation(), delete_research_donation(), _get_current_user_id(), get_research_donation_detail() (+54 more)
|
||||
|
||||
### Community 13 - "Community 13"
|
||||
Cohesion: 0.06
|
||||
Nodes (57): _avatar_url_field(), _build_user_info_payload(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。 (+49 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (51): get_designer_data(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, 审批意见:前端传 commentText,兼容 comment。, StartInstanceBody, TaskActionBody, list_results_by_task() (+43 more)
|
||||
|
||||
### Community 14 - "Community 14"
|
||||
Cohesion: 0.06
|
||||
Nodes (60): get_next_cell_product_code(), _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes() (+52 more)
|
||||
Cohesion: 0.16
|
||||
Nodes (32): _create_insurance_company(), _create_insurance_company_invoice(), _create_insurance_project_price(), delete_insurance_company(), delete_insurance_company_invoice(), delete_insurance_project_price(), _fmt_dt(), _generate_uuid() (+24 more)
|
||||
|
||||
### Community 15 - "Community 15"
|
||||
Cohesion: 0.08
|
||||
Nodes (55): batch_delete_research_donations(), change_donation_status(), convert_from_storage(), convert_to_storage(), create_research_donation(), delete_research_donation(), _get_current_user_id(), get_research_donation_detail() (+47 more)
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 0.12
|
||||
Nodes (30): _apply_qc_status_filter(), _base_query(), _derive_qc_conclusion(), _ensure_notification(), _eq_ci(), _fetch_completed_tasks(), _fmt_dt(), generate_sms_content() (+22 more)
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 0.12
|
||||
Nodes (11): get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.ht, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total, 申请退款 Args: out_trade_no: 商户订单号 total_amount, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 tot, 生成签名 V3 (SHA256 with RSA) (+3 more)
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 0.16
|
||||
Nodes (26): add_step(), copy_step(), create_route(), _create_step_consumable(), _create_step_data_collection(), _create_step_output(), _create_step_reagent(), get_route() (+18 more)
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 0.14
|
||||
Nodes (23): batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status(), list_consumables() (+15 more)
|
||||
|
||||
### Community 18 - "Community 18"
|
||||
Cohesion: 0.13
|
||||
Nodes (18): _access_log_to_dict(), create_access_log(), create_clean_room(), get_access_log(), get_clean_room(), list_access_logs(), list_clean_rooms(), room_code_exists() (+10 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 0.16
|
||||
Nodes (19): get_by_schedule(), get_method(), _get_tenant_no(), list_by_application(), list_materials(), 中试服务交付管理 API(交付信息、交付物料、交付方式), soft_delete(), create_delivery() (+11 more)
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 0.21
|
||||
Nodes (19): _consumable_row_to_dict(), create_process(), _create_sub_consumable(), _create_sub_data_collection(), _create_sub_output(), _create_sub_reagent(), _data_collection_row_to_dict(), get_process() (+11 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 0.18
|
||||
Nodes (18): company_code_exists(), create_company(), get_company(), list_companies(), list_company_options(), _row_to_dict(), soft_delete_company(), update_company() (+10 more)
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 0.25
|
||||
Nodes (13): code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials(), _norm_status(), options_list() (+5 more)
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
Cohesion: 0.21
|
||||
Nodes (16): batch_stock_in(), batch_stock_out(), _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), list_materials() (+8 more)
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
Cohesion: 0.25
|
||||
Nodes (14): batch_stock_in(), batch_stock_out(), create_reagent(), _dec(), get_reagent(), _is_enabled_status(), list_reagents(), _norm_status() (+6 more)
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.2
|
||||
Nodes (14): deduct_for_task(), _display_remark(), list_usages(), list_usages_by_task(), _parse_receiver_purpose_from_remark(), 查询质检任务关联的物料使用记录(task_complete)。, 撤销任务此前 task_complete 扣减,便于重新填报物料使用。, 兼容旧数据:领用人/用途曾拼接在 remark 中。 (+6 more)
|
||||
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 0.25
|
||||
Nodes (13): batch_issue_protocol_nos(), batch_revoke_protocol_nos(), create_protocol_no(), get_protocol_no(), list_protocol_nos(), _parse_issued_time(), protocol_no_exists(), 采集协议号池 CRUD(biz_collection_protocol_no) (+5 more)
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
### Community 25 - "Community 25"
|
||||
Cohesion: 0.24
|
||||
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import Wech, 发送模板消息 Args: openid: 用户openid templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.24
|
||||
Nodes (9): _ensure_customer_for_mother(), create_customer(), get_customer(), id_card_taken(), list_customers(), 客户 CRUD(biz_customer), _row_to_dict(), soft_delete_customer() (+1 more)
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.23
|
||||
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
|
||||
|
||||
### Community 24 - "Community 24"
|
||||
### Community 27 - "Community 27"
|
||||
Cohesion: 0.27
|
||||
Nodes (11): create_consumable_pack(), get_consumable_pack(), get_pack_detail(), _item_row_to_dict(), list_all_packs(), list_consumable_packs(), pack_code_exists(), 耗材包 CRUD(biz_consumable_pack + biz_consumable_pack_item) (+3 more)
|
||||
|
||||
### Community 28 - "Community 28"
|
||||
Cohesion: 0.24
|
||||
Nodes (12): appointment_no_exists(), create_exhibition_appointment(), _format_visit_date(), _generate_appointment_no(), get_exhibition_appointment(), list_exhibition_appointments(), 展览预约 CRUD(biz_exhibition_appointment), 生成预约编号:YYYYMMDD + 6位序号(如 20260515000001) (+4 more)
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 0.24
|
||||
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 试剂变动记录 CRUD(biz_reagent_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减试剂库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
Cohesion: 0.27
|
||||
Nodes (11): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), 保留匹配节点及其全部上级,供关键词检索后仍能正确组树。 (+3 more)
|
||||
|
||||
### Community 31 - "Community 31"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_sop_document(), get_sop_document(), list_sop_documents(), SOP文档 CRUD(biz_sop_document), _row_to_dict(), soft_delete_sop_document(), sop_code_exists(), update_sop_document()
|
||||
|
||||
### Community 32 - "Community 32"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_express_company(), express_code_exists(), get_express_company(), list_express_companies(), 快递公司 CRUD(biz_express_company), _row_to_dict(), soft_delete_express_company(), update_express_company()
|
||||
|
||||
### Community 33 - "Community 33"
|
||||
Cohesion: 0.38
|
||||
Nodes (9): create_check_item(), get_check_item(), item_code_exists(), list_active_check_items(), list_check_items(), _order_query(), _row_to_dict(), soft_delete_check_item() (+1 more)
|
||||
|
||||
### Community 25 - "Community 25"
|
||||
### Community 34 - "Community 34"
|
||||
Cohesion: 0.27
|
||||
Nodes (8): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), 字典数据 CRUD(sys_dict_data), _row_to_dict(), soft_delete_dict_data(), update_dict_data()
|
||||
|
||||
### Community 35 - "Community 35"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): category_code_exists(), create_process_category(), get_process_category(), list_process_categories(), 工艺工序分类 CRUD(biz_process_category), _row_to_dict(), soft_delete_process_category(), update_process_category()
|
||||
|
||||
### Community 36 - "Community 36"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_item_unit(), get_item_unit(), list_item_units(), 物品单位 CRUD(biz_item_unit), _row_to_dict(), soft_delete_item_unit(), unit_code_exists(), update_item_unit()
|
||||
|
||||
### Community 37 - "Community 37"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_cell_sample_type(), get_cell_sample_type(), list_cell_sample_types(), 细胞样本类型 CRUD(biz_cell_sample_type), _row_to_dict(), soft_delete_cell_sample_type(), type_code_exists(), update_cell_sample_type()
|
||||
|
||||
### Community 38 - "Community 38"
|
||||
Cohesion: 0.31
|
||||
Nodes (8): create_output_type(), get_output_type(), list_output_types(), 工艺产出物类型 CRUD(biz_output_type), _row_to_dict(), soft_delete_output_type(), type_code_exists(), update_output_type()
|
||||
|
||||
### Community 39 - "Community 39"
|
||||
Cohesion: 0.36
|
||||
Nodes (9): deduct_for_task(), _display_remark(), list_usages(), list_usages_by_task(), _parse_receiver_purpose_from_remark(), _resolve_receiver_purpose(), revert_task_material_usages(), _row_to_dict() (+1 more)
|
||||
Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
|
||||
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.39
|
||||
Nodes (8): create_lab_item(), get_lab_item(), item_code_exists(), list_active_lab_items(), list_lab_items(), _row_to_dict(), soft_delete_lab_item(), update_lab_item()
|
||||
### Community 40 - "Community 40"
|
||||
Cohesion: 0.33
|
||||
Nodes (7): _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), _row_to_dict(), soft_delete_menu(), update_menu()
|
||||
|
||||
### Community 27 - "Community 27"
|
||||
### Community 41 - "Community 41"
|
||||
Cohesion: 0.36
|
||||
Nodes (7): create_site(), get_site(), list_sites(), _row_to_dict(), site_code_exists(), soft_delete_site(), update_site()
|
||||
|
||||
### Community 42 - "Community 42"
|
||||
Cohesion: 0.29
|
||||
Nodes (2): BaseModel, SoftDeleteModel
|
||||
|
||||
### Community 28 - "Community 28"
|
||||
### Community 43 - "Community 43"
|
||||
Cohesion: 0.38
|
||||
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
### Community 44 - "Community 44"
|
||||
Cohesion: 0.5
|
||||
Nodes (3): BaseSettings, Config, Settings
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
### Community 45 - "Community 45"
|
||||
Cohesion: 0.5
|
||||
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
|
||||
|
||||
### Community 31 - "Community 31"
|
||||
### Community 46 - "Community 46"
|
||||
Cohesion: 0.67
|
||||
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,13 个一级菜单)
|
||||
|
||||
### Community 32 - "Community 32"
|
||||
### Community 47 - "Community 47"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
|
||||
|
||||
### Community 33 - "Community 33"
|
||||
### Community 48 - "Community 48"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
|
||||
|
||||
### Community 36 - "Community 36"
|
||||
### Community 51 - "Community 51"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 37 - "Community 37"
|
||||
### Community 52 - "Community 52"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 38 - "Community 38"
|
||||
### Community 53 - "Community 53"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
|
||||
|
||||
### Community 39 - "Community 39"
|
||||
### Community 54 - "Community 54"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
|
||||
|
||||
### Community 40 - "Community 40"
|
||||
### Community 55 - "Community 55"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
### Community 56 - "Community 56"
|
||||
Cohesion: 1.0
|
||||
Nodes (1): 发送催单通知给配送员 Args: deliver_openid: 配送员openid
|
||||
|
||||
## Knowledge Gaps
|
||||
- **99 isolated node(s):** `刷新会话 TTL(refreshToken 续期;已登录用户每次 API 校验通过后滑动续期)`, `写入 refreshToken(用于 one-time 使用/吊销)`, `根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期)`, `登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。`, `Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。` (+94 more)
|
||||
- **106 isolated node(s):** `刷新会话 TTL(refreshToken 续期;已登录用户每次 API 校验通过后滑动续期)`, `写入 refreshToken(用于 one-time 使用/吊销)`, `根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期)`, `登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。`, `Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。` (+101 more)
|
||||
These have ≤1 connection - possible missing edges or undocumented components.
|
||||
- **Thin community `Community 27`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
|
||||
- **Thin community `Community 42`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 30`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
|
||||
- **Thin community `Community 45`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 31`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,13 个一级菜单)`
|
||||
- **Thin community `Community 46`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,13 个一级菜单)`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 32`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
|
||||
- **Thin community `Community 47`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 33`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
|
||||
- **Thin community `Community 48`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 36`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 51`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 37`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 52`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 38`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
|
||||
- **Thin community `Community 53`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 39`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
|
||||
- **Thin community `Community 54`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 40`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
|
||||
- **Thin community `Community 55`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 41`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
|
||||
- **Thin community `Community 56`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
|
||||
## Suggested Questions
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `SysUser` connect `Community 1` to `Community 0`, `Community 2`, `Community 4`, `Community 7`, `Community 8`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 15`, `Community 16`, `Community 21`?**
|
||||
_High betweenness centrality (0.113) - this node is a cross-community bridge._
|
||||
- **Why does `generate_uuid()` connect `Community 3` to `Community 0`, `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 18`, `Community 19`, `Community 20`, `Community 21`, `Community 23`, `Community 24`, `Community 25`, `Community 26`?**
|
||||
_High betweenness centrality (0.073) - this node is a cross-community bridge._
|
||||
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 11`, `Community 13`, `Community 14`, `Community 15`, `Community 31`?**
|
||||
_High betweenness centrality (0.067) - this node is a cross-community bridge._
|
||||
- **Are the 523 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
|
||||
_`success_response()` has 523 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 514 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `extract_login_credentials()`) actually correct?**
|
||||
_`str` has 514 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 423 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
|
||||
_`error_response()` has 423 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 357 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
|
||||
_`SysUser` has 357 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Why does `SysUser` connect `Community 1` to `Community 0`, `Community 2`, `Community 3`, `Community 4`, `Community 6`, `Community 7`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 17`, `Community 19`, `Community 23`, `Community 24`, `Community 29`?**
|
||||
_High betweenness centrality (0.117) - this node is a cross-community bridge._
|
||||
- **Why does `generate_uuid()` connect `Community 4` to `Community 0`, `Community 1`, `Community 2`, `Community 3`, `Community 5`, `Community 6`, `Community 7`, `Community 9`, `Community 10`, `Community 12`, `Community 13`, `Community 16`, `Community 17`, `Community 18`, `Community 20`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`, `Community 39`, `Community 40`, `Community 41`?**
|
||||
_High betweenness centrality (0.069) - this node is a cross-community bridge._
|
||||
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 3`, `Community 6`, `Community 9`, `Community 10`, `Community 12`, `Community 13`, `Community 46`, `Community 14`, `Community 19`?**
|
||||
_High betweenness centrality (0.068) - this node is a cross-community bridge._
|
||||
- **Are the 526 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
|
||||
_`success_response()` has 526 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 521 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `get_current_user_by_token()`) actually correct?**
|
||||
_`str` has 521 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 426 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
|
||||
_`error_response()` has 426 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 361 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
|
||||
_`SysUser` has 361 INFERRED edges - model-reasoned connections that need verification._
|
||||
@@ -57,12 +57,12 @@
|
||||
</div>
|
||||
<div id="legend"></div>
|
||||
</div>
|
||||
<div id="stats">3386 nodes · 15106 edges · 46 communities</div>
|
||||
<div id="stats">3412 nodes · 15181 edges · 61 communities</div>
|
||||
</div>
|
||||
<script>
|
||||
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#59A14F", "border": "#59A14F", "highlight": {"background": "#ffffff", "border": "#59A14F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 34, "community_name": "Community 34", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 7}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_error_json", "label": "_error_json()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "_error_json()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 3}, {"id": "app_main_sqlalchemy_exception_handler", "label": "sqlalchemy_exception_handler()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "sqlalchemy_exception_handler()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_unhandled_exception_handler", "label": "unhandled_exception_handler()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "unhandled_exception_handler()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 5}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_rationale_81", "label": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "app_main_rationale_92", "label": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 9, "community_name": "Community 9", "source_file": "tasks/__init__.py", "file_type": "code", "degLine truncated
|
||||
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_error_json", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_sqlalchemy_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_unhandled_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_error_json", "to": "app_main_sqlalchemy_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_error_json", "to": "app_main_unhandled_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "app_main_rationale_81", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "app_main_rationale_92", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_unhandled_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "str", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "labeLine truncated
|
||||
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 656}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 499}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 291}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 226}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 225}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 198}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 175}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 153}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 151}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 121}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 112}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 92}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 68}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 64}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 64}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 59}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 34}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 31}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 21}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 20}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 15}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 15}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 12}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 10}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 10}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 9}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 8}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 7}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 4}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 4}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 3}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 2}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 2}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 1}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 1}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 1}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 1}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 1}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 1}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 1}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 1}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 1}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 1}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 1}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 1}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 0}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 0}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 0}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 0}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 0}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 0}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 0}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 0}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 0}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 0}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 0}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 0}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 0}];
|
||||
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 49, "community_name": "Community 49", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 7}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 6, "community_name": "Community 6", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_error_json", "label": "_error_json()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "_error_json()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 3}, {"id": "app_main_sqlalchemy_exception_handler", "label": "sqlalchemy_exception_handler()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "sqlalchemy_exception_handler()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_unhandled_exception_handler", "label": "unhandled_exception_handler()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "unhandled_exception_handler()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 5}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_rationale_81", "label": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "app_main_rationale_92", "label": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "community": 8, "community_name": "Community 8", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 6, "community_name": "Community 6", "source_file": "tasks/__init__.py", "file_type": "code", "degLine truncated
|
||||
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_error_json", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_sqlalchemy_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_unhandled_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_error_json", "to": "app_main_sqlalchemy_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_error_json", "to": "app_main_unhandled_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "app_main_rationale_81", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "app_main_rationale_92", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_unhandled_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "str", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "labeLine truncated
|
||||
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 620}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 558}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 393}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 253}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 187}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 181}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 124}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 123}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 115}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 99}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 88}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 68}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 67}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 64}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 33}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 31}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 28}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 27}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 22}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 22}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 21}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 17}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 16}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 15}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 15}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 13}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 13}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 13}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 13}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 12}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 12}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 10}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 10}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 10}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 10}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 9}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 9}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 9}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 8}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 7}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 4}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 4}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 3}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 2}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 2}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 1}];
|
||||
|
||||
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
|
||||
function esc(s) {
|
||||
|
||||
+4707
-3573
File diff suppressed because it is too large.
Load diff
@@ -2,12 +2,13 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/__init__.py": 1778578257.989357,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/main.py": 1780457411.2283201,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/tasks/__init__.py": 1778579841.437791,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py": 1779245791.6811426,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/auth.py": 1780540737.3359916,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/api_crypto.py": 1778578258.039314,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/login_crypto.py": 1778578258.041774,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py": 1779313263.9269438,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/config.py": 1780539434.4590578,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/wechat_pay.py": 1778578258.0461762,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/api_request_log_middleware.py": 1779882001.753267,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/avatar_url.py": 1780540753.5481932,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/database.py": 1779242347.136184,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/security.py": 1778578258.044949,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/request_payload.py": 1778578258.04292,
|
||||
@@ -26,7 +27,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/core/wechat_message.py": 1778578258.0458734,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/material.py": 1779283385.245847,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_param.py": 1779022399.0175831,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1780462850.084297,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1780545639.1395557,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/__init__.py": 1779418058.876012,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/research_donation.py": 1780458012.8329656,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py": 1779928228.734251,
|
||||
@@ -35,7 +36,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/storage_release_review.py": 1779491680.5729434,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/qc_task.py": 1779597960.4337523,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/process_route.py": 1779367496.1718137,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py": 1778578258.0939043,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/auth.py": 1780539434.444314,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/delivery.py": 1778578258.0949655,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/outbound_release_review.py": 1779968230.0408957,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/price_list.py": 1778578258.096609,
|
||||
@@ -76,7 +77,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_release_review.py": 1779968239.1429183,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/post.py": 1779265648.38155,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_check_result.py": 1779255909.8554008,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py": 1778775532.8870275,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/user.py": 1780539127.1805215,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_work_order.py": 1780479191.5054278,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material.py": 1779283386.3879013,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dict_type.py": 1779265621.5212462,
|
||||
@@ -89,7 +90,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_task.py": 1779927441.9434412,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_item.py": 1779265661.482352,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py": 1779512669.9847593,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1780479210.0456562,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1780545654.7291799,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py": 1779332036.2049248,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/biz_no_generator.py": 1779882385.4674172,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_infusion_confirm.py": 1779828818.7646794,
|
||||
@@ -146,7 +147,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/clinical_payment.py": 1779969576.9773977,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/storage_release_review.py": 1779526635.1455016,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/outbound_release_review.py": 1779968232.5759368,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py": 1779313409.0685387,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py": 1780540754.892583,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py": 1779526648.041865,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py": 1779965447.565143,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/api/collection_protocol.py": 1779882422.004045,
|
||||
@@ -177,5 +178,6 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_callback.py": 1778727966.7277644,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/services/workflow_engine.py": 1778634664.6293883,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/services/web_auth_roles.py": 1778775532.8878627,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/services/protocol_payment_installment.py": 1780545628.43657,
|
||||
"/Users/wuzilong/work/00code/zkxw/backend/app/ws/__init__.py": 1778578258.105995
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
"""缴费模式切换校验"""
|
||||
|
||||
import unittest
|
||||
|
||||
from app.services.protocol_pay_mode_switch import validate_payment_details_for_save
|
||||
|
||||
|
||||
class TestValidatePaymentDetailsForSave(unittest.TestCase):
|
||||
def test_dj_single_dfj_full_contract(self):
|
||||
validate_payment_details_for_save(
|
||||
"dj",
|
||||
10000,
|
||||
None,
|
||||
[{"payStatus": "dfj", "dueAmount": 10000}],
|
||||
)
|
||||
|
||||
def test_dj_rejects_multiple_dfj(self):
|
||||
with self.assertRaises(ValueError) as ctx:
|
||||
validate_payment_details_for_save(
|
||||
"dj",
|
||||
10000,
|
||||
None,
|
||||
[
|
||||
{"payStatus": "dfj", "dueAmount": 5000},
|
||||
{"payStatus": "dfj", "dueAmount": 5000},
|
||||
],
|
||||
)
|
||||
self.assertIn("仅允许一条待缴费", str(ctx.exception))
|
||||
|
||||
def test_dj_partial_paid_remaining(self):
|
||||
validate_payment_details_for_save(
|
||||
"dj",
|
||||
10000,
|
||||
None,
|
||||
[
|
||||
{"payStatus": "yjf", "dueAmount": 2000},
|
||||
{"payStatus": "dfj", "dueAmount": 8000},
|
||||
],
|
||||
)
|
||||
|
||||
def test_dj_partial_paid_wrong_remaining(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validate_payment_details_for_save(
|
||||
"dj",
|
||||
10000,
|
||||
None,
|
||||
[
|
||||
{"payStatus": "yjf", "dueAmount": 2000},
|
||||
{"payStatus": "dfj", "dueAmount": 10000},
|
||||
],
|
||||
)
|
||||
|
||||
def test_fq_count_mismatch(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validate_payment_details_for_save(
|
||||
"fq",
|
||||
6000,
|
||||
6,
|
||||
[{"payStatus": "dfj", "dueAmount": 6000}],
|
||||
)
|
||||
|
||||
def test_fq_partial_paid_valid(self):
|
||||
validate_payment_details_for_save(
|
||||
"fq",
|
||||
10000,
|
||||
4,
|
||||
[
|
||||
{"payStatus": "yjf", "installmentNo": 1, "dueAmount": 2500},
|
||||
{"payStatus": "yjf", "installmentNo": 2, "dueAmount": 2500},
|
||||
{"payStatus": "dfj", "installmentNo": 3, "dueAmount": 2500},
|
||||
{"payStatus": "dfj", "installmentNo": 4, "dueAmount": 2500},
|
||||
],
|
||||
)
|
||||
|
||||
def test_fq_jfqrz_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validate_payment_details_for_save(
|
||||
"fq",
|
||||
6000,
|
||||
2,
|
||||
[
|
||||
{"payStatus": "jfqrz", "dueAmount": 3000},
|
||||
{"payStatus": "dfj", "dueAmount": 3000},
|
||||
],
|
||||
)
|
||||
|
||||
def test_fq_ytf_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validate_payment_details_for_save(
|
||||
"fq",
|
||||
6000,
|
||||
2,
|
||||
[
|
||||
{"payStatus": "ytf", "dueAmount": 3000},
|
||||
{"payStatus": "dfj", "dueAmount": 3000},
|
||||
],
|
||||
)
|
||||
|
||||
def test_blocking_status_rejected(self):
|
||||
with self.assertRaises(ValueError):
|
||||
validate_payment_details_for_save(
|
||||
"dj",
|
||||
10000,
|
||||
None,
|
||||
[{"payStatus": "jfqrz", "dueAmount": 10000}],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -0,0 +1,44 @@
|
||||
"""分期应缴日:小数月间隔(30 天/月)与提前 10 天规则"""
|
||||
|
||||
import unittest
|
||||
|
||||
from app.services.protocol_payment_installment import calc_fq_installment_due_date
|
||||
|
||||
|
||||
class TestCalcFqInstallmentDueDate(unittest.TestCase):
|
||||
def test_first_period_equals_start_date(self):
|
||||
self.assertEqual(calc_fq_installment_due_date("20260604", 0, 0.5), "20260604")
|
||||
|
||||
def test_fractional_interval_half_month_six_periods(self):
|
||||
start = "20260604"
|
||||
interval = 0.5
|
||||
expected = [
|
||||
"20260604",
|
||||
"20260609",
|
||||
"20260624",
|
||||
"20260709",
|
||||
"20260725",
|
||||
"20260809",
|
||||
]
|
||||
for i, exp in enumerate(expected):
|
||||
self.assertEqual(
|
||||
calc_fq_installment_due_date(start, i, interval),
|
||||
exp,
|
||||
msg=f"period {i + 1}",
|
||||
)
|
||||
|
||||
def test_fractional_interval_0_1_advance_10_days(self):
|
||||
# +3 天 = 20260607,再提前 10 天
|
||||
self.assertEqual(calc_fq_installment_due_date("20260604", 1, 0.1), "20260528")
|
||||
|
||||
def test_integer_interval_six_months(self):
|
||||
# +6 日历月 = 20261204,再提前 10 天
|
||||
self.assertEqual(calc_fq_installment_due_date("20260604", 1, 6), "20261124")
|
||||
|
||||
def test_fractional_interval_0_3(self):
|
||||
# index=2 → 0.6 月 → 18 天 → 20260622,再提前 10 天
|
||||
self.assertEqual(calc_fq_installment_due_date("20260604", 2, 0.3), "20260612")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -144,6 +144,7 @@ zkxw-docker-deploy-<版本>/
|
||||
│ └── mysql/init/
|
||||
├── docs/sql/zkxw.sql # 首次部署自动建库用
|
||||
├── 部署说明.md
|
||||
├── 部署指导手册.html # 客户安装手册(浏览器打开,推荐交付)
|
||||
└── VERSION.txt
|
||||
```
|
||||
|
||||
@@ -412,6 +413,10 @@ docker compose up -d
|
||||
### 发版方打包时 pip / pnpm 很慢或超时
|
||||
|
||||
- 已默认 **阿里云 PyPI** + **npmmirror**,并启用 BuildKit 缓存。
|
||||
- 若前端构建在 `corepack prepare pnpm@...` 报错(请求 `registry.npmjs.org` 失败),请更新到含 `COREPACK_NPM_REGISTRY` 的 Dockerfile,或手动指定:
|
||||
```bash
|
||||
NPM_REGISTRY=https://registry.npmmirror.com ./scripts/package-docker-deploy.sh v1.0.0
|
||||
```
|
||||
- **在 Mac(M 芯片)上交叉构建 `linux/amd64` 很慢**(后端 pip 常见 15~40 分钟),日志会长时间不动,**不要误按 Ctrl+C**。
|
||||
- **推荐**:把仓库放到 **Linux x86 云主机**(与甲方同架构),在该机器执行 `./scripts/package-docker-deploy.sh`,通常 5~15 分钟完成。
|
||||
|
||||
|
||||
@@ -5,6 +5,8 @@ ARG NGINX_IMAGE=docker.m.daocloud.io/library/nginx:1.27-alpine
|
||||
FROM ${NODE_IMAGE} AS builder
|
||||
|
||||
ARG NPM_REGISTRY=https://registry.npmmirror.com
|
||||
# corepack 默认走 registry.npmjs.org,国内/受限网络会失败;须显式指定镜像
|
||||
ENV COREPACK_NPM_REGISTRY=${NPM_REGISTRY}
|
||||
|
||||
RUN corepack enable && corepack prepare pnpm@9.15.4 --activate
|
||||
|
||||
|
||||
@@ -0,0 +1,499 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>中科兴皖 Docker 部署指导手册</title>
|
||||
<style>
|
||||
:root {
|
||||
--primary: #10b981;
|
||||
--primary-dark: #059669;
|
||||
--primary-bg: #ecfdf5;
|
||||
--text: #0f172a;
|
||||
--text-muted: #64748b;
|
||||
--border: #e2e8f0;
|
||||
--warn-bg: #fffbeb;
|
||||
--warn-border: #f59e0b;
|
||||
--danger-bg: #fef2f2;
|
||||
--danger-border: #ef4444;
|
||||
--code-bg: #f8fafc;
|
||||
--radius: 10px;
|
||||
--font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC",
|
||||
"Hiragino Sans GB", "Microsoft YaHei", sans-serif;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-behavior: smooth; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--font);
|
||||
font-size: 15px;
|
||||
line-height: 1.65;
|
||||
color: var(--text);
|
||||
background: #f1f5f9;
|
||||
}
|
||||
.layout {
|
||||
display: grid;
|
||||
grid-template-columns: 260px 1fr;
|
||||
min-height: 100vh;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 40px rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
@media (max-width: 900px) {
|
||||
.layout { grid-template-columns: 1fr; }
|
||||
.sidebar { position: static; height: auto; border-right: none; border-bottom: 1px solid var(--border); }
|
||||
}
|
||||
.sidebar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
padding: 24px 20px;
|
||||
background: #fafbfc;
|
||||
border-right: 1px solid var(--border);
|
||||
}
|
||||
.sidebar h1 {
|
||||
font-size: 17px;
|
||||
margin: 0 0 4px;
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
.sidebar .sub {
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.sidebar nav a {
|
||||
display: block;
|
||||
padding: 6px 10px;
|
||||
margin: 2px 0;
|
||||
font-size: 13px;
|
||||
color: var(--text);
|
||||
text-decoration: none;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.sidebar nav a:hover { background: var(--primary-bg); color: var(--primary-dark); }
|
||||
main { padding: 32px 40px 64px; min-width: 0; }
|
||||
@media (max-width: 600px) { main { padding: 20px 16px 48px; } }
|
||||
h2 {
|
||||
font-size: 22px;
|
||||
margin: 40px 0 16px;
|
||||
padding-bottom: 8px;
|
||||
border-bottom: 2px solid var(--primary-bg);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
h2:first-of-type { margin-top: 0; }
|
||||
h3 { font-size: 17px; margin: 24px 0 12px; }
|
||||
p { margin: 0 0 12px; }
|
||||
ul, ol { margin: 0 0 16px; padding-left: 1.4em; }
|
||||
li { margin-bottom: 6px; }
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin: 12px 0 20px;
|
||||
font-size: 14px;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid var(--border);
|
||||
padding: 10px 12px;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
}
|
||||
th { background: var(--primary-bg); font-weight: 600; }
|
||||
pre, code {
|
||||
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
pre {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 14px 16px;
|
||||
overflow-x: auto;
|
||||
margin: 12px 0 20px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
code { background: var(--code-bg); padding: 2px 6px; border-radius: 4px; }
|
||||
pre code { background: none; padding: 0; }
|
||||
.hero {
|
||||
background: linear-gradient(135deg, var(--primary-bg) 0%, #fff 60%);
|
||||
border: 1px solid #a7f3d0;
|
||||
border-radius: var(--radius);
|
||||
padding: 24px 28px;
|
||||
margin-bottom: 28px;
|
||||
}
|
||||
.hero h2 { border: none; margin: 0 0 8px; padding: 0; font-size: 24px; }
|
||||
.hero p { margin: 0; color: var(--text-muted); }
|
||||
.badge {
|
||||
display: inline-block;
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
margin-right: 8px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.steps { counter-reset: step; list-style: none; padding: 0; }
|
||||
.steps > li {
|
||||
counter-increment: step;
|
||||
position: relative;
|
||||
padding: 16px 16px 16px 52px;
|
||||
margin-bottom: 12px;
|
||||
background: #fafbfc;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
.steps > li::before {
|
||||
content: counter(step);
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
background: var(--primary);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.steps h3 { margin: 0 0 8px; font-size: 16px; }
|
||||
.box {
|
||||
border-radius: 8px;
|
||||
padding: 14px 16px;
|
||||
margin: 16px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
.box-warn { background: var(--warn-bg); border-left: 4px solid var(--warn-border); }
|
||||
.box-danger { background: var(--danger-bg); border-left: 4px solid var(--danger-border); }
|
||||
.box-info { background: var(--primary-bg); border-left: 4px solid var(--primary); }
|
||||
.checklist { list-style: none; padding: 0; }
|
||||
.checklist li {
|
||||
padding: 8px 0 8px 28px;
|
||||
position: relative;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
}
|
||||
.checklist li::before {
|
||||
content: "☐";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--primary);
|
||||
font-size: 18px;
|
||||
}
|
||||
.arch {
|
||||
background: var(--code-bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.45;
|
||||
white-space: pre;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.tree {
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 13px;
|
||||
background: var(--code-bg);
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
footer {
|
||||
margin-top: 48px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid var(--border);
|
||||
font-size: 13px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="layout">
|
||||
<aside class="sidebar">
|
||||
<h1>中科兴皖</h1>
|
||||
<p class="sub">Docker 部署指导手册<br />适用:甲方运维人员</p>
|
||||
<nav>
|
||||
<a href="#overview">概述</a>
|
||||
<a href="#requirements">环境要求</a>
|
||||
<a href="#package">交付包说明</a>
|
||||
<a href="#mirror">镜像加速(国内)</a>
|
||||
<a href="#install">安装步骤</a>
|
||||
<a href="#config">配置说明</a>
|
||||
<a href="#verify">验收检查</a>
|
||||
<a href="#architecture">服务架构</a>
|
||||
<a href="#profiles">部署模式</a>
|
||||
<a href="#ops">日常运维</a>
|
||||
<a href="#backup">备份与升级</a>
|
||||
<a href="#faq">常见问题</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<main>
|
||||
<div class="hero">
|
||||
<h2><span class="badge">Docker</span>中科兴皖系统部署指导</h2>
|
||||
<p>
|
||||
本手册帮助您在 Linux 服务器上完成<strong>预构建镜像</strong>方式的安装。
|
||||
交付包不含前后端源码,首次启动需联网拉取 MySQL / Redis / MinIO 等基础镜像。
|
||||
对外访问端口默认为 <strong>8112</strong>。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<section id="overview">
|
||||
<h2>1. 概述</h2>
|
||||
<table>
|
||||
<tr><th>项目</th><th>说明</th></tr>
|
||||
<tr><td>部署方式</td><td><code>docker load</code> 导入应用镜像 + <code>docker compose up -d</code></td></tr>
|
||||
<tr><td>应用镜像</td><td><code>zkxw-backend</code>、<code>zkxw-web</code>(已预构建,无需编译)</td></tr>
|
||||
<tr><td>CPU 架构</td><td><code>linux/amd64</code>(常见 x86 云主机;ARM 服务器需联系交付方重新打包)</td></tr>
|
||||
<tr><td>对外端口</td><td><strong>8112</strong>(Web 管理端 + API 反代)</td></tr>
|
||||
<tr><td>默认账号</td><td><code>admin</code> / <code>111111</code>(首次登录后请立即修改)</td></tr>
|
||||
</table>
|
||||
<div class="box box-info">
|
||||
<strong>说明:</strong>MySQL、Redis、MinIO 仅在 Docker 内部网络通信,<strong>不占用</strong>宿主机 3306 / 6379 / 9000 端口,一般不会与贵方已有中间件冲突。
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="requirements">
|
||||
<h2>2. 环境要求</h2>
|
||||
<table>
|
||||
<tr><th>项</th><th>要求</th></tr>
|
||||
<tr><td>操作系统</td><td>Linux x86_64(推荐 Ubuntu 22.04、CentOS 7+)</td></tr>
|
||||
<tr><td>Docker</td><td>≥ 24.0</td></tr>
|
||||
<tr><td>Docker Compose</td><td>v2(使用 <code>docker compose</code> 子命令)</td></tr>
|
||||
<tr><td>网络</td><td>可访问 Docker Hub,或已配置国内 Registry 镜像加速</td></tr>
|
||||
<tr><td>硬件建议</td><td>4 核 CPU、8 GB 内存、磁盘 ≥ 50 GB</td></tr>
|
||||
<tr><td>端口</td><td>宿主机 <strong>8112</strong> 未被占用;防火墙 / 安全组已放行 TCP 8112</td></tr>
|
||||
</table>
|
||||
<p>安装前请执行以下命令确认环境:</p>
|
||||
<pre><code>docker --version
|
||||
docker compose version
|
||||
docker info | grep -A2 "Registry Mirrors" # 国内环境建议已配置加速</code></pre>
|
||||
</section>
|
||||
|
||||
<section id="package">
|
||||
<h2>3. 交付包目录说明</h2>
|
||||
<p>解压 <code>zkxw-docker-deploy-<版本>.tar.gz</code> 后,目录结构如下:</p>
|
||||
<div class="tree">zkxw-docker-deploy-<版本>/
|
||||
├── images/
|
||||
│ └── zkxw-app-images.tar # 预构建前后端镜像(必做 docker load)
|
||||
├── deploy/docker/
|
||||
│ ├── docker-compose.yml
|
||||
│ ├── .env.example # 复制为 .env 后修改密码
|
||||
│ ├── mysql/init/
|
||||
│ └── 部署指导手册.html # 本手册
|
||||
├── docs/sql/zkxw.sql # 首次部署自动建库(非业务源码)
|
||||
├── 部署说明.md # Markdown 版说明(可选阅读)
|
||||
└── VERSION.txt # 版本与镜像 tag 信息</div>
|
||||
<div class="box box-warn">
|
||||
<strong>不包含:</strong>后端 Python 源码、前端 Vue 源码、Dockerfile。数据库脚本仅为表结构与基线数据。
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="mirror">
|
||||
<h2>4. Docker 镜像加速(国内强烈建议)</h2>
|
||||
<p>
|
||||
应用镜像通过 <code>docker load</code> 本地导入;但首次 <code>docker compose up</code> 仍需从网络拉取
|
||||
<code>mysql:5.7.36</code>、<code>redis:7-alpine</code>、<code>minio/minio</code> 等基础镜像。
|
||||
国内服务器建议配置 Registry 镜像加速。
|
||||
</p>
|
||||
<p>编辑 <code>/etc/docker/daemon.json</code>(示例,任选可用加速地址):</p>
|
||||
<pre><code>{
|
||||
"registry-mirrors": [
|
||||
"https://docker.1ms.run",
|
||||
"https://docker.m.daocloud.io"
|
||||
]
|
||||
}</code></pre>
|
||||
<pre><code>sudo systemctl daemon-reload
|
||||
sudo systemctl restart docker</code></pre>
|
||||
<p>若贵司已有阿里云 ACR 等专属加速地址,请优先使用官方提供的 URL。</p>
|
||||
</section>
|
||||
|
||||
<section id="install">
|
||||
<h2>5. 安装步骤</h2>
|
||||
<p>以下命令假设交付包已上传至 <code>/opt/zkxw</code>,请按实际路径调整。</p>
|
||||
<ol class="steps">
|
||||
<li>
|
||||
<h3>解压交付包</h3>
|
||||
<pre><code>mkdir -p /opt/zkxw && cd /opt/zkxw
|
||||
tar -xzf zkxw-docker-deploy-*.tar.gz
|
||||
cd zkxw-docker-deploy-*</code></pre>
|
||||
</li>
|
||||
<li>
|
||||
<h3>导入应用镜像</h3>
|
||||
<pre><code>docker load -i images/zkxw-app-images.tar
|
||||
docker images | grep zkxw-</code></pre>
|
||||
<p>请记下镜像 tag(如 <code>zkxw-backend:v1.0.0</code>),下一步配置须一致。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>配置环境变量</h3>
|
||||
<pre><code>cd deploy/docker
|
||||
cp .env.example .env
|
||||
vi .env</code></pre>
|
||||
<p>至少修改:<code>MYSQL_ROOT_PASSWORD</code>、<code>DATABASE_URL</code> 中的密码、<code>SECRET_KEY</code>、<code>MINIO_SECRET_KEY</code>。</p>
|
||||
<p>确认 <code>ZKXW_BACKEND_IMAGE</code>、<code>ZKXW_WEB_IMAGE</code> 与 <code>docker images</code> 显示的 tag 一致(可参考包内 <code>VERSION.txt</code>)。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>启动全部服务</h3>
|
||||
<pre><code>docker compose up -d</code></pre>
|
||||
<p>首次启动会自动拉取基础镜像,MySQL 导入 <code>zkxw.sql</code> 约需 <strong>1~3 分钟</strong>,请耐心等待。</p>
|
||||
</li>
|
||||
<li>
|
||||
<h3>(可选)查看启动进度</h3>
|
||||
<pre><code>docker compose ps
|
||||
docker compose logs -f mysql # 可选,Ctrl+C 仅退出日志,不停止服务
|
||||
docker compose logs -f backend</code></pre>
|
||||
</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section id="config">
|
||||
<h2>6. 配置说明(.env 要点)</h2>
|
||||
<p>默认模式 <code>COMPOSE_PROFILES=full</code>:自带 MySQL、Redis、MinIO。</p>
|
||||
<table>
|
||||
<tr><th>变量</th><th>说明</th></tr>
|
||||
<tr><td><code>HTTP_PORT</code></td><td>对外 HTTP 端口,默认 <strong>8112</strong></td></tr>
|
||||
<tr><td><code>ZKXW_BACKEND_IMAGE</code></td><td>后端镜像名:tag,须与 docker load 一致</td></tr>
|
||||
<tr><td><code>ZKXW_WEB_IMAGE</code></td><td>前端镜像名:tag,须与 docker load 一致</td></tr>
|
||||
<tr><td><code>MYSQL_ROOT_PASSWORD</code></td><td>MySQL root 密码(full 模式)</td></tr>
|
||||
<tr><td><code>DATABASE_URL</code></td><td>数据库连接串,密码须与上面一致</td></tr>
|
||||
<tr><td><code>SECRET_KEY</code></td><td>JWT 密钥,生产环境务必改为长随机串</td></tr>
|
||||
<tr><td><code>REDIS_HOST</code></td><td>full 模式填 <code>redis</code></td></tr>
|
||||
<tr><td><code>MINIO_ENDPOINT</code></td><td>full 模式填 <code>minio:9000</code></td></tr>
|
||||
<tr><td><code>MINIO_BASE_URL</code></td><td>保持 <code>/minio/zkxw</code>(由 Web 镜像内 Nginx 反代)</td></tr>
|
||||
<tr><td><code>API_ENCRYPT_ENABLED</code></td><td>默认 <code>false</code>,Docker 交付为明文 API</td></tr>
|
||||
</table>
|
||||
<div class="box box-danger">
|
||||
<strong>切勿将 .env 提交到版本库。</strong>修改密码后若服务已启动,执行 <code>docker compose up -d</code> 并 <code>docker compose restart backend</code>。
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="verify">
|
||||
<h2>7. 验收检查</h2>
|
||||
<ul class="checklist">
|
||||
<li><code>docker compose ps</code> 中 mysql、redis、minio、backend、web 均为 running(backend/web 可为 healthy)</li>
|
||||
<li>服务器本机:<code>curl -s http://127.0.0.1:8112/health</code> 返回正常</li>
|
||||
<li>浏览器访问 <code>http://<服务器IP>:8112/</code> 可打开登录页</li>
|
||||
<li>使用 <code>admin</code> / <code>111111</code> 登录成功(登录后请改密)</li>
|
||||
<li>防火墙 / 安全组已放行 TCP 8112</li>
|
||||
</ul>
|
||||
<table>
|
||||
<tr><th>地址</th><th>说明</th></tr>
|
||||
<tr><td><code>http://<IP>:8112/</code></td><td>Web 管理端</td></tr>
|
||||
<tr><td><code>http://<IP>:8112/health</code></td><td>健康检查</td></tr>
|
||||
<tr><td><code>http://<IP>:8112/docs</code></td><td>Swagger API 文档</td></tr>
|
||||
</table>
|
||||
</section>
|
||||
|
||||
<section id="architecture">
|
||||
<h2>8. 服务架构</h2>
|
||||
<div class="arch">浏览器 :8112
|
||||
└── web(Nginx + 前端静态)
|
||||
├── /api/* → backend:8111(FastAPI)
|
||||
└── /minio/zkxw/* → minio:9000(附件,容器内网络)
|
||||
|
||||
backend → mysql:3306(业务库 zkxw)
|
||||
→ redis:6379(会话)
|
||||
→ minio:9000(对象存储)</div>
|
||||
</section>
|
||||
|
||||
<section id="profiles">
|
||||
<h2>9. 部署模式(高级)</h2>
|
||||
<p>通过 <code>.env</code> 中 <code>COMPOSE_PROFILES</code> 切换,默认无需修改。</p>
|
||||
<h3>9.1 full(默认,全栈)</h3>
|
||||
<pre><code>COMPOSE_PROFILES=full</code></pre>
|
||||
<p>启动 MySQL + Redis + MinIO + 后端 + 前端,适合独立部署一台服务器。</p>
|
||||
<h3>9.2 app(仅应用,连接已有中间件)</h3>
|
||||
<p>若贵方已有 MySQL、Redis、MinIO,可设为 <code>COMPOSE_PROFILES=app</code>,并将 <code>DATABASE_URL</code>、<code>REDIS_HOST</code>、<code>MINIO_*</code> 改为实际地址。具体示例见 <code>deploy/docker/.env.example</code> 注释。</p>
|
||||
<h3>9.3 app,storage(外部库 + 自带 MinIO)</h3>
|
||||
<p>已有 MySQL/Redis,仅 MinIO 由本 compose 提供时使用。</p>
|
||||
<div class="box box-warn">
|
||||
使用外部 MinIO 且不在 Docker 网络内时,可能需要交付方重新构建 Web 镜像。一般建议先按默认 <code>full</code> 模式完成安装。
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="ops">
|
||||
<h2>10. 日常运维命令</h2>
|
||||
<p>以下命令均在 <code>deploy/docker</code> 目录执行:</p>
|
||||
<pre><code># 查看状态
|
||||
docker compose ps
|
||||
|
||||
# 查看日志
|
||||
docker compose logs -f backend
|
||||
docker compose logs -f web
|
||||
|
||||
# 重启
|
||||
docker compose restart
|
||||
|
||||
# 停止(不删数据卷)
|
||||
docker compose down
|
||||
|
||||
# 进入后端容器
|
||||
docker compose exec backend bash</code></pre>
|
||||
<div class="box box-danger">
|
||||
<strong>警告:</strong><code>docker compose down -v</code> 会删除所有数据卷(MySQL、MinIO 等),导致数据丢失。仅在首次部署失败且可接受清空数据时使用。
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="backup">
|
||||
<h2>11. 备份与升级</h2>
|
||||
<h3>11.1 数据卷</h3>
|
||||
<table>
|
||||
<tr><th>卷名(前缀 zkxw_)</th><th>内容</th></tr>
|
||||
<tr><td>mysql_data</td><td>MySQL 业务数据</td></tr>
|
||||
<tr><td>redis_data</td><td>Redis 持久化</td></tr>
|
||||
<tr><td>minio_data</td><td>附件对象</td></tr>
|
||||
<tr><td>backend_uploads</td><td>本地上传目录(若使用本地存储)</td></tr>
|
||||
</table>
|
||||
<h3>11.2 MySQL 备份示例</h3>
|
||||
<pre><code>docker compose exec mysql mysqldump -uroot -p zkxw > zkxw_backup.sql</code></pre>
|
||||
<h3>11.3 版本升级</h3>
|
||||
<ol>
|
||||
<li>备份数据库与 MinIO 数据</li>
|
||||
<li>解压新版本交付包,<code>docker load -i images/zkxw-app-images.tar</code></li>
|
||||
<li>更新 <code>.env</code> 中 <code>ZKXW_BACKEND_IMAGE</code>、<code>ZKXW_WEB_IMAGE</code></li>
|
||||
<li>在 <code>deploy/docker</code> 执行 <code>docker compose up -d</code></li>
|
||||
<li><code>curl -s http://127.0.0.1:8112/health</code> 验收</li>
|
||||
</ol>
|
||||
<p>若仅有数据库结构变更,请使用交付方提供的增量 SQL,<strong>不要</strong>删除已有 mysql_data 卷。</p>
|
||||
</section>
|
||||
|
||||
<section id="faq">
|
||||
<h2>12. 常见问题</h2>
|
||||
<h3>无法访问 8112</h3>
|
||||
<ul>
|
||||
<li>检查云主机安全组 / 防火墙是否放行 TCP 8112</li>
|
||||
<li><code>docker compose ps</code> 确认 web 为 running</li>
|
||||
<li><code>docker compose logs web</code> 查看 Nginx 日志</li>
|
||||
</ul>
|
||||
<h3>/api 返回 502</h3>
|
||||
<ul>
|
||||
<li>后端未就绪:<code>docker compose logs backend</code></li>
|
||||
<li>首次部署 MySQL 仍在导入:等待 1~3 分钟后重试</li>
|
||||
</ul>
|
||||
<h3>拉取 mysql/redis/minio 镜像失败或很慢</h3>
|
||||
<p>请按第 4 节配置 Docker Registry 镜像加速后,重新执行 <code>docker compose up -d</code>。</p>
|
||||
<h3>附件无法显示</h3>
|
||||
<ul>
|
||||
<li>确认 <code>STORAGE_TYPE=minio</code></li>
|
||||
<li><code>docker compose logs minio-init</code> 应显示 bucket 创建成功</li>
|
||||
<li>浏览器中附件 URL 应为 <code>/minio/zkxw/...</code></li>
|
||||
</ul>
|
||||
<h3>首次部署数据库初始化失败(可清空重来)</h3>
|
||||
<pre><code>cd deploy/docker
|
||||
docker compose down -v
|
||||
docker compose up -d</code></pre>
|
||||
<p>此操作会清空所有数据,仅适用于尚未正式上线的环境。</p>
|
||||
</section>
|
||||
|
||||
<footer>
|
||||
<p>中科兴皖 · Docker 部署指导手册 · 与交付包内 <code>deploy/docker/README.md</code> 保持一致</p>
|
||||
<p>技术支持请联系项目交付方。安装完成后请修改默认管理员密码。</p>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,3 @@
|
||||
-- 每期间隔(月)支持小数,如 0.1、0.5
|
||||
ALTER TABLE `biz_protocol_payment`
|
||||
MODIFY COLUMN `installment_interval_months` decimal(10, 2) DEFAULT NULL COMMENT '每期间隔(月)';
|
||||
+1
-1
@@ -3046,7 +3046,7 @@ CREATE TABLE `biz_protocol_payment` (
|
||||
`pay_mode` varchar(8) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'dj趸交 fq分期',
|
||||
`contract_amount` decimal(18,2) DEFAULT NULL COMMENT '合同金额',
|
||||
`installment_count` int(11) DEFAULT NULL COMMENT '分期期数',
|
||||
`installment_interval_months` int(11) DEFAULT NULL COMMENT '每期间隔(月)',
|
||||
`installment_interval_months` decimal(10,2) DEFAULT NULL COMMENT '每期间隔(月)',
|
||||
`lump_sum_deadline` char(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '趸交截止时间YYYYMMDD',
|
||||
`installment_start_date` char(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '分期开始时间YYYYMMDD',
|
||||
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
# 采集协议单 · 缴费模式切换设计
|
||||
|
||||
**日期**:2026-06-04
|
||||
**范围**:`web-admin` 采集协议单新增/编辑弹窗(`ProtocolFormDialog.vue`)及后端缴费主表/明细保存
|
||||
**状态**:已实现(P0)
|
||||
|
||||
---
|
||||
|
||||
## 1. 背景
|
||||
|
||||
采集协议单缴费主表 `pay_mode` 有两种取值:
|
||||
|
||||
| 值 | 含义 | 明细约定 |
|
||||
|----|------|----------|
|
||||
| `dj` | 趸交(一次性) | **1 条**有效明细 |
|
||||
| `fq` | 分期 | **N 条**明细,N = `installment_count` |
|
||||
|
||||
用户在**编辑已保存协议**时可能切换缴费模式。当前实现仅做字段联动(金额同步、日期重算),**不区分明细缴费状态**,会导致:
|
||||
|
||||
- 分期改趸交后仍保留多条明细且每条金额 = 合同全额;
|
||||
- 已缴明细被重算应缴日/期次;
|
||||
- 趸交已缴后仍可改分期,账实不符。
|
||||
|
||||
本设计定义切换规则与实现边界。
|
||||
|
||||
---
|
||||
|
||||
## 2. 决策记录
|
||||
|
||||
| 议题 | 决定 |
|
||||
|------|------|
|
||||
| 小数月间隔换算 | 30 天/月(已实现,见 `protocol-payment-installment.ts`) |
|
||||
| 第 2 期起提前 10 天 | 保留 |
|
||||
| 分期部分已缴后改趸交,未缴期次 | **A:作废**(软删/不再展示,不进分期预警) |
|
||||
| 已缴/确认中明细 | **保留**,只读,不参与重算 |
|
||||
| 趸交已缴后改分期 | **禁止** |
|
||||
| 趸交确认中改分期 | **禁止**(提示先完成或撤回财务确认) |
|
||||
|
||||
---
|
||||
|
||||
## 3. 明细状态与「锁定」定义
|
||||
|
||||
| pay_status | 含义 | 切换时 |
|
||||
|------------|------|--------|
|
||||
| `dfj` | 待缴费 | 可作废、可重建 |
|
||||
| `jfqrz` | 缴费确认中 | **锁定**(视为已占用,禁止模式切换) |
|
||||
| `yjf` | 已缴费 | **锁定**(保留,只读) |
|
||||
| `tfqrz` | 退费确认中 | **锁定**(禁止切换) |
|
||||
| `ytf` | 已退费 | **锁定**(禁止切换) |
|
||||
|
||||
**剩余应缴金额**:
|
||||
|
||||
```
|
||||
remaining = contractAmount − Σ(dueAmount WHERE pay_status IN ('yjf'))
|
||||
```
|
||||
|
||||
`jfqrz` 阶段切换一律阻断;若业务后续允许「确认中算占用」,再单独开变更。
|
||||
|
||||
---
|
||||
|
||||
## 4. 场景规则
|
||||
|
||||
### 4.1 趸交 → 分期(dj → fq)
|
||||
|
||||
| 前置条件 | 处理 |
|
||||
|----------|------|
|
||||
| 无明细或全部 `dfj` | **允许**。作废全部现有明细;按分期参数生成 N 条新 `dfj` 明细;主表 `pay_mode=fq`。 |
|
||||
| 存在 `jfqrz` / `yjf` / `tfqrz` / `ytf` | **禁止**。提示原因。 |
|
||||
|
||||
切换后:第 i 期 `installmentNo=i`,应缴日按 `calcFqInstallmentDueDate`,应缴金额按合同均分(末期待尾差)。
|
||||
|
||||
### 4.2 分期 → 趸交(fq → dj),一期未缴
|
||||
|
||||
| 前置条件 | 处理 |
|
||||
|----------|------|
|
||||
| 全部 `dfj` | **允许**。作废全部 N 条分期明细;**新建 1 条**趸交明细:`dueAmount=contractAmount`,`installmentNo=null`,应缴日=`lumpSumDeadline`。 |
|
||||
| 存在任何非 `dfj` | 走 4.3 |
|
||||
|
||||
### 4.3 分期 → 趸交(fq → dj),部分已缴
|
||||
|
||||
| 前置条件 | 处理 |
|
||||
|----------|------|
|
||||
| 有 `yjf`,无 `jfqrz`/`tfqrz`/`ytf` | **允许**。 |
|
||||
| 存在 `jfqrz`/`tfqrz`/`ytf` | **禁止**。 |
|
||||
|
||||
**允许时步骤**:
|
||||
|
||||
1. **保留**所有 `yjf` 明细(只读展示,保留原 `installmentNo`、转账信息)。
|
||||
2. **作废**所有 `dfj` 分期明细(不进入表单列表;保存时 `del_flag=1`)。
|
||||
3. **新建 1 条**趸交明细:`dueAmount=remaining`,`payStatus=dfj`,`installmentNo=null`,应缴日=`lumpSumDeadline`。
|
||||
4. 主表 `pay_mode=dj`;分期参数字段可保留只读快照(便于查看历史计划)。
|
||||
|
||||
若 `remaining ≤ 0`:禁止切换,提示「已缴清,无需改趸交」。
|
||||
|
||||
### 4.4 趸交 → 分期,趸交已缴
|
||||
|
||||
**禁止**。提示「趸交已结清,无法改为分期」。
|
||||
|
||||
---
|
||||
|
||||
## 5. 交互设计
|
||||
|
||||
### 5.1 切换前校验
|
||||
|
||||
用户点击「分期 / 趸交」radio 时:
|
||||
|
||||
1. 若目标模式与当前相同 → 无操作。
|
||||
2. 调用 `evaluatePayModeSwitch(currentMode, targetMode, details, contractAmount)`。
|
||||
3. 返回 `blocked` → `ElMessageBox.alert` 说明原因,**回滚 radio**。
|
||||
4. 返回 `allowed` → `ElMessageBox.confirm` 展示影响摘要,确认后执行变换。
|
||||
|
||||
**确认文案示例(fq→dj,部分已缴)**:
|
||||
|
||||
> 将作废 4 期未缴计划,保留 2 期已缴记录,并新增 1 条趸交明细(剩余 ¥X,XXX.XX)。是否继续?
|
||||
|
||||
### 5.2 编辑态保护
|
||||
|
||||
- 锁定明细:禁用删除、应缴金额、缴费状态、期次、应缴日编辑。
|
||||
- 趸交模式下隐藏「添加明细」(或禁用,保证仅 1 条有效未缴行 + 已缴历史行)。
|
||||
- 切到分期时**不**强制 `resetCountInterval`;优先保留主表已保存的期数/间隔/开始时间。
|
||||
|
||||
### 5.3 表单数据结构(过渡期)
|
||||
|
||||
```typescript
|
||||
interface PaymentDetailRow {
|
||||
// ...existing fields
|
||||
_payModeLocked?: boolean // yjf 等锁定行
|
||||
_voided?: boolean // 前端待作废,保存时不提交或提交 void 标记
|
||||
}
|
||||
```
|
||||
|
||||
保存 payload:仅提交**未作废**明细 + 锁定保留行;作废行由后端按 id 软删(P1)或前端不提交、后端 diff(P2)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 后端改造(分阶段)
|
||||
|
||||
### P0(与前端同步上线)
|
||||
|
||||
在 `save_payment_details` / 协议 bundle 保存前增加校验:
|
||||
|
||||
- `pay_mode=dj`:有效明细中「未锁定 + 未作废」的**待缴**行 ≤ 1;`Σ dueAmount(dfj 行)` = `remaining`(无已缴时 = 合同金额)。
|
||||
- `pay_mode=fq`:有效 `dfj` 行数 = `installment_count`(无已缴切换场景);或允许「已缴 k 期 + 剩余 N−k 期 dfj」(dj→fq 不适用,仅 fq 内改参数时需另议)。
|
||||
- 禁止客户端把 `yjf` 行 `pay_status` 改回 `dfj`。
|
||||
|
||||
### P1
|
||||
|
||||
- 作废明细:`del_flag=1`,分期预警自然排除。
|
||||
- 保存时带 `detail.id` upsert,避免每次编辑换 UUID。
|
||||
|
||||
### P2
|
||||
|
||||
- 专用 API:`POST .../payment/change-mode`
|
||||
- 操作日志:记录模式变更、作废条数、剩余金额
|
||||
|
||||
---
|
||||
|
||||
## 7. 核心算法(前端纯函数)
|
||||
|
||||
建议新增 `web-admin/src/utils/protocol-pay-mode-switch.ts`:
|
||||
|
||||
```typescript
|
||||
type SwitchResult =
|
||||
| { ok: true; details: DetailLike[]; summary: string }
|
||||
| { ok: false; reason: string }
|
||||
|
||||
function evaluatePayModeSwitch(...): SwitchResult | 'need_confirm'
|
||||
function applyPayModeSwitch(...): SwitchResult
|
||||
```
|
||||
|
||||
**禁止**在 `onPayModeChange` 中直接 `forEach` 重写全部明细;改为 `applyPayModeSwitch` 返回新数组。
|
||||
|
||||
`tryGenerateInstallmentDetails` / `syncPaymentDueAmounts`:
|
||||
|
||||
- 跳过 `_payModeLocked` 或 `payStatus !== 'dfj'` 的行;
|
||||
- 仅对未锁定 `dfj` 行重算金额/日期。
|
||||
|
||||
---
|
||||
|
||||
## 8. 测试用例
|
||||
|
||||
| # | 场景 | 期望 |
|
||||
|---|------|------|
|
||||
| T1 | dj dfj×1 → fq 6期 | 1 条作废,6 条新 dfj,金额均分 |
|
||||
| T2 | fq 6×dfj → dj | 6 条作废,1 条 dj dfj 全额 |
|
||||
| T3 | fq 2×yjf + 4×dfj → dj | 2 条 yjf 保留,4 条作废,1 条 dj remaining |
|
||||
| T4 | dj yjf×1 → fq | blocked |
|
||||
| T5 | fq 含 jfqrz → dj | blocked |
|
||||
| T6 | fq 全部 yjf → dj | blocked(remaining=0) |
|
||||
| T7 | 切换取消 | radio 回滚,明细不变 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 不在本次范围
|
||||
|
||||
- 退费后再改模式的专流程 UI
|
||||
- 小程序端缴费模式切换
|
||||
|
||||
---
|
||||
|
||||
## 10. 实现顺序建议
|
||||
|
||||
1. `protocol-pay-mode-switch.ts` + 单元测试(Node/vitest 或 backend pytest 镜像逻辑)
|
||||
2. 改造 `onPayModeChange` + 确认弹窗
|
||||
3. 改造 `tryGenerateInstallmentDetails` / `syncPaymentDueAmounts` 跳过锁定行
|
||||
4. 后端 P0 校验
|
||||
5. 联调四个场景 + 分期预警回归
|
||||
|
||||
---
|
||||
|
||||
## 11. 分期参数变更(非模式切换)
|
||||
|
||||
编辑已保存的**分期**协议时,用户可能修改「分期期数 / 每期间隔 / 分期开始时间」,规则如下:
|
||||
|
||||
| 情况 | 处理 |
|
||||
|------|------|
|
||||
| 全部 `dfj` | 确认后按新参数**整表重建** N 条明细 |
|
||||
| 部分 `yjf` | 保留已缴行;**作废**全部 `dfj`;按 **剩余金额** 均分生成 `(新期数 − 已缴期数)` 条未缴明细;应缴日按已缴期数续算 index |
|
||||
| 期数小于已缴最大期次 | **禁止** |
|
||||
| 含 `jfqrz`/`tfqrz`/`ytf` | **禁止** |
|
||||
| 仅改间隔/开始时间(期数不变) | 确认后保留 yjf,重建未缴行(金额+日期) |
|
||||
|
||||
实现:`web-admin/src/utils/protocol-fq-params-change.ts`,表单 `@change` → `handleFqParamsChange()`。
|
||||
|
||||
---
|
||||
|
||||
**审阅**:请确认本 spec 无遗漏后,进入 `writing-plans` 生成实现任务清单。
|
||||
@@ -39,6 +39,8 @@ cp -R "${ROOT}/deploy/docker/mysql" "${STAGING}/deploy/docker/"
|
||||
cp "${ROOT}/docs/sql/zkxw.sql" "${STAGING}/docs/sql/zkxw.sql"
|
||||
|
||||
cp "${ROOT}/deploy/docker/README.md" "${STAGING}/部署说明.md"
|
||||
cp "${ROOT}/deploy/docker/部署指导手册.html" "${STAGING}/部署指导手册.html"
|
||||
cp "${ROOT}/deploy/docker/部署指导手册.html" "${STAGING}/deploy/docker/部署指导手册.html"
|
||||
|
||||
cat > "${STAGING}/VERSION.txt" <<EOF
|
||||
package=${PKG_NAME}
|
||||
@@ -64,6 +66,7 @@ echo "包内不含前后端源码,包含:"
|
||||
echo " - images/zkxw-app-images.tar"
|
||||
echo " - deploy/docker/ (compose + .env.example + mysql init)"
|
||||
echo " - docs/sql/zkxw.sql"
|
||||
echo " - 部署指导手册.html(客户安装手册,浏览器打开)"
|
||||
echo ""
|
||||
echo "甲方服务器执行:"
|
||||
echo " tar -xzf ${PKG_NAME}.tar.gz"
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,11 +1,11 @@
|
||||
# Graph Report - src (2026-06-03)
|
||||
# Graph Report - src (2026-06-04)
|
||||
|
||||
## Corpus Check
|
||||
- Large corpus: 680 files · ~424,746 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
|
||||
- Large corpus: 683 files · ~427,683 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
|
||||
|
||||
## Summary
|
||||
- 1957 nodes · 2519 edges · 51 communities detected
|
||||
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 557 edges (avg confidence: 0.8)
|
||||
- 2000 nodes · 2611 edges · 48 communities detected
|
||||
- Extraction: 78% EXTRACTED · 22% INFERRED · 0% AMBIGUOUS · INFERRED: 579 edges (avg confidence: 0.8)
|
||||
- Token cost: 0 input · 0 output
|
||||
|
||||
## Community Hubs (Navigation)
|
||||
@@ -43,7 +43,7 @@
|
||||
- [[_COMMUNITY_Community 32|Community 32]]
|
||||
- [[_COMMUNITY_Community 33|Community 33]]
|
||||
- [[_COMMUNITY_Community 34|Community 34]]
|
||||
- [[_COMMUNITY_Community 36|Community 36]]
|
||||
- [[_COMMUNITY_Community 35|Community 35]]
|
||||
- [[_COMMUNITY_Community 37|Community 37]]
|
||||
- [[_COMMUNITY_Community 38|Community 38]]
|
||||
- [[_COMMUNITY_Community 39|Community 39]]
|
||||
@@ -51,19 +51,16 @@
|
||||
- [[_COMMUNITY_Community 41|Community 41]]
|
||||
- [[_COMMUNITY_Community 42|Community 42]]
|
||||
- [[_COMMUNITY_Community 44|Community 44]]
|
||||
- [[_COMMUNITY_Community 45|Community 45]]
|
||||
- [[_COMMUNITY_Community 46|Community 46]]
|
||||
- [[_COMMUNITY_Community 48|Community 48]]
|
||||
- [[_COMMUNITY_Community 49|Community 49]]
|
||||
- [[_COMMUNITY_Community 50|Community 50]]
|
||||
- [[_COMMUNITY_Community 51|Community 51]]
|
||||
- [[_COMMUNITY_Community 52|Community 52]]
|
||||
- [[_COMMUNITY_Community 53|Community 53]]
|
||||
- [[_COMMUNITY_Community 55|Community 55]]
|
||||
- [[_COMMUNITY_Community 57|Community 57]]
|
||||
- [[_COMMUNITY_Community 54|Community 54]]
|
||||
|
||||
## God Nodes (most connected - your core abstractions)
|
||||
1. `get()` - 206 edges
|
||||
2. `push()` - 36 edges
|
||||
2. `push()` - 39 edges
|
||||
3. `WebSocketClient` - 26 edges
|
||||
4. `emit()` - 16 edges
|
||||
5. `MenuProcessor` - 16 edges
|
||||
@@ -75,53 +72,53 @@
|
||||
|
||||
## Surprising Connections (you probably didn't know these)
|
||||
- `handleBatchDelete()` --calls--> `withFullscreenLoading()` [INFERRED]
|
||||
views/basic-info/customer/index.vue → utils/fullscreen-loading.ts
|
||||
views/production/consumable/ConsumablePackTab.vue → utils/fullscreen-loading.ts
|
||||
- `handleDownloadAttachment()` --calls--> `downloadAttachmentFile()` [INFERRED]
|
||||
views/pilot-service/infusion-schedule-management/InfusionScheduleHandoverDialog.vue → utils/download-attachment.ts
|
||||
- `subscribeTokenRefresh()` --calls--> `push()` [INFERRED]
|
||||
utils/http/index.ts → views/operations/storage-facility/index.vue
|
||||
- `handleUnauthorizedResponse()` --calls--> `fetchRefreshToken()` [INFERRED]
|
||||
utils/http/index.ts → api/auth.ts
|
||||
- `fetchLeaveList()` --calls--> `get()` [INFERRED]
|
||||
api/leave.ts → views/production/process/ProcessRouteTab.vue
|
||||
- `fetchLeaveDetail()` --calls--> `get()` [INFERRED]
|
||||
api/leave.ts → views/production/process/ProcessRouteTab.vue
|
||||
- `fetchConsumableList()` --calls--> `get()` [INFERRED]
|
||||
api/production.ts → views/production/process/ProcessRouteTab.vue
|
||||
- `fetchReagentList()` --calls--> `get()` [INFERRED]
|
||||
api/production.ts → views/production/process/ProcessRouteTab.vue
|
||||
|
||||
## Communities
|
||||
|
||||
### Community 0 - "Community 0"
|
||||
Cohesion: 0.01
|
||||
Nodes (103): fetchAccessLogList(), fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList() (+95 more)
|
||||
Nodes (111): fetchAccessLogList(), fetchActiveRegions(), fetchCategoryList(), fetchCategoryParameters(), fetchCellProductPriceList(), fetchCellProductSpecList(), fetchCellProductTypeList(), fetchCellSampleTypeList() (+103 more)
|
||||
|
||||
### Community 1 - "Community 1"
|
||||
Cohesion: 0.03
|
||||
Nodes (91): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionList(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchCheckupInstitutionProjects(), fetchPilotCheckupActualItems(), fetchPilotCheckupDetail() (+83 more)
|
||||
Nodes (93): batchSavePilotCheckup(), deletePilotCheckupActualItem(), fetchCheckupInstitutionList(), fetchCheckupInstitutionPackageDetail(), fetchCheckupInstitutionPackages(), fetchCheckupInstitutionProjects(), fetchPilotCheckupDetail(), markPilotCheckupChecked() (+85 more)
|
||||
|
||||
### Community 2 - "Community 2"
|
||||
Cohesion: 0.03
|
||||
Nodes (40): fetchGetMenuList(), fetchGetMenuCodes(), fetchGetUserInfo(), fetchLogin(), fetchRefreshToken(), clickTab(), handleTouchEnd(), setTransition() (+32 more)
|
||||
Nodes (38): clickTab(), handleTouchEnd(), setTransition(), useSettingsHandlers(), useSettingsPanel(), useSettingsState(), IframeRouteManager, RoutePermissionValidator (+30 more)
|
||||
|
||||
### Community 3 - "Community 3"
|
||||
Cohesion: 0.03
|
||||
Nodes (36): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllReagentStockLogs() (+28 more)
|
||||
Nodes (37): fetchAllConsumablePacks(), fetchAllConsumables(), fetchAllConsumableStockLogs(), fetchAllOutputTypes(), fetchAllProcessCategories(), fetchAllProcesses(), fetchAllReagents(), fetchAllReagentStockLogs() (+29 more)
|
||||
|
||||
### Community 4 - "Community 4"
|
||||
Cohesion: 0.03
|
||||
Nodes (35): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+27 more)
|
||||
Nodes (41): fetchAttachmentDownloadUrl(), fetchClinicalPaymentDetail(), fetchClinicalPayments(), fetchClinicalReceiptConfirmed(), fetchClinicalReceiptPending(), fetchClinicalRefundConfirmed(), fetchClinicalRefundPending(), fetchOrderAdjusts() (+33 more)
|
||||
|
||||
### Community 5 - "Community 5"
|
||||
Cohesion: 0.04
|
||||
Nodes (28): updateInfusionScheduleStatus(), submitOutboundReleaseReview(), fetchStorageReleaseReviewDetail(), fetchStorageReleaseReviewList(), submitStorageReleaseReview(), disableDevTools(), handleLock(), handleUnlock() (+20 more)
|
||||
Cohesion: 0.03
|
||||
Nodes (35): fetchCollectionRegionList(), fetchCreateCollectionRegion(), fetchCreateHospital(), fetchDeleteCollectionRegion(), fetchDeleteHospital(), fetchHospitalList(), fetchUpdateCollectionRegion(), fetchUpdateHospital() (+27 more)
|
||||
|
||||
### Community 6 - "Community 6"
|
||||
Cohesion: 0.04
|
||||
Nodes (32): handleBlur(), handleFocus(), handleInput(), fetchClinicalPaymentDetail(), fetchClinicalPayments(), fetchClinicalReceiptConfirmed(), fetchClinicalReceiptPending(), fetchClinicalRefundConfirmed() (+24 more)
|
||||
Nodes (35): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), submitOutboundReleaseReview(), fetchStorageReleaseReviewDetail(), fetchStorageReleaseReviewList(), submitStorageReleaseReview() (+27 more)
|
||||
|
||||
### Community 7 - "Community 7"
|
||||
Cohesion: 0.06
|
||||
Nodes (34): toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url(), hexToBytes() (+26 more)
|
||||
Cohesion: 0.04
|
||||
Nodes (35): handleBlur(), handleFocus(), handleInput(), fetchEthnicList(), formatAmount(), fmtMoney(), auditorDisplay(), dash() (+27 more)
|
||||
|
||||
### Community 8 - "Community 8"
|
||||
Cohesion: 0.06
|
||||
Nodes (29): for(), set(), walk(), annotateForkEdges(), chainApiToElements(), walkAncestorBranch(), walkAncestorParents(), if() (+21 more)
|
||||
Nodes (11): fetchGetLatestUpgradeLog(), getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager (+3 more)
|
||||
|
||||
### Community 9 - "Community 9"
|
||||
Cohesion: 0.06
|
||||
@@ -132,24 +129,24 @@ Cohesion: 0.1
|
||||
Nodes (2): WebSocketClient, TableCache
|
||||
|
||||
### Community 11 - "Community 11"
|
||||
Cohesion: 0.07
|
||||
Nodes (21): auditorDisplay(), dash(), expressName(), formatYm(), formatYmd(), sampleTypeName(), siteName(), unitName() (+13 more)
|
||||
Cohesion: 0.08
|
||||
Nodes (33): fetchRefreshToken(), toLogin(), base64ToBytes(), bytesToBase64(), decryptJson(), deriveKey(), encryptJson(), fromBase64Url() (+25 more)
|
||||
|
||||
### Community 12 - "Community 12"
|
||||
Cohesion: 0.06
|
||||
Nodes (24): fetchAttachmentDownloadUrl(), handleDownloadAttachment(), fullFileUrl(), handleDownloadAttachment(), handlePreviewAttachment(), isVideoFile(), handleReceptionAttachmentDownload(), handleDownloadAttachment() (+16 more)
|
||||
Cohesion: 0.07
|
||||
Nodes (20): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), collectIds(), postorder(), preorder(), applyTreeExpand() (+12 more)
|
||||
|
||||
### Community 13 - "Community 13"
|
||||
Cohesion: 0.09
|
||||
Nodes (8): getDefaultLanguage(), checkStorageCompatibility(), StorageConfig, getSystemStorage(), getSysVersion(), StorageKeyManager, StorageCompatibilityManager, validateStorageData()
|
||||
Cohesion: 0.07
|
||||
Nodes (26): fetchCreateSite(), fetchDeleteSite(), fetchSiteList(), fetchUpdateSite(), fetchUserList(), formatHandoverUserLabel(), formatNowDatetime(), fullFileUrl() (+18 more)
|
||||
|
||||
### Community 14 - "Community 14"
|
||||
Cohesion: 0.07
|
||||
Nodes (25): fetchCreateSite(), fetchDeleteSite(), fetchSiteList(), fetchUpdateSite(), fetchUserList(), formatHandoverUserLabel(), formatNowDatetime(), fullFileUrl() (+17 more)
|
||||
Nodes (22): for(), set(), walk(), annotateForkEdges(), chainApiToElements(), walkAncestorBranch(), walkAncestorParents(), if() (+14 more)
|
||||
|
||||
### Community 15 - "Community 15"
|
||||
Cohesion: 0.08
|
||||
Nodes (20): fetchCreateMenu(), fetchDeleteMenu(), fetchMenuTree(), fetchUpdateMenu(), collectIds(), postorder(), preorder(), applyTreeExpand() (+12 more)
|
||||
Cohesion: 0.13
|
||||
Nodes (26): applyFqParamsChange(), countByStatus(), evaluateFqParamsChange(), formatMoneySummary(), generateInitialFqDetails(), getPaidInstallmentRows(), maxPaidInstallmentNo(), activeDetails() (+18 more)
|
||||
|
||||
### Community 16 - "Community 16"
|
||||
Cohesion: 0.08
|
||||
@@ -157,56 +154,56 @@ Nodes (11): maskIdCard(), buildOutboundPilotContextSections(), applicationStatus
|
||||
|
||||
### Community 17 - "Community 17"
|
||||
Cohesion: 0.12
|
||||
Nodes (22): completePilotApplication(), deletePilotApplication(), fetchPilotApplicationList(), startPilotApplication(), voidPilotApplication(), handleBatchComplete(), handleBatchStart(), handleBatchVoid() (+14 more)
|
||||
Nodes (19): fetchGetUserInfo(), fetchLogin(), fetchUpdateProfile(), fetchUploadProfileAvatar(), fetchUserInfo(), buildWebEncryptedLoginBody(), defaultAvatarPathByRole(), hasCustomUserAvatar() (+11 more)
|
||||
|
||||
### Community 18 - "Community 18"
|
||||
Cohesion: 0.12
|
||||
Nodes (20): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleBatchDelete() (+12 more)
|
||||
Nodes (22): completePilotApplication(), deletePilotApplication(), fetchPilotApplicationList(), startPilotApplication(), voidPilotApplication(), handleBatchComplete(), handleBatchStart(), handleBatchVoid() (+14 more)
|
||||
|
||||
### Community 19 - "Community 19"
|
||||
Cohesion: 0.12
|
||||
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
|
||||
Nodes (20): fetchCreateUser(), fetchDeleteUser(), fetchResetPassword(), fetchUpdateUser(), fetchUserDetail(), formatUserDeptDisplay(), handleAdd(), handleBatchDelete() (+12 more)
|
||||
|
||||
### Community 20 - "Community 20"
|
||||
Cohesion: 0.12
|
||||
Nodes (15): addCopyButton(), highlightCode(), insertLineNumbers(), isBlockProcessed(), markBlockAsProcessed(), processBlock(), setupHighlightDirective(), setupRippleDirective() (+7 more)
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
Cohesion: 0.13
|
||||
Nodes (5): fetchGetMenuList(), fetchGetMenuCodes(), MenuProcessor, useAppMode(), useAuth()
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
Cohesion: 0.1
|
||||
Nodes (6): fetchProductionTaskDetail(), fetchProductionTaskList(), fetchUpdateProductionTask(), handleClose(), handleSubmit(), loadTaskDetail()
|
||||
|
||||
### Community 21 - "Community 21"
|
||||
### Community 23 - "Community 23"
|
||||
Cohesion: 0.15
|
||||
Nodes (16): fetchPilotCheckupList(), canEditActualCheckupInfo(), canEditReserve(), canFillCheckupInfo(), canMarkChecked(), handleDropdownCommand(), handleEditActual(), handleEditReserve() (+8 more)
|
||||
|
||||
### Community 22 - "Community 22"
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 0.12
|
||||
Nodes (12): fetchApproveTask(), fetchBusinessAllTasks(), fetchCompletedTasks(), fetchDesignerData(), fetchInstanceDetail(), fetchMyInstances(), fetchPendingTasks(), fetchProcessDefList() (+4 more)
|
||||
|
||||
### Community 23 - "Community 23"
|
||||
### Community 25 - "Community 25"
|
||||
Cohesion: 0.13
|
||||
Nodes (8): fetchOutboundReleaseMaterial(), fetchOutboundReleaseReviewDetail(), fetchOutboundReleaseReviewList(), fetchReleaseReviewList(), handleReset(), handleSearch(), loadData(), onReviewSubmitted()
|
||||
|
||||
### Community 24 - "Community 24"
|
||||
Cohesion: 0.16
|
||||
Nodes (14): fetchCreateCustomer(), fetchCustomerList(), fetchDeleteCustomer(), fetchUpdateCustomer(), handleAdd(), handleBatchDelete(), handleDelete(), handleDropdownCommand() (+6 more)
|
||||
|
||||
### Community 25 - "Community 25"
|
||||
### Community 26 - "Community 26"
|
||||
Cohesion: 0.16
|
||||
Nodes (10): useTable(), useTableImpl(), getColumnChecks(), useTableColumns(), createErrorHandler(), createSmartDebounce(), defaultResponseAdapter(), extractPagination() (+2 more)
|
||||
|
||||
### Community 26 - "Community 26"
|
||||
### Community 27 - "Community 27"
|
||||
Cohesion: 0.2
|
||||
Nodes (2): ComponentLoader, RouteTransformer
|
||||
|
||||
### Community 27 - "Community 27"
|
||||
### Community 28 - "Community 28"
|
||||
Cohesion: 0.27
|
||||
Nodes (14): useChart(), useChartComponent(), useChartOps(), colourBlend(), getCssVar(), getDarkColor(), getLightColor(), handleElementThemeColor() (+6 more)
|
||||
|
||||
### Community 28 - "Community 28"
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 0.18
|
||||
Nodes (9): addSample(), applyDonationBundleToForm(), confirmBatchTransportApply(), createEmptyTransport(), ensureEthnicOptionInList(), handleOpenForAdd(), loadEthnicOptions(), normalizeSampleRow() (+1 more)
|
||||
|
||||
### Community 29 - "Community 29"
|
||||
Cohesion: 0.14
|
||||
Nodes (8): useSettingsHandlers(), useSettingsPanel(), useSettingsState(), useCeremony(), useTheme(), themeAnimation(), toggleTheme(), toggleTransition()
|
||||
|
||||
### Community 30 - "Community 30"
|
||||
Cohesion: 0.18
|
||||
Nodes (5): fetchServiceOrderTxnList(), handleReset(), handleSearch(), handleTabChange(), loadData()
|
||||
@@ -223,124 +220,106 @@ Nodes (3): fetchMaterialList(), fetchMaterialOptions(), fetchMaterialStockLogLis
|
||||
Cohesion: 0.2
|
||||
Nodes (2): fetchQcMaterialList(), fetchQcMaterialOptions()
|
||||
|
||||
### Community 36 - "Community 36"
|
||||
### Community 35 - "Community 35"
|
||||
Cohesion: 0.28
|
||||
Nodes (1): FireworkSystem
|
||||
|
||||
### Community 37 - "Community 37"
|
||||
Cohesion: 0.39
|
||||
Nodes (6): isIgnorableScriptError(), normalizeErrorMessage(), registerPromiseErrorHandler(), registerResourceErrorHandler(), scriptErrorHandler(), setupErrorHandle()
|
||||
|
||||
### Community 37 - "Community 37"
|
||||
### Community 38 - "Community 38"
|
||||
Cohesion: 0.36
|
||||
Nodes (1): TableHeightCalculator
|
||||
|
||||
### Community 38 - "Community 38"
|
||||
### Community 39 - "Community 39"
|
||||
Cohesion: 0.25
|
||||
Nodes (2): fetchQcTaskDetail(), fetchQcTaskList()
|
||||
|
||||
### Community 39 - "Community 39"
|
||||
### Community 40 - "Community 40"
|
||||
Cohesion: 0.25
|
||||
Nodes (3): fetchOutboundQcDetail(), fetchQcWorkOrderDetail(), fetchQcWorkOrderList()
|
||||
|
||||
### Community 40 - "Community 40"
|
||||
### Community 41 - "Community 41"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): logApiCryptoBootInfo(), maskSecret()
|
||||
|
||||
### Community 41 - "Community 41"
|
||||
Cohesion: 0.29
|
||||
Nodes (2): fetchLeaveDetail(), fetchLeaveList()
|
||||
|
||||
### Community 42 - "Community 42"
|
||||
Cohesion: 0.47
|
||||
Nodes (3): isPaymentDueWithinWarnWindow(), parsePaymentDueYmd(), startOfLocalDay()
|
||||
|
||||
### Community 44 - "Community 44"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchSampleReceptionCheckItemList(), fetchSampleReceptionCheckItemsActive()
|
||||
|
||||
### Community 45 - "Community 45"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcThirdPartyItemList(), fetchQcThirdPartyItemsActive()
|
||||
|
||||
### Community 46 - "Community 46"
|
||||
Cohesion: 0.33
|
||||
Nodes (2): fetchQcThirdPartyCompanyList(), fetchQcThirdPartyCompanyOptions()
|
||||
|
||||
### Community 48 - "Community 48"
|
||||
### Community 46 - "Community 46"
|
||||
Cohesion: 0.5
|
||||
Nodes (2): focusInput(), handleKeydown()
|
||||
|
||||
### Community 49 - "Community 49"
|
||||
### Community 48 - "Community 48"
|
||||
Cohesion: 0.67
|
||||
Nodes (2): if(), logSidebarMenu()
|
||||
|
||||
### Community 51 - "Community 51"
|
||||
### Community 50 - "Community 50"
|
||||
Cohesion: 0.5
|
||||
Nodes (1): fetchStorageEntrySmsList()
|
||||
|
||||
### Community 52 - "Community 52"
|
||||
### Community 51 - "Community 51"
|
||||
Cohesion: 0.5
|
||||
Nodes (1): fetchSampleSmsNotificationList()
|
||||
|
||||
### Community 53 - "Community 53"
|
||||
### Community 52 - "Community 52"
|
||||
Cohesion: 0.5
|
||||
Nodes (1): fetchQcSmsList()
|
||||
|
||||
### Community 55 - "Community 55"
|
||||
### Community 54 - "Community 54"
|
||||
Cohesion: 1.0
|
||||
Nodes (2): getSettingDefaults(), resetToDefaults()
|
||||
|
||||
### Community 57 - "Community 57"
|
||||
Cohesion: 1.0
|
||||
Nodes (2): defaultAvatarPathByRole(), resolveUserAvatarUrl()
|
||||
|
||||
## Knowledge Gaps
|
||||
- **Thin community `Community 10`** (42 nodes): `WebSocketClient`, `.calculateReconnectDelay()`, `.clearAllTimers()`, `.clearConnectionTimers()`, `.clearTimer()`, `.close()`, `.closeCurrentSocketForReconnect()`, `.connect()`, `.connectionStatusText()`, `.constructor()`, `.destroyInstance()`, `.flushMessageQueue()`, `.getInstance()`, `.getReadyStateText()`, `.handleClose()`, `.handleConnectionTimeout()`, `.handleError()`, `.handleMessage()`, `.handleOpen()`, `.init()`, `.isWebSocketConnected()`, `.reconnect()`, `.resetHeartbeat()`, `.send()`, `.startHeartbeat()`, `.startPing()`, `TableCache`, `.cleanupExpired()`, `.clear()`, `.clearByTags()`, `.clearCurrentSearch()`, `.clearPagination()`, `.constructor()`, `.evictLRU()`, `.generateKey()`, `.generateTags()`, `.get()`, `.getStats()`, `.log()`, `.set()`, `index.ts`, `tableCache.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 26`** (17 nodes): `ComponentLoader`, `.constructor()`, `.createEmptyComponent()`, `.createErrorComponent()`, `.load()`, `.loadIframe()`, `.loadLayout()`, `.load()`, `RouteTransformer`, `.extractFirstSegment()`, `.handleFirstLevelRoute()`, `.handleIframeRoute()`, `.handleNormalRoute()`, `.isFirstLevelRoute()`, `.transform()`, `ComponentLoader.ts`, `RouteTransformer.ts`
|
||||
- **Thin community `Community 27`** (17 nodes): `ComponentLoader`, `.constructor()`, `.createEmptyComponent()`, `.createErrorComponent()`, `.load()`, `.loadIframe()`, `.loadLayout()`, `.load()`, `RouteTransformer`, `.extractFirstSegment()`, `.handleFirstLevelRoute()`, `.handleIframeRoute()`, `.handleNormalRoute()`, `.isFirstLevelRoute()`, `.transform()`, `ComponentLoader.ts`, `RouteTransformer.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 34`** (10 nodes): `fetchBatchStockInQcMaterial()`, `fetchBatchStockOutQcMaterial()`, `fetchCreateQcMaterial()`, `fetchDeleteQcMaterial()`, `fetchQcMaterialList()`, `fetchQcMaterialOptions()`, `fetchStockInQcMaterial()`, `fetchStockOutQcMaterial()`, `fetchUpdateQcMaterial()`, `qc-material.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 37`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
|
||||
- **Thin community `Community 35`** (9 nodes): `FireworkSystem`, `.constructor()`, `.createFirework()`, `.createParticle()`, `.getAvailableParticle()`, `.initializePool()`, `.preloadAllImages()`, `.preloadImage()`, `index.vue`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 38`** (8 nodes): `fetchCompleteQcTask()`, `fetchCreateQcTask()`, `fetchDeleteQcTask()`, `fetchQcTaskDetail()`, `fetchQcTaskList()`, `fetchStartQcTask()`, `fetchUpdateQcTaskAttachments()`, `qc-task.ts`
|
||||
- **Thin community `Community 38`** (8 nodes): `TableHeightCalculator`, `.calculate()`, `.calculateOffset()`, `.calculatePaginationOffset()`, `.constructor()`, `.getHeaderHeight()`, `useTableHeight()`, `useTableHeight.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 40`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
|
||||
- **Thin community `Community 39`** (8 nodes): `fetchCompleteQcTask()`, `fetchCreateQcTask()`, `fetchDeleteQcTask()`, `fetchQcTaskDetail()`, `fetchQcTaskList()`, `fetchStartQcTask()`, `fetchUpdateQcTaskAttachments()`, `qc-task.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 41`** (7 nodes): `fetchCreateLeave()`, `fetchDeleteLeave()`, `fetchLeaveDetail()`, `fetchLeaveList()`, `fetchSubmitLeave()`, `fetchUpdateLeave()`, `leave.ts`
|
||||
- **Thin community `Community 41`** (7 nodes): `App.vue`, `main.ts`, `refreshButtonAutoIcons()`, `refreshPanelTitleIcons()`, `logApiCryptoBootInfo()`, `maskSecret()`, `console.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 44`** (6 nodes): `fetchCreateSampleReceptionCheckItem()`, `fetchDeleteSampleReceptionCheckItem()`, `fetchSampleReceptionCheckItemList()`, `fetchSampleReceptionCheckItemsActive()`, `fetchUpdateSampleReceptionCheckItem()`, `sample-reception-check-item.ts`
|
||||
- **Thin community `Community 44`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 45`** (6 nodes): `fetchCreateQcThirdPartyItem()`, `fetchDeleteQcThirdPartyItem()`, `fetchQcThirdPartyItemList()`, `fetchQcThirdPartyItemsActive()`, `fetchUpdateQcThirdPartyItem()`, `qc-third-party-item.ts`
|
||||
- **Thin community `Community 46`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 46`** (6 nodes): `fetchCreateQcThirdPartyCompany()`, `fetchDeleteQcThirdPartyCompany()`, `fetchQcThirdPartyCompanyList()`, `fetchQcThirdPartyCompanyOptions()`, `fetchUpdateQcThirdPartyCompany()`, `qc-third-party-company.ts`
|
||||
- **Thin community `Community 48`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 48`** (5 nodes): `focusInput()`, `handleKeydown()`, `if()`, `search()`, `index.vue`
|
||||
- **Thin community `Community 50`** (4 nodes): `fetchGenerateStorageEntrySms()`, `fetchStorageEntrySmsList()`, `fetchToggleStorageEntrySmsNotified()`, `storage-entry-sms-notification.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 49`** (4 nodes): `if()`, `logSidebarMenu()`, `index.vue`, `SidebarSubmenu.vue`
|
||||
- **Thin community `Community 51`** (4 nodes): `fetchGenerateSms()`, `fetchSampleSmsNotificationList()`, `fetchToggleSmsNotified()`, `sample-sms-notification.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 51`** (4 nodes): `fetchGenerateStorageEntrySms()`, `fetchStorageEntrySmsList()`, `fetchToggleStorageEntrySmsNotified()`, `storage-entry-sms-notification.ts`
|
||||
- **Thin community `Community 52`** (4 nodes): `fetchGenerateQcSms()`, `fetchQcSmsList()`, `fetchToggleQcSmsNotified()`, `qc-sms-notification.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 52`** (4 nodes): `fetchGenerateSms()`, `fetchSampleSmsNotificationList()`, `fetchToggleSmsNotified()`, `sample-sms-notification.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 53`** (4 nodes): `fetchGenerateQcSms()`, `fetchQcSmsList()`, `fetchToggleQcSmsNotified()`, `qc-sms-notification.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 55`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
- **Thin community `Community 57`** (3 nodes): `defaultAvatarPathByRole()`, `resolveUserAvatarUrl()`, `user-avatar.ts`
|
||||
- **Thin community `Community 54`** (3 nodes): `getSettingDefaults()`, `resetToDefaults()`, `setting.ts`
|
||||
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
|
||||
|
||||
## Suggested Questions
|
||||
_Questions this graph is uniquely positioned to answer:_
|
||||
|
||||
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 8`, `Community 9`, `Community 14`, `Community 15`, `Community 17`, `Community 18`, `Community 20`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 30`, `Community 32`, `Community 33`, `Community 34`, `Community 38`, `Community 39`, `Community 41`, `Community 44`, `Community 45`, `Community 46`, `Community 51`, `Community 52`, `Community 53`?**
|
||||
_High betweenness centrality (0.280) - this node is a cross-community bridge._
|
||||
- **Why does `push()` connect `Community 1` to `Community 0`, `Community 3`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 12`, `Community 14`, `Community 16`, `Community 28`?**
|
||||
_High betweenness centrality (0.131) - this node is a cross-community bridge._
|
||||
- **Why does `get()` connect `Community 0` to `Community 1`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 18`, `Community 19`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 25`, `Community 30`, `Community 32`, `Community 33`, `Community 34`, `Community 39`, `Community 40`, `Community 44`, `Community 50`, `Community 51`, `Community 52`?**
|
||||
_High betweenness centrality (0.276) - this node is a cross-community bridge._
|
||||
- **Why does `push()` connect `Community 1` to `Community 0`, `Community 35`, `Community 3`, `Community 4`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 14`, `Community 15`, `Community 16`, `Community 29`?**
|
||||
_High betweenness centrality (0.144) - this node is a cross-community bridge._
|
||||
- **Why does `handleDynamicRoutes()` connect `Community 2` to `Community 17`, `Community 21`?**
|
||||
_High betweenness centrality (0.033) - this node is a cross-community bridge._
|
||||
- **Are the 205 inferred relationships involving `get()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `buildTreePathLabelFromFlat()`) actually correct?**
|
||||
_`get()` has 205 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 35 inferred relationships involving `push()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `fetchAllPagedRecords()`) actually correct?**
|
||||
_`push()` has 35 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 38 inferred relationships involving `push()` (e.g. with `collectLeafFacilityNodesInTreeOrder()` and `fetchAllPagedRecords()`) actually correct?**
|
||||
_`push()` has 38 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Are the 15 inferred relationships involving `emit()` (e.g. with `handleSubmit()` and `handleBlur()`) actually correct?**
|
||||
_`emit()` has 15 INFERRED edges - model-reasoned connections that need verification._
|
||||
- **Should `Community 0` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.01 - nodes in this community are weakly interconnected._
|
||||
- **Should `Community 1` be split into smaller, more focused modules?**
|
||||
_Cohesion score 0.03 - nodes in this community are weakly interconnected._
|
||||
_Cohesion score 0.01 - nodes in this community are weakly interconnected._
|
||||
@@ -57,12 +57,12 @@
|
||||
</div>
|
||||
<div id="legend"></div>
|
||||
</div>
|
||||
<div id="stats">1957 nodes · 2519 edges · 301 communities</div>
|
||||
<div id="stats">2000 nodes · 2611 edges · 298 communities</div>
|
||||
</div>
|
||||
<script>
|
||||
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 40, "community_name": "Community 40", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 40, "community_name": "Community 40", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 40, "community_name": "Community 40", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 40, "community_name": "Community 40", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 40, "community_name": "Community 40", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 40, "community_name": "Community 40", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#9C755F", "border": "#9C755F", "highlight": {"background": "#ffffff", "border": "#9C755F"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 88, "community_name": "Community 88", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 89, "community_name": "Community 89", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 19, "community_name": "Community 19", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 19, "community_name": "Community 19", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 19, "community_name": "Community 19", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 19, "community_name": "Community 19", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 19, "community_name": "Community 19", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective", "laLine truncated
|
||||
const RAW_EDGES = [{"from": "app_vue", "to": "src_app_refreshbuttonautoicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "src_app_refreshpaneltitleicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "main_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "utils_sys_console_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_masksecret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_logapicryptobootinfo", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "src_main_masksecret", "to": "src_main_logapicryptobootinfo", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_ts", "to": "directives_index_setupglobdirectives", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_setupglobdirectives", "to": "core_auth_setupauthdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "core_roles_setuprolesdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_highlight_setuphighlightdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_ripple_setuprippledirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_core_roles_ts", "to": "core_roles_checkrolepermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_setuprolesdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_roles_checkrolepermission", "to": "core_roles_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_checkauthpermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_setupauthdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_checkauthpermission", "to": "core_auth_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_ripple_ts", "to": "business_ripple_setuprippledirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_highlightcode", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_insertlinenumbers", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_addcopybutton", "label": "contains", "title": "contains [EXTRACTED]", "dLine truncated
|
||||
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 310}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 130}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 104}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 81}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 73}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 67}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 61}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 57}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 45}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 45}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 42}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 41}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 39}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 37}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 37}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 35}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 33}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 26}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 24}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 22}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 22}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 22}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 19}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 18}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 18}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 17}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 17}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 16}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 16}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 15}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 14}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 13}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 12}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 11}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 8}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 8}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 8}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 8}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 7}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 7}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 6}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 6}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 6}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 6}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 6}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 6}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 5}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 4}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 4}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 4}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 4}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 4}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 4}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 3}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 3}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 3}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 3}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 3}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 3}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 3}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 3}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 3}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 2}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 2}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 2}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 2}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 2}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 2}, {"cid": 70, "color": "#4E79A7", "label": "Community 70", "count":Line truncated
|
||||
const RAW_NODES = [{"id": "app_vue", "label": "App.vue", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "App.vue", "community": 41, "community_name": "Community 41", "source_file": "App.vue", "file_type": "code", "degree": 3}, {"id": "src_app_refreshbuttonautoicons", "label": "refreshButtonAutoIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshButtonAutoIcons()", "community": 41, "community_name": "Community 41", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "src_app_refreshpaneltitleicons", "label": "refreshPanelTitleIcons()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "refreshPanelTitleIcons()", "community": 41, "community_name": "Community 41", "source_file": "App.vue", "file_type": "code", "degree": 1}, {"id": "main_ts", "label": "main.ts", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.4, "font": {"size": 0, "color": "#ffffff"}, "title": "main.ts", "community": 41, "community_name": "Community 41", "source_file": "main.ts", "file_type": "code", "degree": 4}, {"id": "src_main_masksecret", "label": "maskSecret()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "maskSecret()", "community": 41, "community_name": "Community 41", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "src_main_logapicryptobootinfo", "label": "logApiCryptoBootInfo()", "color": {"background": "#F28E2B", "border": "#F28E2B", "highlight": {"background": "#ffffff", "border": "#F28E2B"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "logApiCryptoBootInfo()", "community": 41, "community_name": "Community 41", "source_file": "main.ts", "file_type": "code", "degree": 2}, {"id": "env_d_ts", "label": "env.d.ts", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "env.d.ts", "community": 85, "community_name": "Community 85", "source_file": "env.d.ts", "file_type": "code", "degree": 0}, {"id": "shims_loose_d_ts", "label": "shims-loose.d.ts", "color": {"background": "#B07AA1", "border": "#B07AA1", "highlight": {"background": "#ffffff", "border": "#B07AA1"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "shims-loose.d.ts", "community": 86, "community_name": "Community 86", "source_file": "shims-loose.d.ts", "file_type": "code", "degree": 0}, {"id": "directives_index_ts", "label": "index.ts", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "index.ts", "community": 20, "community_name": "Community 20", "source_file": "directives/index.ts", "file_type": "code", "degree": 1}, {"id": "directives_index_setupglobdirectives", "label": "setupGlobDirectives()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.5, "font": {"size": 0, "color": "#ffffff"}, "title": "setupGlobDirectives()", "community": 20, "community_name": "Community 20", "source_file": "directives/index.ts", "file_type": "code", "degree": 5}, {"id": "directives_core_roles_ts", "label": "roles.ts", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "roles.ts", "community": 20, "community_name": "Community 20", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 3}, {"id": "core_roles_checkrolepermission", "label": "checkRolePermission()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "checkRolePermission()", "community": 20, "community_name": "Community 20", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_removeelement", "label": "removeElement()", "color": {"background": "#4E79A7", "border": "#4E79A7", "highlight": {"background": "#ffffff", "border": "#4E79A7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "removeElement()", "community": 20, "community_name": "Community 20", "source_file": "directives/core/roles.ts", "file_type": "code", "degree": 2}, {"id": "core_roles_setuprolesdirective", "laLine truncated
|
||||
const RAW_EDGES = [{"from": "app_vue", "to": "src_app_refreshbuttonautoicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "src_app_refreshpaneltitleicons", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_vue", "to": "main_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "utils_sys_console_ts", "label": "imports_from", "title": "imports_from [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_masksecret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_ts", "to": "src_main_logapicryptobootinfo", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "src_main_masksecret", "to": "src_main_logapicryptobootinfo", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_ts", "to": "directives_index_setupglobdirectives", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_index_setupglobdirectives", "to": "core_auth_setupauthdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "core_roles_setuprolesdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_highlight_setuphighlightdirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_index_setupglobdirectives", "to": "business_ripple_setuprippledirective", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "directives_core_roles_ts", "to": "core_roles_checkrolepermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_roles_ts", "to": "core_roles_setuprolesdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_roles_checkrolepermission", "to": "core_roles_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_checkauthpermission", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_removeelement", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_core_auth_ts", "to": "core_auth_setupauthdirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_checkauthpermission", "to": "core_auth_removeelement", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_ripple_ts", "to": "business_ripple_setuprippledirective", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_highlightcode", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_insertlinenumbers", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "directives_business_highlight_ts", "to": "business_highlight_addcopybutton", "label": "contains", "title": "contains [EXTRACTED]", "dLine truncated
|
||||
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 331}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 128}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 89}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 82}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 73}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 73}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 72}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 67}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 55}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 45}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 42}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 41}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 39}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 38}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 37}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 32}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 31}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 27}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 26}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 24}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 22}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 22}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 22}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 22}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 19}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 18}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 17}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 17}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 16}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 16}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 14}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 13}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 12}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 11}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 9}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 8}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 8}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 8}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 8}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 7}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 6}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 6}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 6}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 6}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 5}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 5}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 4}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 4}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 4}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 4}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 4}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 4}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 3}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 3}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 3}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 3}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 3}, {"cid": 59, "color": "#BAB0AC", "label": "Community 59", "count": 3}, {"cid": 60, "color": "#4E79A7", "label": "Community 60", "count": 3}, {"cid": 61, "color": "#F28E2B", "label": "Community 61", "count": 2}, {"cid": 62, "color": "#E15759", "label": "Community 62", "count": 2}, {"cid": 63, "color": "#76B7B2", "label": "Community 63", "count": 2}, {"cid": 64, "color": "#59A14F", "label": "Community 64", "count": 2}, {"cid": 65, "color": "#EDC948", "label": "Community 65", "count": 2}, {"cid": 66, "color": "#B07AA1", "label": "Community 66", "count": 2}, {"cid": 67, "color": "#FF9DA7", "label": "Community 67", "count": 2}, {"cid": 68, "color": "#9C755F", "label": "Community 68", "count": 2}, {"cid": 69, "color": "#BAB0AC", "label": "Community 69", "count": 2}, {"cid": 70, "color": "#4E79A7", "label": "Community 70", "count": Line truncated
|
||||
|
||||
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
|
||||
function esc(s) {
|
||||
|
||||
+2738
-1247
File diff suppressed because it is too large.
Load diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/App.vue": 1779790323.6203642,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/main.ts": 1779258114.8468678,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/App.vue": 1780480414.9445062,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/main.ts": 1780480414.9551268,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/env.d.ts": 1778582067.998984,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/shims-loose.d.ts": 1778582068.0215242,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/directives/index.ts": 1778582067.9976711,
|
||||
@@ -8,26 +8,26 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/directives/core/auth.ts": 1778582067.9971414,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/directives/business/ripple.ts": 1778582067.996821,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/directives/business/highlight.ts": 1778582067.9966211,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api.d.ts": 1779155643.5621417,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api.d.ts": 1780539154.013632,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/index.ts": 1778582068.02854,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/config/index.ts": 1778582068.0266159,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/component/chart.ts": 1778582068.026058,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/component/index.ts": 1778582068.0262403,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/response.ts": 1778582068.025649,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/response.ts": 1780480414.9570467,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/common/index.ts": 1778582068.0254738,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/directive/directive.d.ts": 1778582068.026978,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api/api.d.ts": 1778582068.0246184,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1780477949.7778664,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1780477857.5482304,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts": 1780546861.7453368,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/auto-imports.d.ts": 1780546851.8236628,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/store/index.ts": 1778582068.0293276,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/router/index.ts": 1778775532.895603,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/types/router/index.ts": 1780480414.9574106,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/locales/index.ts": 1778582068.004279,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/setting.ts": 1778582067.9954739,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/index.ts": 1779344841.362722,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/index.ts": 1780480414.9542737,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/modules/component.ts": 1778582067.9943824,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/modules/festival.ts": 1778582067.9949014,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/modules/headerBar.ts": 1778582067.9952137,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/modules/fastEnter.ts": 1779232181.1371717,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/modules/fastEnter.ts": 1780480414.9544525,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/config/assets/images.ts": 1778582067.993645,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/plugins/echarts.ts": 1778582068.010295,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/plugins/index.ts": 1778582068.010531,
|
||||
@@ -40,9 +40,9 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/enums/appEnum.ts": 1778582067.9982593,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/patch-el-select-filterable.ts": 1779790341.162103,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/storage-slot-options.ts": 1779790341.466299,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts": 1779790341.943788,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts": 1780540742.1887667,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/fullscreen-loading.ts": 1779117454.818312,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/router.ts": 1779938225.7809103,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/router.ts": 1780480414.9585993,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-labels.ts": 1779199125.4894068,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/status-tag-registry.ts": 1779826490.6921933,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/fetch-paged-list.ts": 1778775532.895782,
|
||||
@@ -55,8 +55,10 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/money-format.ts": 1779695444.9027524,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/category-path-display.ts": 1779790340.9231393,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/qc-labels.ts": 1779199108.173778,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts": 1780547381.0547066,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/loginRsa.ts": 1778582068.0373487,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts": 1780310646.0954366,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts": 1780546639.7181845,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts": 1780545638.298603,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/download-attachment.ts": 1779159591.1376455,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/ui/colors.ts": 1778582068.046773,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/ui/emojo.ts": 1778582068.0469406,
|
||||
@@ -71,43 +73,43 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/form/validator.ts": 1778582068.0335238,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/constants/links.ts": 1778582068.031627,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/constants/index.ts": 1778582068.0312057,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/worktab.ts": 1779240471.2587266,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/jump.ts": 1778775532.8961763,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/route.ts": 1779790341.1550379,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/worktab.ts": 1780480414.958444,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/jump.ts": 1780480414.9581196,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/route.ts": 1780480414.9582925,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/navigation/index.ts": 1778582068.0376182,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/storage/storage.ts": 1778582068.0412395,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/storage/storage-config.ts": 1778582068.040829,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/storage/index.ts": 1778582068.040637,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/storage/storage-key-manager.ts": 1778582068.0410247,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/mittBus.ts": 1778582068.0423212,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/upgrade.ts": 1779790341.6936553,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/upgrade.ts": 1780480414.9587884,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/error-handle.ts": 1778582068.0419197,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/index.ts": 1778582068.0421178,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/sys/console.ts": 1778582068.0417144,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/table/tableConfig.ts": 1778582068.0443969,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/table/tableCache.ts": 1778582068.044193,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/table/tableUtils.ts": 1778582068.0454955,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/status.ts": 1778582068.036632,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/status.ts": 1780480414.957961,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/crypto.ts": 1778582068.0353796,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/index.ts": 1779463885.9788811,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/error.ts": 1778582068.0356607,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/index.ts": 1780480414.9578006,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/http/error.ts": 1780480414.9575992,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/socket/index.ts": 1778582068.0397933,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/router/sidebar-menu-filter.ts": 1778582068.0391986,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/tables/art-table/index.vue": 1779525781.573567,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/tables/art-table-header/index.vue": 1779790330.385015,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-search-bar/index.vue": 1779525781.574576,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-form/index.vue": 1779525781.575067,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-button-more/index.vue": 1779525781.5755153,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-excel-import/index.vue": 1779525781.575924,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-excel-export/index.vue": 1779525781.576321,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-drag-verify/index.vue": 1779525781.576787,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-wang-editor/index.vue": 1779790328.3615272,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-button-table/index.vue": 1779525781.5775588,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/tables/art-table-header/index.vue": 1780480414.9533372,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-search-bar/index.vue": 1780480414.9481184,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-form/index.vue": 1780480414.9478915,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-button-more/index.vue": 1780480414.9465926,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-excel-import/index.vue": 1780480414.9476178,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-excel-export/index.vue": 1780480414.9474266,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-drag-verify/index.vue": 1780480414.9471714,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-wang-editor/index.vue": 1780480414.9483848,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/forms/art-button-table/index.vue": 1780480414.9469068,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/widget/art-icon-button/index.vue": 1779525781.578175,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-bar-chart-card/index.vue": 1779525781.5786,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-data-list-card/index.vue": 1779525781.5789726,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-timeline-list-card/index.vue": 1779525781.5793364,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-stats-card/index.vue": 1779525781.5797477,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-stats-card/index.vue": 1780480414.9464056,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-image-card/index.vue": 1779525781.5800624,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-donut-chart-card/index.vue": 1779525781.5803144,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/cards/art-progress-card/index.vue": 1779525781.5805767,
|
||||
@@ -121,7 +123,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/charts/art-radar-chart/index.vue": 1779525781.5834749,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/charts/art-h-bar-chart/index.vue": 1779525781.5837238,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/others/art-watermark/index.vue": 1779525781.5842316,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/others/art-menu-right/index.vue": 1779790330.3317213,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/others/art-menu-right/index.vue": 1780480414.9530756,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/banners/art-card-banner/index.vue": 1779525781.5850756,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/banners/art-basic-banner/index.vue": 1779525781.5857205,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-global-component/index.vue": 1779525781.5863822,
|
||||
@@ -131,45 +133,46 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/composables/useSettingsState.ts": 1778582067.9773157,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/composables/useSettingsHandlers.ts": 1778582067.9766955,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/ThemeSettings.vue": 1779525781.5871665,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingHeader.vue": 1779525781.587754,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingItem.vue": 1779525781.5882142,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingHeader.vue": 1780480414.9523888,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingItem.vue": 1780480414.9525797,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue": 1779525781.5885482,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/BasicSettings.vue": 1779525781.588895,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingDrawer.vue": 1779525781.5892572,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SettingActions.vue": 1779525781.5898669,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/ColorSettings.vue": 1779525781.5901814,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/ColorSettings.vue": 1780480414.952198,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/MenuLayoutSettings.vue": 1779525781.5907402,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/SectionTitle.vue": 1779525781.5913193,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue": 1779525781.59174,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-settings-panel/widget/ContainerSettings.vue": 1779525781.5920076,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-work-tab/index.vue": 1779525781.592554,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-chat-window/index.vue": 1779525781.59301,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-page-content/index.vue": 1779942912.5296464,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-work-tab/index.vue": 1780480414.9528105,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-chat-window/index.vue": 1780480414.949035,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-page-content/index.vue": 1780480414.9517472,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-horizontal-menu/index.vue": 1779525781.5938804,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-horizontal-menu/widget/HorizontalSubmenu.vue": 1779525781.5942907,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-mixed-menu/index.vue": 1779525781.5947194,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue": 1779790328.9606564,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue": 1779525781.59551,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-sidebar-menu/index.vue": 1780480414.950054,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-menus/art-sidebar-menu/widget/SidebarSubmenu.vue": 1780480414.9512155,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-fireworks-effect/index.vue": 1779525781.5963395,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-global-search/index.vue": 1779525781.5967863,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-notification/index.vue": 1779525781.597402,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-global-search/index.vue": 1780480414.949282,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-notification/index.vue": 1780480414.9515367,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-fast-enter/index.vue": 1779525781.5979466,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-screen-lock/index.vue": 1779525781.598362,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-screen-lock/index.vue": 1780480414.9519973,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-breadcrumb/index.vue": 1779525781.5987902,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/index.vue": 1779525781.5991871,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue": 1779790328.7361135,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/index.vue": 1780480414.949582,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue": 1780540514.104913,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue": 1780540511.8256087,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/theme/theme-svg/index.vue": 1779525781.6001027,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/result/ArtResultPage.vue": 1779525781.6004124,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/exception/ExceptionIllustration.vue": 1779790330.5225084,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/exception/ArtException.vue": 1779790330.512786,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/login/AuthTopBar.vue": 1779790330.5399241,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/exception/ArtException.vue": 1780480414.9538875,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/login/AuthTopBar.vue": 1780480414.9540887,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/views/login/LoginLeftView.vue": 1779525781.6012564,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/text-effect/art-text-scroll/index.vue": 1779525781.6015408,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/text-effect/art-text-scroll/index.vue": 1780480414.953665,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/text-effect/art-count-to/index.vue": 1779525781.6018777,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/text-effect/art-festival-text-scroll/index.vue": 1779525781.6024969,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-svg-icon/index.vue": 1779525781.603243,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-back-to-top/index.vue": 1779525781.6038082,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-logo/index.vue": 1779790326.538098,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-svg-icon/index.vue": 1780480414.9462214,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-back-to-top/index.vue": 1780480414.9458482,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/base/art-logo/index.vue": 1780480414.9460301,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/media/art-video-player/index.vue": 1779525781.6045322,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/media/art-cutter-img/index.vue": 1779525781.6051006,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/components/business/protocol-finance-confirm-fields/index.vue": 1779790325.7480125,
|
||||
@@ -236,15 +239,15 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/system.ts": 1779790323.5636237,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/material.ts": 1779283387.4196396,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/sample-reception.ts": 1780462889.9246686,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts": 1778582067.8610063,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts": 1780539439.6854532,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/api/qc-work-order.ts": 1780478257.9926786,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/auth/login/index.vue": 1779938231.136978,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/auth/login/index.vue": 1780480414.9591243,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/refund-confirm/index.vue": 1779866933.9349332,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/index.vue": 1779859546.0906804,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolStatusChangeDialog.vue": 1779525781.613681,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolViewDialog.vue": 1780462937.905501,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolAttachmentReadonly.vue": 1779525781.6162472,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue": 1780458686.0600615,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue": 1780547422.9811244,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolAuditDialog.vue": 1779525781.6193507,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/sample-info/index.vue": 1780457198.009363,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/sample-reception-info/index.vue": 1780325524.917126,
|
||||
@@ -279,17 +282,17 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationViewDialog.vue": 1780478943.7240853,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationFormDialog.vue": 1780458686.0616076,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/research-donation/list/DonationStatusChangeDialog.vue": 1779525781.6357327,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/dashboard/console/index.vue": 1779857063.389745,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/dashboard/console/index.vue": 1780480414.9592953,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/tenant/index.vue": 1779858296.9440098,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/order/index.vue": 1779856873.200306,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/unit/index.vue": 1779858300.774436,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/role/index.vue": 1779858382.6288393,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/role/index.vue": 1780480414.9603326,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/post/index.vue": 1779858367.1503367,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/category/index.vue": 1779859746.1898513,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/express/index.vue": 1779858275.4881697,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/index.vue": 1779856885.5607417,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/index.vue": 1780480414.960575,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/detail.vue": 1779790371.4357243,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/modules/user-dialog.vue": 1779790371.5651114,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/modules/user-dialog.vue": 1780480414.960775,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/user/modules/user-search.vue": 1779525781.643876,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/product/index.vue": 1779859799.4894958,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/workflow/my-applications/index.vue": 1779856891.19533,
|
||||
@@ -299,7 +302,7 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/workflow/components/ApprovalDialog.vue": 1779790371.6886575,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/workflow/designer/FlowDesigner.vue": 1779790371.8114932,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/workflow/process/index.vue": 1779859839.5932422,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/menu/index.vue": 1779858346.0258229,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/menu/index.vue": 1780480414.960126,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/site/index.vue": 1779858286.7791865,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/dept/index.vue": 1779858319.5899463,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/system/dict/index.vue": 1779857764.622668,
|
||||
@@ -352,9 +355,9 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/storage-release-review/StorageReleaseViewDialog.vue": 1780478944.9533937,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/qc-material-usage/index.vue": 1779864358.234948,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/quality-inspection/third-party-company/index.vue": 1779864494.1133437,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/500/index.vue": 1779546148.0553653,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/403/index.vue": 1779546144.3909206,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/404/index.vue": 1779546146.242008,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/500/index.vue": 1780480414.959776,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/403/index.vue": 1780480414.95946,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/exception/404/index.vue": 1780480414.9596128,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-type/index.vue": 1779871660.7926793,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-type/CellProductPriceTab.vue": 1779871667.0159404,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/pilot-service/cell-product-type/ProjectPriceSystemTab.vue": 1779864896.060257,
|
||||
@@ -410,27 +413,27 @@
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/views/basic-info/collection-region/CollectionProtocolNoTab.vue": 1779865978.3539536,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/assets/svg/loading.ts": 1778582067.932299,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/index.ts": 1778582068.0218356,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/worktab.ts": 1779790340.7550395,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/worktab.ts": 1780480414.9568844,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/table.ts": 1779257771.098434,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/menu.ts": 1779790340.600478,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/menu.ts": 1780480414.9564605,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/setting.ts": 1778582068.0225098,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts": 1779938228.2554607,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts": 1780540187.1384017,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/routesAlias.ts": 1778582068.0211735,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/index.ts": 1779232037.727516,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/index.ts": 1780480414.9557922,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/RouteTransformer.ts": 1778582068.0132053,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/RouteValidator.ts": 1778582068.013567,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/ComponentLoader.ts": 1778582068.0119128,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/MenuProcessor.ts": 1779882681.9204168,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/MenuProcessor.ts": 1780480414.955383,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/RouteRegistry.ts": 1778582068.0129957,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/RoutePermissionValidator.ts": 1778582068.0127926,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/index.ts": 1778582068.0138035,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/core/IframeRouteManager.ts": 1778582068.0121944,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/sqxp.ts": 1780457411.241232,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/index.ts": 1778598510.6043763,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/exception.ts": 1779546186.993006,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/routes/staticRoutes.ts": 1779546226.1088154,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/index.ts": 1780480414.9561174,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/modules/exception.ts": 1780480414.9559598,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/routes/staticRoutes.ts": 1780480414.9562852,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/routes/asyncRoutes.ts": 1778582068.0206802,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/guards/beforeEach.ts": 1779938234.2979362,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/guards/beforeEach.ts": 1780480414.9556284,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/router/guards/afterEach.ts": 1778582068.0146143,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/assets/svg/my-copy.svg": 1778582067.9349968,
|
||||
"/Users/wuzilong/work/00code/zkxw/web-admin/src/assets/svg/search.svg": 1778582067.9393654,
|
||||
|
||||
@@ -38,6 +38,9 @@ export function fetchGetUserInfo() {
|
||||
username: string
|
||||
realName: string
|
||||
phone: string
|
||||
email?: string
|
||||
sex?: string
|
||||
remark?: string
|
||||
role: string
|
||||
regionId: string
|
||||
regionName: string
|
||||
@@ -50,6 +53,50 @@ export function fetchGetUserInfo() {
|
||||
})
|
||||
}
|
||||
|
||||
/** 当前用户更新个人信息 */
|
||||
export function fetchUpdateProfile(data: {
|
||||
phoneNo?: string
|
||||
email?: string
|
||||
sex?: string
|
||||
remark?: string
|
||||
avatarUrl?: string
|
||||
}) {
|
||||
return request.put<{
|
||||
id: string
|
||||
username: string
|
||||
realName: string
|
||||
phone: string
|
||||
email?: string
|
||||
sex?: string
|
||||
remark?: string
|
||||
role: string
|
||||
regionId: string
|
||||
regionName: string
|
||||
avatarUrl?: string | null
|
||||
}>({
|
||||
url: '/web/auth/profile',
|
||||
data,
|
||||
showSuccessMessage: true
|
||||
})
|
||||
}
|
||||
|
||||
/** 当前用户上传头像 */
|
||||
export function fetchUploadProfileAvatar(data: FormData) {
|
||||
return request.post<{ url: string }>({
|
||||
url: '/web/auth/upload-avatar',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
/** 当前用户修改密码 */
|
||||
export function fetchChangePassword(data: { oldPassword: string; newPassword: string }) {
|
||||
return request.post({
|
||||
url: '/web/auth/change-password',
|
||||
data,
|
||||
showSuccessMessage: true
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户菜单 code 权限
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!-- 用户菜单 -->
|
||||
<template>
|
||||
<ElPopover
|
||||
<div class="user-menu-root">
|
||||
<ElPopover
|
||||
ref="userMenuPopover"
|
||||
placement="bottom-end"
|
||||
:width="240"
|
||||
@@ -13,16 +14,21 @@
|
||||
>
|
||||
<template #reference>
|
||||
<div class="user-avatar-wrapper">
|
||||
<el-avatar :size="34" :src="avatarDisplayUrl">
|
||||
{{ userInfo.realName?.charAt(0) || userInfo.username?.charAt(0) || '管' }}
|
||||
<el-avatar :size="34" :src="avatarDisplayUrl || undefined" :key="avatarDisplayUrl">
|
||||
<span v-if="showAvatarInitial">{{ avatarInitialText }}</span>
|
||||
</el-avatar>
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
<div class="pt-3">
|
||||
<div class="flex-c pb-1 px-0">
|
||||
<el-avatar :size="40" :src="avatarDisplayUrl" style="margin-right: 12px">
|
||||
{{ userInfo.realName?.charAt(0) || userInfo.username?.charAt(0) || '管' }}
|
||||
<el-avatar
|
||||
:size="40"
|
||||
:src="avatarDisplayUrl || undefined"
|
||||
:key="avatarDisplayUrl"
|
||||
style="margin-right: 12px"
|
||||
>
|
||||
<span v-if="showAvatarInitial">{{ avatarInitialText }}</span>
|
||||
</el-avatar>
|
||||
<div class="w-[calc(100%-60px)] h-full">
|
||||
<span class="block text-sm font-medium text-g-800 truncate">
|
||||
@@ -43,6 +49,15 @@
|
||||
<span>{{ userInfo.regionName }}</span>
|
||||
</li>
|
||||
<div class="w-full h-px my-2 bg-g-300/80"></div>
|
||||
<li class="btn-item" @click="openProfileDialog">
|
||||
<ArtSvgIcon icon="edit" />
|
||||
<span>个人信息</span>
|
||||
</li>
|
||||
<li class="btn-item" @click="openPasswordDialog">
|
||||
<ArtSvgIcon icon="ri:lock-password-line" />
|
||||
<span>修改密码</span>
|
||||
</li>
|
||||
<div class="w-full h-px my-2 bg-g-300/80"></div>
|
||||
<div class="log-out c-p" @click="loginOut">
|
||||
{{ $t('topBar.user.logout') }}
|
||||
</div>
|
||||
@@ -50,13 +65,23 @@
|
||||
</div>
|
||||
</template>
|
||||
</ElPopover>
|
||||
|
||||
<UserProfileDialog v-model:visible="profileDialogVisible" />
|
||||
<UserPasswordDialog v-model:visible="passwordDialogVisible" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { resolveUserAvatarUrl } from '@/utils/user-avatar'
|
||||
import {
|
||||
resolveUserAvatarFromInfo,
|
||||
pickUserAvatarRaw,
|
||||
hasCustomUserAvatar
|
||||
} from '@/utils/user-avatar'
|
||||
import UserProfileDialog from './UserProfileDialog.vue'
|
||||
import UserPasswordDialog from './UserPasswordDialog.vue'
|
||||
|
||||
defineOptions({ name: 'ArtUserMenu' })
|
||||
|
||||
@@ -64,11 +89,31 @@
|
||||
|
||||
const { getUserInfo: userInfo } = storeToRefs(userStore)
|
||||
|
||||
const avatarDisplayUrl = computed(() =>
|
||||
resolveUserAvatarUrl(userInfo.value.avatarUrl, userInfo.value.role)
|
||||
const avatarDisplayUrl = computed(() => resolveUserAvatarFromInfo(userInfo.value))
|
||||
|
||||
const showAvatarInitial = computed(() => !hasCustomUserAvatar(pickUserAvatarRaw(userInfo.value)))
|
||||
|
||||
const avatarInitialText = computed(
|
||||
() => userInfo.value.realName?.charAt(0) || userInfo.value.username?.charAt(0) || '管'
|
||||
)
|
||||
|
||||
const userMenuPopover = ref()
|
||||
const profileDialogVisible = ref(false)
|
||||
const passwordDialogVisible = ref(false)
|
||||
|
||||
function openProfileDialog() {
|
||||
closeUserMenu()
|
||||
setTimeout(() => {
|
||||
profileDialogVisible.value = true
|
||||
}, 150)
|
||||
}
|
||||
|
||||
function openPasswordDialog() {
|
||||
closeUserMenu()
|
||||
setTimeout(() => {
|
||||
passwordDialogVisible.value = true
|
||||
}, 150)
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色名称
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<!-- 当前用户修改密码 -->
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="修改密码"
|
||||
width="480px"
|
||||
class="dialog-form-layout"
|
||||
align-center
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
scroll-to-error
|
||||
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
||||
>
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="原密码" prop="oldPassword" class="form-col-span-2">
|
||||
<el-input
|
||||
v-model="formData.oldPassword"
|
||||
type="password"
|
||||
show-password
|
||||
placeholder="请输入原密码"
|
||||
autocomplete="current-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="新密码" prop="newPassword" class="form-col-span-2">
|
||||
<el-input
|
||||
v-model="formData.newPassword"
|
||||
type="password"
|
||||
show-password
|
||||
placeholder="至少 6 位"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="确认新密码" prop="confirmPassword" class="form-col-span-2">
|
||||
<el-input
|
||||
v-model="formData.confirmPassword"
|
||||
type="password"
|
||||
show-password
|
||||
placeholder="请再次输入新密码"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button class="btn-ghost" @click="handleClose">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" :loading="submitting" @click="handleSubmit">
|
||||
<el-icon><Check /></el-icon>
|
||||
确定
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch } from 'vue'
|
||||
import type { FormInstance, FormRules } from 'element-plus'
|
||||
import { Close, Check } from '@element-plus/icons-vue'
|
||||
import { fetchChangePassword } from '@/api/auth'
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void
|
||||
}>()
|
||||
|
||||
const formRef = ref<FormInstance>()
|
||||
const submitting = ref(false)
|
||||
|
||||
const formData = reactive({
|
||||
oldPassword: '',
|
||||
newPassword: '',
|
||||
confirmPassword: ''
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
oldPassword: [{ required: true, message: '请输入原密码', trigger: 'blur' }],
|
||||
newPassword: [
|
||||
{ required: true, message: '请输入新密码', trigger: 'blur' },
|
||||
{ min: 6, message: '新密码长度不能少于 6 位', trigger: 'blur' }
|
||||
],
|
||||
confirmPassword: [
|
||||
{ required: true, message: '请再次输入新密码', trigger: 'blur' },
|
||||
{
|
||||
validator: (_rule, value, callback) => {
|
||||
if (value !== formData.newPassword) {
|
||||
callback(new Error('两次输入的新密码不一致'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val)
|
||||
})
|
||||
|
||||
function resetForm() {
|
||||
formData.oldPassword = ''
|
||||
formData.newPassword = ''
|
||||
formData.confirmPassword = ''
|
||||
formRef.value?.clearValidate?.()
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!formRef.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
await fetchChangePassword({
|
||||
oldPassword: formData.oldPassword,
|
||||
newPassword: formData.newPassword
|
||||
})
|
||||
dialogVisible.value = false
|
||||
} catch {
|
||||
/* 校验或接口错误已由全局处理 */
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val) {
|
||||
resetForm()
|
||||
}
|
||||
}
|
||||
)
|
||||
</script>
|
||||
@@ -0,0 +1,326 @@
|
||||
<!-- 当前用户个人信息编辑 -->
|
||||
<template>
|
||||
<el-dialog
|
||||
v-model="dialogVisible"
|
||||
title="个人信息"
|
||||
width="560px"
|
||||
class="dialog-form-layout"
|
||||
align-center
|
||||
destroy-on-close
|
||||
:close-on-click-modal="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-position="top"
|
||||
scroll-to-error
|
||||
:scroll-into-view-options="{ behavior: 'smooth', block: 'center' }"
|
||||
>
|
||||
<div class="form-grid-2">
|
||||
<el-form-item label="头像" class="form-col-span-2">
|
||||
<div class="profile-avatar-row">
|
||||
<el-avatar
|
||||
:size="72"
|
||||
:src="avatarPreviewUrl || undefined"
|
||||
:key="avatarPreviewKey"
|
||||
>
|
||||
<span v-if="showAvatarInitial">{{ avatarInitial }}</span>
|
||||
</el-avatar>
|
||||
<div class="profile-avatar-actions">
|
||||
<div class="profile-avatar-btns">
|
||||
<el-upload
|
||||
ref="avatarUploadRef"
|
||||
accept="image/*"
|
||||
:show-file-list="false"
|
||||
:auto-upload="false"
|
||||
:disabled="avatarUploading"
|
||||
@change="handleAvatarChange"
|
||||
>
|
||||
<el-button class="btn-ghost" :loading="avatarUploading">
|
||||
<el-icon><Upload /></el-icon>
|
||||
上传头像
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<el-button
|
||||
v-if="formData.avatarUrl"
|
||||
class="btn-ghost"
|
||||
:disabled="avatarUploading"
|
||||
@click="handleClearAvatar"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
恢复默认
|
||||
</el-button>
|
||||
</div>
|
||||
<p class="profile-avatar-tip">支持 JPG、PNG 等图片,大小不超过 2MB</p>
|
||||
</div>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号" prop="phoneNo">
|
||||
<el-input v-model="formData.phoneNo" placeholder="选填" maxlength="11" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="邮箱" prop="email">
|
||||
<el-input v-model="formData.email" placeholder="选填" maxlength="50" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="性别" prop="sex">
|
||||
<el-select v-model="formData.sex" placeholder="请选择" style="width: 100%">
|
||||
<el-option label="男" value="0" />
|
||||
<el-option label="女" value="1" />
|
||||
<el-option label="未知" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" class="form-col-span-2">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="选填"
|
||||
maxlength="512"
|
||||
show-word-limit
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button class="btn-ghost" @click="handleClose">
|
||||
<el-icon><Close /></el-icon>
|
||||
取消
|
||||
</el-button>
|
||||
<el-button class="btn-main" type="primary" :loading="submitting" @click="handleSubmit">
|
||||
<el-icon><Check /></el-icon>
|
||||
保存
|
||||
</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed, watch, onBeforeUnmount } from 'vue'
|
||||
import type { FormInstance, FormRules, UploadFile, UploadInstance } from 'element-plus'
|
||||
import { Close, Check, Upload, Delete } from '@element-plus/icons-vue'
|
||||
import { fetchGetUserInfo, fetchUpdateProfile, fetchUploadProfileAvatar } from '@/api/auth'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import {
|
||||
pickUserAvatarRaw,
|
||||
pickUploadAvatarUrl,
|
||||
hasCustomUserAvatar,
|
||||
resolveUserAvatarUrl
|
||||
} from '@/utils/user-avatar'
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:visible', val: boolean): void
|
||||
}>()
|
||||
|
||||
const userStore = useUserStore()
|
||||
const formRef = ref<FormInstance>()
|
||||
const avatarUploadRef = ref<UploadInstance>()
|
||||
const submitting = ref(false)
|
||||
const avatarUploading = ref(false)
|
||||
const avatarLocalPreview = ref('')
|
||||
const displayRole = ref('')
|
||||
|
||||
const formData = reactive({
|
||||
phoneNo: '',
|
||||
email: '',
|
||||
sex: '0',
|
||||
remark: '',
|
||||
avatarUrl: ''
|
||||
})
|
||||
|
||||
const formRules: FormRules = {
|
||||
phoneNo: [
|
||||
{
|
||||
validator: (_rule, value, callback) => {
|
||||
const v = (value || '').trim()
|
||||
if (v && !/^1\d{10}$/.test(v)) {
|
||||
callback(new Error('请输入正确的手机号'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
],
|
||||
email: [
|
||||
{
|
||||
validator: (_rule, value, callback) => {
|
||||
const v = (value || '').trim()
|
||||
if (v && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)) {
|
||||
callback(new Error('请输入正确的邮箱'))
|
||||
return
|
||||
}
|
||||
callback()
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const dialogVisible = computed({
|
||||
get: () => props.visible,
|
||||
set: (val) => emit('update:visible', val)
|
||||
})
|
||||
|
||||
const avatarPreviewUrl = computed(() => {
|
||||
if (avatarLocalPreview.value) return avatarLocalPreview.value
|
||||
return resolveUserAvatarUrl(formData.avatarUrl, displayRole.value)
|
||||
})
|
||||
|
||||
const avatarPreviewKey = computed(
|
||||
() => avatarLocalPreview.value || formData.avatarUrl || 'default-avatar'
|
||||
)
|
||||
|
||||
const showAvatarInitial = computed(
|
||||
() => !avatarLocalPreview.value && !hasCustomUserAvatar(formData.avatarUrl)
|
||||
)
|
||||
|
||||
const avatarInitial = computed(() => {
|
||||
const info = userStore.getUserInfo
|
||||
return info.realName?.charAt(0) || info.username?.charAt(0) || '管'
|
||||
})
|
||||
|
||||
function revokeAvatarLocalPreview() {
|
||||
if (avatarLocalPreview.value) {
|
||||
URL.revokeObjectURL(avatarLocalPreview.value)
|
||||
avatarLocalPreview.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
dialogVisible.value = false
|
||||
}
|
||||
|
||||
function handleClearAvatar() {
|
||||
formData.avatarUrl = ''
|
||||
revokeAvatarLocalPreview()
|
||||
avatarUploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
async function loadProfile() {
|
||||
const data = await fetchGetUserInfo()
|
||||
formData.phoneNo = data.phone || ''
|
||||
formData.email = data.email || ''
|
||||
formData.sex = data.sex || '0'
|
||||
formData.remark = data.remark || ''
|
||||
formData.avatarUrl = pickUserAvatarRaw(data) || pickUserAvatarRaw(userStore.getUserInfo) || ''
|
||||
displayRole.value = data.role || userStore.getUserInfo.role || ''
|
||||
revokeAvatarLocalPreview()
|
||||
avatarUploadRef.value?.clearFiles()
|
||||
}
|
||||
|
||||
async function handleAvatarChange(uploadFile: UploadFile) {
|
||||
const file = uploadFile.raw
|
||||
if (!file) return
|
||||
if (uploadFile.status && uploadFile.status !== 'ready') return
|
||||
|
||||
if (!file.type.startsWith('image/')) {
|
||||
ElMessage.error('仅支持上传图片文件')
|
||||
avatarUploadRef.value?.clearFiles()
|
||||
return
|
||||
}
|
||||
if (file.size > 2 * 1024 * 1024) {
|
||||
ElMessage.error('头像大小不能超过 2MB')
|
||||
avatarUploadRef.value?.clearFiles()
|
||||
return
|
||||
}
|
||||
|
||||
avatarUploading.value = true
|
||||
revokeAvatarLocalPreview()
|
||||
avatarLocalPreview.value = URL.createObjectURL(file)
|
||||
try {
|
||||
const fd = new FormData()
|
||||
fd.append('file', file)
|
||||
const res = await fetchUploadProfileAvatar(fd)
|
||||
const stored = pickUploadAvatarUrl(res)
|
||||
if (!stored) {
|
||||
ElMessage.error('上传成功但未返回图片地址')
|
||||
handleClearAvatar()
|
||||
return
|
||||
}
|
||||
formData.avatarUrl = stored
|
||||
ElMessage.success('头像上传成功')
|
||||
} catch {
|
||||
handleClearAvatar()
|
||||
} finally {
|
||||
avatarUploading.value = false
|
||||
avatarUploadRef.value?.clearFiles()
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!formRef.value) return
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
const updated = await fetchUpdateProfile({
|
||||
phoneNo: formData.phoneNo.trim() || undefined,
|
||||
email: formData.email.trim() || undefined,
|
||||
sex: formData.sex,
|
||||
remark: formData.remark.trim() || undefined,
|
||||
avatarUrl: formData.avatarUrl || ''
|
||||
})
|
||||
userStore.setUserInfo({
|
||||
phone: updated.phone,
|
||||
email: updated.email,
|
||||
sex: updated.sex,
|
||||
remark: updated.remark,
|
||||
avatarUrl: pickUserAvatarRaw(updated)
|
||||
})
|
||||
dialogVisible.value = false
|
||||
} catch {
|
||||
/* 校验或接口错误已由全局处理 */
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.visible,
|
||||
(val) => {
|
||||
if (val) {
|
||||
loadProfile().catch(() => {})
|
||||
formRef.value?.clearValidate?.()
|
||||
} else {
|
||||
revokeAvatarLocalPreview()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
revokeAvatarLocalPreview()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.profile-avatar-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.profile-avatar-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.profile-avatar-btns {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.profile-avatar-tip {
|
||||
margin: 0;
|
||||
font-size: 12px;
|
||||
color: var(--mint-text-muted, #64748b);
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "label": "UserProfileDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L1"}, {"id": "widget_userprofiledialog_revokeavatarlocalpreview", "label": "revokeAvatarLocalPreview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L168"}, {"id": "widget_userprofiledialog_handleclose", "label": "handleClose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L175"}, {"id": "widget_userprofiledialog_handleclearavatar", "label": "handleClearAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L179"}, {"id": "widget_userprofiledialog_loadprofile", "label": "loadProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L185"}, {"id": "widget_userprofiledialog_handleavatarchange", "label": "handleAvatarChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L197"}, {"id": "widget_userprofiledialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L230"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L94", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L95", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L96", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L97", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L98", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_revokeavatarlocalpreview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L168", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleclose", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L175", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "label": "user-avatar.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L1"}, {"id": "utils_user_avatar_defaultavatarpathbyrole", "label": "defaultAvatarPathByRole()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L7"}, {"id": "utils_user_avatar_pickuseravatarraw", "label": "pickUserAvatarRaw()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L12"}, {"id": "utils_user_avatar_resolvestoragefileurl", "label": "resolveStorageFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L21"}, {"id": "utils_user_avatar_resolveuseravatarurl", "label": "resolveUserAvatarUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L30"}, {"id": "utils_user_avatar_resolveuseravatarfrominfo", "label": "resolveUserAvatarFromInfo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L40"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_defaultavatarpathbyrole", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_pickuseravatarraw", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolvestoragefileurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L21", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L30", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarfrominfo", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L40", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarurl", "target": "utils_user_avatar_resolvestoragefileurl", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L35", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarurl", "target": "utils_user_avatar_defaultavatarpathbyrole", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L36", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarfrominfo", "target": "utils_user_avatar_resolveuseravatarurl", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L43", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarfrominfo", "target": "utils_user_avatar_pickuseravatarraw", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L43", "weight": 1.0}], "raw_calls": [{"caller_nid": "utils_user_avatar_pickuseravatarraw", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L17"}, {"caller_nid": "utils_user_avatar_pickuseravatarraw", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L17"}, {"caller_nid": "utils_user_avatar_resolvestoragefileurl", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L22"}, {"caller_nid": "utils_user_avatar_resolvestoragefileurl", "callee": "String", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L22"}, {"caller_nid": "utils_user_avatar_resolvestoragefileurl", "callee": "test", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_loLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "label": "UserProfileDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L1"}, {"id": "widget_userprofiledialog_revokeavatarlocalpreview", "label": "revokeAvatarLocalPreview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L187"}, {"id": "widget_userprofiledialog_handleclose", "label": "handleClose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L194"}, {"id": "widget_userprofiledialog_handleclearavatar", "label": "handleClearAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L198"}, {"id": "widget_userprofiledialog_loadprofile", "label": "loadProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L204"}, {"id": "widget_userprofiledialog_handleavatarchange", "label": "handleAvatarChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L216"}, {"id": "widget_userprofiledialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L255"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L100", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L101", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L102", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L103", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L104", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_revokeavatarlocalpreview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L187", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleclose", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L194", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_hLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "label": "auth.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L1"}, {"id": "api_auth_fetchlogin", "label": "fetchLogin()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L9"}, {"id": "api_auth_fetchgetuserinfo", "label": "fetchGetUserInfo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L35"}, {"id": "api_auth_fetchupdateprofile", "label": "fetchUpdateProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L57"}, {"id": "api_auth_fetchuploadprofileavatar", "label": "fetchUploadProfileAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L84"}, {"id": "api_auth_fetchchangepassword", "label": "fetchChangePassword()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L92"}, {"id": "api_auth_fetchgetmenucodes", "label": "fetchGetMenuCodes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L103"}, {"id": "api_auth_fetchrefreshtoken", "label": "fetchRefreshToken()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L118"}, {"id": "api_auth_fetchlogout", "label": "fetchLogout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L132"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_http", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_loginrsa", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchlogin", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchgetuserinfo", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchupdateprofile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L57", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchuploadprofileavatar", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L84", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchchangepassword", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L92", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchgetmenucodes", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L103", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchrefreshtoken", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L118", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchlogout", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L132", "weight": 1.0}], "raw_calls": [{"caller_nid": "api_auth_fetchlogin", "callee": "buildWebEncryptedLoginBody", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L10"}, {"caller_nid": "api_auth_fetchlogin", "callee": "post", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "label": "UserProfileDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L1"}, {"id": "widget_userprofiledialog_handleclose", "label": "handleClose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L120"}, {"id": "widget_userprofiledialog_loadprofile", "label": "loadProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L124"}, {"id": "widget_userprofiledialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L132"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L62", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L63", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L64", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L65", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleclose", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L120", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_loadprofile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L124", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handlesubmit", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L132", "weight": 1.0}], "raw_calls": [{"caller_nid": "widget_userprofiledialog_loadprofile", "callee": "fetchGetUserInfo", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L125"}, {"caller_nid": "widget_userprofiledialog_handlesubmit", "callee": "validate", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L135"}, {"caller_nid": "widget_userprofiledialog_handlesubmit", "callee": "fetchUpdateProfile", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L137"}, {"caller_nid": "widget_userprofiledialog_handlesubmit", "callee": "trim", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L138"}, {"caller_nid": "widget_userprofiledialog_handLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "label": "user-avatar.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L1"}, {"id": "utils_user_avatar_joinpublicasset", "label": "joinPublicAsset()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L2"}, {"id": "utils_user_avatar_defaultavatarpathbyrole", "label": "defaultAvatarPathByRole()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L14"}, {"id": "utils_user_avatar_normalizeavatarstoragekey", "label": "normalizeAvatarStorageKey()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L22"}, {"id": "utils_user_avatar_pickuseravatarraw", "label": "pickUserAvatarRaw()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L44"}, {"id": "utils_user_avatar_hascustomuseravatar", "label": "hasCustomUserAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L53"}, {"id": "utils_user_avatar_pickuploadavatarurl", "label": "pickUploadAvatarUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L58"}, {"id": "utils_user_avatar_resolvestoragefileurl", "label": "resolveStorageFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L69"}, {"id": "utils_user_avatar_resolveuseravatarurl", "label": "resolveUserAvatarUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L78"}, {"id": "utils_user_avatar_resolveuseravatarfrominfo", "label": "resolveUserAvatarFromInfo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L88"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_joinpublicasset", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_defaultavatarpathbyrole", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L14", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_normalizeavatarstoragekey", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L22", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_pickuseravatarraw", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L44", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_hascustomuseravatar", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L53", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_pickuploadavatarurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L58", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolvestoragefileurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L69", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L78", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarfrominfo", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "sLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "label": "ProtocolFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1"}, {"id": "protocol_protocolformdialog_fmtmoney", "label": "fmtMoney()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1218"}, {"id": "protocol_protocolformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1290"}, {"id": "protocol_protocolformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1310"}, {"id": "protocol_protocolformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1317"}, {"id": "protocol_protocolformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1328"}, {"id": "protocol_protocolformdialog_expressname", "label": "expressName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1356"}, {"id": "protocol_protocolformdialog_for", "label": "for()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L2131"}, {"id": "protocol_protocolformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L2668"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1152", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1153", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1165", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_business", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1171", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_download_attachment", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1172", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1173", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_ethnic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1185", "weight": 1.0}, {"source":Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "label": "protocol-fq-params-change.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L1"}, {"id": "utils_protocol_fq_params_change_formatmoneysummary", "label": "formatMoneySummary()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L26"}, {"id": "utils_protocol_fq_params_change_countbystatus", "label": "countByStatus()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L30"}, {"id": "utils_protocol_fq_params_change_fqparamssnapshot", "label": "fqParamsSnapshot()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L34"}, {"id": "utils_protocol_fq_params_change_issamefqparams", "label": "isSameFqParams()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L42"}, {"id": "utils_protocol_fq_params_change_getpaidinstallmentrows", "label": "getPaidInstallmentRows()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L50"}, {"id": "utils_protocol_fq_params_change_maxpaidinstallmentno", "label": "maxPaidInstallmentNo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L56"}, {"id": "utils_protocol_fq_params_change_evaluatefqparamschange", "label": "evaluateFqParamsChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L63"}, {"id": "utils_protocol_fq_params_change_applyfqparamschange", "label": "applyFqParamsChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L143"}, {"id": "utils_protocol_fq_params_change_generateinitialfqdetails", "label": "generateInitialFqDetails()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L182"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "utils_protocol_fq_params_change_formatmoneysummary", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L26", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "utils_protocol_fq_params_change_countbystatus", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L30", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "utils_protocol_fq_params_change_fqparamssnapshot", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L34", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "utils_protocol_fq_params_change_issamefqparams", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L42", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_fq_params_change_ts", "target": "utils_protocol_fq_params_change_getpaidinstallmentrows", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-fq-params-change.ts", "source_location": "L50", "wLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "label": "ArtUserMenu.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L1"}, {"id": "widget_artusermenu_openprofiledialog", "label": "openProfileDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L91"}, {"id": "widget_artusermenu_openpassworddialog", "label": "openPasswordDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L98"}, {"id": "widget_artusermenu_getrolename", "label": "getRoleName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L108"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openprofiledialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L91", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openpassworddialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L98", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_getrolename", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L108", "weight": 1.0}], "raw_calls": [{"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L92"}, {"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L93"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L99"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L100"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "label": "user-avatar.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L1"}, {"id": "utils_user_avatar_joinpublicasset", "label": "joinPublicAsset()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L2"}, {"id": "utils_user_avatar_defaultavatarpathbyrole", "label": "defaultAvatarPathByRole()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L14"}, {"id": "utils_user_avatar_pickuseravatarraw", "label": "pickUserAvatarRaw()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L19"}, {"id": "utils_user_avatar_hascustomuseravatar", "label": "hasCustomUserAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L28"}, {"id": "utils_user_avatar_pickuploadavatarurl", "label": "pickUploadAvatarUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L33"}, {"id": "utils_user_avatar_resolvestoragefileurl", "label": "resolveStorageFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L44"}, {"id": "utils_user_avatar_resolveuseravatarurl", "label": "resolveUserAvatarUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L53"}, {"id": "utils_user_avatar_resolveuseravatarfrominfo", "label": "resolveUserAvatarFromInfo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L63"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_joinpublicasset", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_defaultavatarpathbyrole", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L14", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_pickuseravatarraw", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_hascustomuseravatar", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L28", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_pickuploadavatarurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L33", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolvestoragefileurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L44", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarurl", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L53", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar_ts", "target": "utils_user_avatar_resolveuseravatarfrominfo", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L63", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarurl", "target": "utils_user_avatar_resolvestoragefileurl", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/user-avatar.ts", "source_location": "L58", "weight": 1.0}, {"source": "utils_user_avatar_resolveuseravatarurl", "target": "utils_user_avatar_defaultavatarpathbyrole", "relation": "calls", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utilLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "label": "auth.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L1"}, {"id": "api_auth_fetchlogin", "label": "fetchLogin()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L9"}, {"id": "api_auth_fetchgetuserinfo", "label": "fetchGetUserInfo()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L35"}, {"id": "api_auth_fetchupdateprofile", "label": "fetchUpdateProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L57"}, {"id": "api_auth_fetchchangepassword", "label": "fetchChangePassword()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L83"}, {"id": "api_auth_fetchgetmenucodes", "label": "fetchGetMenuCodes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L94"}, {"id": "api_auth_fetchrefreshtoken", "label": "fetchRefreshToken()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L109"}, {"id": "api_auth_fetchlogout", "label": "fetchLogout()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L123"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_http", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_loginrsa", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L2", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchlogin", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchgetuserinfo", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchupdateprofile", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L57", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchchangepassword", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L83", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchgetmenucodes", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L94", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchrefreshtoken", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L109", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth_ts", "target": "api_auth_fetchlogout", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L123", "weight": 1.0}], "raw_calls": [{"caller_nid": "api_auth_fetchlogin", "callee": "buildWebEncryptedLoginBody", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L10"}, {"caller_nid": "api_auth_fetchlogin", "callee": "post", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L11"}, {"caller_nid": "api_auth_fetchgetuserinfo", "callee": "get", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L36"}, {"caller_nid": "api_auth_fetchupdateprofile", "callee": "put", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts", "source_location": "L63"}, {"caller_nid": "api_auth_fetchchangepassword", "callee": "post", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/api/auth.ts",Line truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "label": "ArtUserMenu.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L1"}, {"id": "widget_artusermenu_openprofiledialog", "label": "openProfileDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L89"}, {"id": "widget_artusermenu_openpassworddialog", "label": "openPasswordDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L96"}, {"id": "widget_artusermenu_getrolename", "label": "getRoleName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L106"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openprofiledialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L89", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openpassworddialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L96", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_getrolename", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L106", "weight": 1.0}], "raw_calls": [{"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L90"}, {"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L91"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L97"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L98"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_api_d_ts", "label": "api.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api.d.ts", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_types_api_d_ts", "target": "vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/api.d.ts", "source_location": "L793", "weight": 1.0}], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "label": "protocol-pay-mode-switch.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L1"}, {"id": "utils_protocol_pay_mode_switch_ispaydetaillocked", "label": "isPayDetailLocked()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L30"}, {"id": "utils_protocol_pay_mode_switch_markpaydetaillocks", "label": "markPayDetailLocks()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L35"}, {"id": "utils_protocol_pay_mode_switch_sumpaidamount", "label": "sumPaidAmount()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L41"}, {"id": "utils_protocol_pay_mode_switch_calcremainingamount", "label": "calcRemainingAmount()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L47"}, {"id": "utils_protocol_pay_mode_switch_formatmoneysummary", "label": "formatMoneySummary()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L56"}, {"id": "utils_protocol_pay_mode_switch_activedetails", "label": "activeDetails()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L60"}, {"id": "utils_protocol_pay_mode_switch_hasblockingstatus", "label": "hasBlockingStatus()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L64"}, {"id": "utils_protocol_pay_mode_switch_countbystatus", "label": "countByStatus()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L68"}, {"id": "utils_protocol_pay_mode_switch_createpaymentdetailrow", "label": "createPaymentDetailRow()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L72"}, {"id": "utils_protocol_pay_mode_switch_evaluatepaymodeswitch", "label": "evaluatePayModeSwitch()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L96"}, {"id": "utils_protocol_pay_mode_switch_applypaymodeswitch", "label": "applyPayModeSwitch()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L162"}, {"id": "utils_protocol_pay_mode_switch_canaddpaymentdetail", "label": "canAddPaymentDetail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L210"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "target": "utils_protocol_pay_mode_switch_ispaydetaillocked", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L30", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "target": "utils_protocol_pay_mode_switch_markpaydetaillocks", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "target": "utils_protocol_pay_mode_switch_sumpaidamount", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L41", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_pay_mode_switch_ts", "target": "utils_protocol_pay_mode_switch_calcremainingamount", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-pay-mode-switch.ts", "source_location": "L47", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utiLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "label": "user.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "pinia", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L16", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_enums_appenum", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L17", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_router", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L18", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_worktab", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_types_router", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L20", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_router_guards_beforeeach", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L21", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_menu", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L22", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_storage_storage_config", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L23", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L24", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_router_routesalias", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L25", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_router", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L26", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user_ts", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/store/modules/user.ts", "source_location": "L27", "weight": 1.0}], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "label": "ArtUserMenu.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L1"}, {"id": "widget_artusermenu_openprofiledialog", "label": "openProfileDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L104"}, {"id": "widget_artusermenu_openpassworddialog", "label": "openPasswordDialog()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L111"}, {"id": "widget_artusermenu_getrolename", "label": "getRoleName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L121"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openprofiledialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L104", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_openpassworddialog", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L111", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_artusermenu_vue", "target": "widget_artusermenu_getrolename", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L121", "weight": 1.0}], "raw_calls": [{"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L105"}, {"caller_nid": "widget_artusermenu_openprofiledialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L106"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "closeUserMenu", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L112"}, {"caller_nid": "widget_artusermenu_openpassworddialog", "callee": "setTimeout", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue", "source_location": "L113"}]}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "label": "UserProfileDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L1"}, {"id": "widget_userprofiledialog_revokeavatarlocalpreview", "label": "revokeAvatarLocalPreview()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L168"}, {"id": "widget_userprofiledialog_handleclose", "label": "handleClose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L175"}, {"id": "widget_userprofiledialog_handleclearavatar", "label": "handleClearAvatar()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L179"}, {"id": "widget_userprofiledialog_loadprofile", "label": "loadProfile()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L185"}, {"id": "widget_userprofiledialog_handleavatarchange", "label": "handleAvatarChange()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L197"}, {"id": "widget_userprofiledialog_handlesubmit", "label": "handleSubmit()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L230"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L94", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L95", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_auth", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L96", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_store_modules_user", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L97", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_user_avatar", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L98", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_revokeavatarlocalpreview", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L168", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleclose", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/components/core/layouts/art-header-bar/widget/UserProfileDialog.vue", "source_location": "L175", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_components_core_layouts_art_header_bar_widget_userprofiledialog_vue", "target": "widget_userprofiledialog_handleLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_types_import_components_d_ts", "label": "components.d.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/types/import/components.d.ts", "source_location": "L1"}], "edges": [], "raw_calls": []}
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "label": "protocol-payment-installment.ts", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L1"}, {"id": "utils_protocol_payment_installment_addmonthsymd", "label": "addMonthsYmd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L5"}, {"id": "utils_protocol_payment_installment_adddaysymd", "label": "addDaysYmd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L19"}, {"id": "utils_protocol_payment_installment_addintervalmonthsymd", "label": "addIntervalMonthsYmd()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L34"}, {"id": "utils_protocol_payment_installment_calcfqinstallmentduedate", "label": "calcFqInstallmentDueDate()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L55"}, {"id": "utils_protocol_payment_installment_calcinstallmentdueamounts", "label": "calcInstallmentDueAmounts()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L67"}, {"id": "utils_protocol_payment_installment_alignfqpaymentdetailsfordisplay", "label": "alignFqPaymentDetailsForDisplay()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L93"}, {"id": "utils_protocol_payment_installment_sortfqpaymentdetails", "label": "sortFqPaymentDetails()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L160"}, {"id": "utils_protocol_payment_installment_syncfqpaymentdetailrowcount", "label": "syncFqPaymentDetailRowCount()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L170"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_addmonthsymd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_adddaysymd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L19", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_addintervalmonthsymd", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L34", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_calcfqinstallmentduedate", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L55", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_calcinstallmentdueamounts", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L67", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_alignfqpaymentdetailsfordisplay", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L93", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utils_protocol_payment_installment_sortfqpaymentdetails", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/utils/protocol-payment-installment.ts", "source_location": "L160", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_protocol_payment_installment_ts", "target": "utLine truncated
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "label": "ProtocolFormDialog.vue", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1"}, {"id": "protocol_protocolformdialog_fmtmoney", "label": "fmtMoney()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1213"}, {"id": "protocol_protocolformdialog_createemptytransport", "label": "createEmptyTransport()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1278"}, {"id": "protocol_protocolformdialog_fullfileurl", "label": "fullFileUrl()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1298"}, {"id": "protocol_protocolformdialog_loadethnicoptions", "label": "loadEthnicOptions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1305"}, {"id": "protocol_protocolformdialog_ensureethnicoptioninlist", "label": "ensureEthnicOptionInList()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1316"}, {"id": "protocol_protocolformdialog_expressname", "label": "expressName()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1344"}, {"id": "protocol_protocolformdialog_for", "label": "for()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L2070"}, {"id": "protocol_protocolformdialog_if", "label": "if()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L2607"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "element_plus", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1152", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "icons_vue", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1153", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_collection_protocol", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1165", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_business", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1171", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_utils_download_attachment", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1172", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_admin", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1173", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_web_admin_src_views_cell_storage_protocol_protocolformdialog_vue", "target": "users_wuzilong_work_00code_zkxw_web_admin_src_api_ethnic", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/web-admin/src/views/cell-storage/protocol/ProtocolFormDialog.vue", "source_location": "L1185", "weight": 1.0}, {"source":Line truncated
|
||||
@@ -24,6 +24,7 @@ import { StorageConfig } from '@/utils/storage/storage-config'
|
||||
import { fetchLogout } from '@/api/auth'
|
||||
import { RoutesAlias } from '@/router/routesAlias'
|
||||
import { resolveSafeRedirectTarget } from '@/utils/router'
|
||||
import { pickUserAvatarRaw } from '@/utils/user-avatar'
|
||||
|
||||
/**
|
||||
* 用户状态管理
|
||||
@@ -57,11 +58,13 @@ export const useUserStore = defineStore(
|
||||
* @param newInfo 新的用户信息
|
||||
*/
|
||||
const setUserInfo = (newInfo: Partial<Api.Auth.UserInfo> & Record<string, any>) => {
|
||||
const merged = { ...(info.value || {}), ...(newInfo || {}) }
|
||||
const avatarRaw = pickUserAvatarRaw(newInfo) || pickUserAvatarRaw(merged)
|
||||
info.value = {
|
||||
...(info.value || {}),
|
||||
...(newInfo || {}),
|
||||
...merged,
|
||||
buttons: newInfo?.buttons ?? info.value?.buttons ?? [],
|
||||
userName: newInfo?.userName ?? newInfo?.username ?? info.value?.userName ?? ''
|
||||
userName: newInfo?.userName ?? newInfo?.username ?? info.value?.userName ?? '',
|
||||
avatarUrl: avatarRaw || undefined
|
||||
} as Api.Auth.UserInfo
|
||||
}
|
||||
|
||||
|
||||
Vendored
+3
-1
@@ -9,10 +9,12 @@ declare namespace Api {
|
||||
username: string
|
||||
realName?: string
|
||||
phone?: string
|
||||
email?: string
|
||||
sex?: string
|
||||
remark?: string
|
||||
role: string
|
||||
regionId?: string
|
||||
regionName?: string
|
||||
email?: string
|
||||
roles?: string[]
|
||||
/** 自定义头像 URL,空则前端使用 `/avatart.jpg` */
|
||||
avatarUrl?: string | null
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
/**
|
||||
* 分期参数变更(期数 / 间隔 / 开始时间),非缴费模式切换
|
||||
* 规则见 docs/superpowers/specs/2026-06-04-protocol-pay-mode-switch-design.md §分期参数变更
|
||||
*/
|
||||
|
||||
import {
|
||||
calcFqInstallmentDueDate,
|
||||
calcInstallmentDueAmounts,
|
||||
sortFqPaymentDetails
|
||||
} from '@/utils/protocol-payment-installment'
|
||||
import {
|
||||
calcRemainingAmount,
|
||||
createPaymentDetailRow,
|
||||
type DetailLike,
|
||||
type EvaluateResult
|
||||
} from '@/utils/protocol-pay-mode-switch'
|
||||
|
||||
export interface FqParams {
|
||||
installmentCount: number | null
|
||||
installmentIntervalMonths: number | null
|
||||
installmentStartDate: string
|
||||
}
|
||||
|
||||
const BLOCKING_STATUSES = new Set(['jfqrz', 'tfqrz', 'ytf'])
|
||||
|
||||
function formatMoneySummary(v: number): string {
|
||||
return `¥${v.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`
|
||||
}
|
||||
|
||||
function countByStatus(details: DetailLike[], status: string): number {
|
||||
return details.filter((d) => String(d.payStatus || 'dfj') === status).length
|
||||
}
|
||||
|
||||
export function fqParamsSnapshot(params: FqParams): FqParams {
|
||||
return {
|
||||
installmentCount: params.installmentCount,
|
||||
installmentIntervalMonths: params.installmentIntervalMonths,
|
||||
installmentStartDate: params.installmentStartDate || ''
|
||||
}
|
||||
}
|
||||
|
||||
export function isSameFqParams(a: FqParams, b: FqParams): boolean {
|
||||
return (
|
||||
Number(a.installmentCount) === Number(b.installmentCount) &&
|
||||
Number(a.installmentIntervalMonths) === Number(b.installmentIntervalMonths) &&
|
||||
String(a.installmentStartDate || '') === String(b.installmentStartDate || '')
|
||||
)
|
||||
}
|
||||
|
||||
export function getPaidInstallmentRows(details: DetailLike[]): DetailLike[] {
|
||||
return [...details]
|
||||
.filter((d) => String(d.payStatus) === 'yjf')
|
||||
.sort((a, b) => Number(a.installmentNo || 0) - Number(b.installmentNo || 0))
|
||||
}
|
||||
|
||||
function maxPaidInstallmentNo(details: DetailLike[]): number {
|
||||
return getPaidInstallmentRows(details).reduce(
|
||||
(max, d) => Math.max(max, Number(d.installmentNo || 0)),
|
||||
0
|
||||
)
|
||||
}
|
||||
|
||||
export function evaluateFqParamsChange(
|
||||
_oldParams: FqParams,
|
||||
newParams: FqParams,
|
||||
details: DetailLike[],
|
||||
contractAmount: number | null
|
||||
): EvaluateResult {
|
||||
const rows = details.filter((d) => !d._voided)
|
||||
const newCount = Number(newParams.installmentCount)
|
||||
const interval = Number(newParams.installmentIntervalMonths)
|
||||
const startDate = String(newParams.installmentStartDate || '')
|
||||
|
||||
if (!newCount || newCount < 1) {
|
||||
return { action: 'blocked', reason: '请填写有效的分期期数。' }
|
||||
}
|
||||
if (!interval || interval <= 0) {
|
||||
return { action: 'blocked', reason: '请填写有效的每期间隔(月)。' }
|
||||
}
|
||||
if (!startDate) {
|
||||
return { action: 'blocked', reason: '请填写分期开始时间。' }
|
||||
}
|
||||
|
||||
if (rows.some((d) => BLOCKING_STATUSES.has(String(d.payStatus || '')))) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: '存在缴费确认中或退费处理中的明细,请先完成相关流程后再修改分期参数。'
|
||||
}
|
||||
}
|
||||
|
||||
const paidRows = getPaidInstallmentRows(rows)
|
||||
const maxPaidNo = maxPaidInstallmentNo(rows)
|
||||
|
||||
if (maxPaidNo > 0 && newCount < maxPaidNo) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: `已有第 ${maxPaidNo} 期缴费记录,分期期数不能少于 ${maxPaidNo}。`
|
||||
}
|
||||
}
|
||||
|
||||
const dfjCount = countByStatus(rows, 'dfj')
|
||||
|
||||
if (paidRows.length === 0) {
|
||||
if (rows.length === 0) {
|
||||
return { action: 'noop' }
|
||||
}
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将按新参数(${newCount} 期)重新生成缴费明细,原有 ${rows.length} 条待缴计划将被替换。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
const remaining = calcRemainingAmount(contractAmount, rows)
|
||||
const newUnpaidCount = newCount - paidRows.length
|
||||
|
||||
if (newUnpaidCount < 0) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: `已有 ${paidRows.length} 期缴费记录,分期期数不能少于 ${paidRows.length}。`
|
||||
}
|
||||
}
|
||||
|
||||
if (remaining <= 0 && dfjCount > 0) {
|
||||
return { action: 'blocked', reason: '已缴清,无需调整分期计划。' }
|
||||
}
|
||||
|
||||
const countChanged = Number(_oldParams.installmentCount) !== newCount
|
||||
|
||||
if (countChanged) {
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将保留 ${paidRows.length} 期已缴记录,作废 ${dfjCount} 期未缴计划,并重新生成 ${newUnpaidCount} 期未缴明细(剩余 ${formatMoneySummary(remaining)})。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将保留已缴记录,并更新 ${dfjCount} 期未缴计划的应缴时间与金额(剩余 ${formatMoneySummary(remaining)})。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
/** 按新分期参数重建明细:保留 yjf,作废原 dfj,生成剩余期次 */
|
||||
export function applyFqParamsChange(
|
||||
params: FqParams,
|
||||
details: DetailLike[],
|
||||
contractAmount: number | null
|
||||
): DetailLike[] {
|
||||
const count = Number(params.installmentCount) || 0
|
||||
const interval = Number(params.installmentIntervalMonths) || 0
|
||||
const startDate = params.installmentStartDate || ''
|
||||
if (!count || !interval || !startDate) return details
|
||||
|
||||
const paidRows = getPaidInstallmentRows(details).map((d) => ({
|
||||
...d,
|
||||
_payModeLocked: true
|
||||
}))
|
||||
const remainingCount = count - paidRows.length
|
||||
const remaining = calcRemainingAmount(contractAmount, paidRows)
|
||||
const amounts =
|
||||
remainingCount > 0
|
||||
? calcInstallmentDueAmounts(remaining, remainingCount)
|
||||
: []
|
||||
|
||||
const result: DetailLike[] = [...paidRows]
|
||||
|
||||
for (let i = 0; i < remainingCount; i++) {
|
||||
const periodIndex = paidRows.length + i
|
||||
result.push(
|
||||
createPaymentDetailRow({
|
||||
dueAmount: amounts[i] ?? null,
|
||||
installmentNo: periodIndex + 1,
|
||||
installmentDueDate: calcFqInstallmentDueDate(startDate, periodIndex, interval),
|
||||
expanded: false
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
return sortFqPaymentDetails(result)
|
||||
}
|
||||
|
||||
/** 首次填充分期参数时生成明细(无需确认) */
|
||||
export function generateInitialFqDetails(
|
||||
params: FqParams,
|
||||
contractAmount: number | null
|
||||
): DetailLike[] {
|
||||
const count = Number(params.installmentCount) || 0
|
||||
const interval = Number(params.installmentIntervalMonths) || 0
|
||||
const startDate = params.installmentStartDate || ''
|
||||
if (!count || !interval || !startDate) return []
|
||||
|
||||
const amounts = calcInstallmentDueAmounts(contractAmount, count)
|
||||
const result: DetailLike[] = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
result.push(
|
||||
createPaymentDetailRow({
|
||||
dueAmount: amounts[i] ?? null,
|
||||
installmentNo: i + 1,
|
||||
installmentDueDate: calcFqInstallmentDueDate(startDate, i, interval),
|
||||
expanded: i === 0
|
||||
})
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* 采集协议单 · 缴费模式切换(dj ↔ fq)
|
||||
* 规则见 docs/superpowers/specs/2026-06-04-protocol-pay-mode-switch-design.md
|
||||
*/
|
||||
|
||||
import {
|
||||
calcFqInstallmentDueDate,
|
||||
calcInstallmentDueAmounts
|
||||
} from '@/utils/protocol-payment-installment'
|
||||
|
||||
export type PayMode = 'dj' | 'fq'
|
||||
export type DetailLike = Record<string, any>
|
||||
|
||||
const LOCKED_STATUSES = new Set(['jfqrz', 'yjf', 'tfqrz', 'ytf'])
|
||||
const BLOCKING_STATUSES = new Set(['jfqrz', 'tfqrz', 'ytf'])
|
||||
|
||||
export interface PayModeSwitchContext {
|
||||
contractAmount: number | null
|
||||
lumpSumDeadline: string
|
||||
installmentCount: number | null
|
||||
installmentIntervalMonths: number | null
|
||||
installmentStartDate: string
|
||||
}
|
||||
|
||||
export type EvaluateResult =
|
||||
| { action: 'noop' }
|
||||
| { action: 'blocked'; reason: string }
|
||||
| { action: 'confirm'; summary: string }
|
||||
|
||||
export function isPayDetailLocked(detail: DetailLike): boolean {
|
||||
if (detail._payModeLocked) return true
|
||||
return LOCKED_STATUSES.has(String(detail.payStatus || ''))
|
||||
}
|
||||
|
||||
export function markPayDetailLocks(details: DetailLike[]): void {
|
||||
for (const d of details) {
|
||||
d._payModeLocked = isPayDetailLocked(d)
|
||||
}
|
||||
}
|
||||
|
||||
export function sumPaidAmount(details: DetailLike[]): number {
|
||||
return details
|
||||
.filter((d) => String(d.payStatus) === 'yjf')
|
||||
.reduce((sum, d) => sum + (Number(d.dueAmount) || 0), 0)
|
||||
}
|
||||
|
||||
export function calcRemainingAmount(
|
||||
contractAmount: number | null,
|
||||
details: DetailLike[]
|
||||
): number {
|
||||
if (contractAmount == null) return 0
|
||||
const remaining = Number(contractAmount) - sumPaidAmount(details)
|
||||
return Math.round(remaining * 100) / 100
|
||||
}
|
||||
|
||||
function formatMoneySummary(v: number): string {
|
||||
return `¥${v.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`
|
||||
}
|
||||
|
||||
function activeDetails(details: DetailLike[]): DetailLike[] {
|
||||
return details.filter((d) => !d._voided)
|
||||
}
|
||||
|
||||
function hasBlockingStatus(details: DetailLike[]): boolean {
|
||||
return details.some((d) => BLOCKING_STATUSES.has(String(d.payStatus || '')))
|
||||
}
|
||||
|
||||
function countByStatus(details: DetailLike[], status: string): number {
|
||||
return details.filter((d) => String(d.payStatus || 'dfj') === status).length
|
||||
}
|
||||
|
||||
export function createPaymentDetailRow(options: {
|
||||
dueAmount: number | null
|
||||
installmentDueDate?: string
|
||||
installmentNo?: number | null
|
||||
payStatus?: string
|
||||
expanded?: boolean
|
||||
}): DetailLike {
|
||||
const now = new Date()
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
const defaultTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||
return {
|
||||
transferType: '',
|
||||
dueAmount: options.dueAmount,
|
||||
transferAmount: null,
|
||||
transferTime: defaultTime,
|
||||
payStatus: options.payStatus ?? 'dfj',
|
||||
installmentNo: options.installmentNo ?? null,
|
||||
installmentDueDate: options.installmentDueDate ?? '',
|
||||
_expanded: options.expanded ?? false,
|
||||
_payModeLocked: false,
|
||||
attachments: []
|
||||
}
|
||||
}
|
||||
|
||||
export function evaluatePayModeSwitch(
|
||||
fromMode: PayMode,
|
||||
toMode: PayMode,
|
||||
details: DetailLike[],
|
||||
ctx: PayModeSwitchContext
|
||||
): EvaluateResult {
|
||||
if (fromMode === toMode) return { action: 'noop' }
|
||||
|
||||
const rows = activeDetails(details)
|
||||
|
||||
if (hasBlockingStatus(rows)) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: '存在缴费确认中或退费处理中的明细,请先完成相关流程后再切换缴费模式。'
|
||||
}
|
||||
}
|
||||
|
||||
if (fromMode === 'dj' && toMode === 'fq') {
|
||||
if (rows.some((d) => isPayDetailLocked(d))) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: '趸交已有缴费记录,无法改为分期。'
|
||||
}
|
||||
}
|
||||
const count = ctx.installmentCount || 6
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将清除当前趸交计划,按 ${count} 期分期重新生成缴费明细。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
if (fromMode === 'fq' && toMode === 'dj') {
|
||||
const dfjCount = countByStatus(rows, 'dfj')
|
||||
const yjfCount = countByStatus(rows, 'yjf')
|
||||
|
||||
if (yjfCount > 0 && dfjCount === 0) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: '分期已全部缴清,无需改为趸交。'
|
||||
}
|
||||
}
|
||||
|
||||
const remaining = calcRemainingAmount(ctx.contractAmount, rows)
|
||||
if (yjfCount > 0 && remaining <= 0) {
|
||||
return {
|
||||
action: 'blocked',
|
||||
reason: '已缴清,无需改为趸交。'
|
||||
}
|
||||
}
|
||||
|
||||
if (yjfCount > 0) {
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将作废 ${dfjCount} 期未缴计划,保留 ${yjfCount} 期已缴记录,并新增 1 条趸交明细(剩余 ${formatMoneySummary(remaining)})。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
action: 'confirm',
|
||||
summary: `将作废 ${dfjCount || rows.length} 期分期计划,并合并为 1 条趸交明细。是否继续?`
|
||||
}
|
||||
}
|
||||
|
||||
return { action: 'noop' }
|
||||
}
|
||||
|
||||
export function applyPayModeSwitch(
|
||||
fromMode: PayMode,
|
||||
toMode: PayMode,
|
||||
details: DetailLike[],
|
||||
ctx: PayModeSwitchContext
|
||||
): DetailLike[] {
|
||||
const rows = activeDetails(details)
|
||||
|
||||
if (fromMode === 'dj' && toMode === 'fq') {
|
||||
const count = Number(ctx.installmentCount) || 6
|
||||
const interval = Number(ctx.installmentIntervalMonths) || 6
|
||||
const startDate = ctx.installmentStartDate || ''
|
||||
const amounts = calcInstallmentDueAmounts(ctx.contractAmount, count)
|
||||
const result: DetailLike[] = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
result.push(
|
||||
createPaymentDetailRow({
|
||||
dueAmount: amounts[i] ?? null,
|
||||
installmentNo: i + 1,
|
||||
installmentDueDate:
|
||||
startDate && interval ? calcFqInstallmentDueDate(startDate, i, interval) : '',
|
||||
expanded: i === 0
|
||||
})
|
||||
)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (fromMode === 'fq' && toMode === 'dj') {
|
||||
const yjfRows = rows
|
||||
.filter((d) => String(d.payStatus) === 'yjf')
|
||||
.map((d) => ({ ...d, _payModeLocked: true }))
|
||||
const remaining = calcRemainingAmount(ctx.contractAmount, yjfRows)
|
||||
const deadline = ctx.lumpSumDeadline || ''
|
||||
const dueAmount = yjfRows.length ? remaining : ctx.contractAmount
|
||||
const newDjRow = createPaymentDetailRow({
|
||||
dueAmount,
|
||||
installmentNo: null,
|
||||
installmentDueDate: deadline,
|
||||
expanded: yjfRows.length === 0
|
||||
})
|
||||
return [...yjfRows, newDjRow]
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
/** 趸交模式下是否还可添加待缴明细 */
|
||||
export function canAddPaymentDetail(payMode: string, details: DetailLike[]): boolean {
|
||||
if (payMode === 'fq') return true
|
||||
const dfjCount = details.filter(
|
||||
(d) => !isPayDetailLocked(d) && String(d.payStatus || 'dfj') === 'dfj'
|
||||
).length
|
||||
return dfjCount < 1
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
/** 分期缴费:期数对齐、应缴日/金额计算(与 ProtocolFormDialog 逻辑一致) */
|
||||
|
||||
const DAYS_PER_MONTH = 30
|
||||
|
||||
export function addMonthsYmd(dateStr: string, months: number): string {
|
||||
const compact = String(dateStr || '').replace(/-/g, '')
|
||||
if (compact.length !== 8) return ''
|
||||
@@ -28,13 +30,34 @@ export function addDaysYmd(dateStr: string, days: number): string {
|
||||
return `${yy}${mm}${dd}`
|
||||
}
|
||||
|
||||
/** 分期应缴费时间:第 1 期=开始时间,第 2 期起在按月递增基础上提前 10 天 */
|
||||
/** 整数部分按日历加月,小数部分按 30 天/月换算为天数 */
|
||||
export function addIntervalMonthsYmd(dateStr: string, totalMonths: number): string {
|
||||
const compact = String(dateStr || '').replace(/-/g, '')
|
||||
if (compact.length !== 8 || !Number.isFinite(totalMonths) || totalMonths === 0) {
|
||||
return compact.length === 8 ? compact : ''
|
||||
}
|
||||
const wholeMonths = Math.trunc(totalMonths)
|
||||
const fracMonths = totalMonths - wholeMonths
|
||||
let result = compact
|
||||
if (wholeMonths !== 0) {
|
||||
result = addMonthsYmd(result, wholeMonths)
|
||||
}
|
||||
if (fracMonths !== 0) {
|
||||
const days = Math.round(fracMonths * DAYS_PER_MONTH)
|
||||
if (days !== 0) {
|
||||
result = addDaysYmd(result, days)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/** 分期应缴费时间:第 1 期=开始时间,第 2 期起在间隔递增基础上提前 10 天 */
|
||||
export function calcFqInstallmentDueDate(
|
||||
startDate: string,
|
||||
index: number,
|
||||
intervalMonths: number
|
||||
): string {
|
||||
const base = addMonthsYmd(startDate, index * intervalMonths)
|
||||
const base = addIntervalMonthsYmd(startDate, index * intervalMonths)
|
||||
if (index >= 1) {
|
||||
return addDaysYmd(base, -10)
|
||||
}
|
||||
|
||||
@@ -1,17 +1,92 @@
|
||||
/** 未设置头像时使用 `public/avatart.jpg`(根路径 `/avatart.jpg`) */
|
||||
export const DEFAULT_USER_AVATAR_URL = '/avatart.jpg'
|
||||
/** 未设置头像时使用 `public/avatart.jpg` */
|
||||
function joinPublicAsset(path: string): string {
|
||||
const base = import.meta.env.BASE_URL || '/'
|
||||
const prefix = base.endsWith('/') ? base : `${base}/`
|
||||
return `${prefix}${path.replace(/^\//, '')}`
|
||||
}
|
||||
|
||||
export const DEFAULT_USER_AVATAR_URL = joinPublicAsset('avatart.jpg')
|
||||
|
||||
/** 本地/部署环境由 .env 配置;docker 默认走 Nginx `/minio/zkxw` 反代 */
|
||||
const minioBaseUrl = (import.meta.env.VITE_MINIO_BASE_URL || '/minio/zkxw').replace(/\/$/, '')
|
||||
|
||||
/** @deprecated 各角色默认已统一为默认头像图,保留参数仅为兼容旧调用 */
|
||||
export function defaultAvatarPathByRole(_role: string | undefined): string {
|
||||
return DEFAULT_USER_AVATAR_URL
|
||||
}
|
||||
|
||||
/** 展示用头像:`avatarUrl` 非空则用其值,否则用默认图 */
|
||||
/**
|
||||
* 将库中头像值规范为存储相对路径(如 avatar/202606/04/xxx.jpeg)。
|
||||
* 兼容历史数据里写入的完整 URL(如 https://www.chengyantek.cn/zkxw/avatar/...)。
|
||||
*/
|
||||
export function normalizeAvatarStorageKey(raw: string | null | undefined): string {
|
||||
const u = raw != null ? String(raw).trim() : ''
|
||||
if (!u) return ''
|
||||
if (!/^https?:\/\//i.test(u) && !u.startsWith('/')) return u
|
||||
|
||||
const marker = '/avatar/'
|
||||
const lower = u.toLowerCase()
|
||||
const idx = lower.indexOf(marker)
|
||||
if (idx >= 0) {
|
||||
return `avatar/${u.slice(idx + marker.length)}`
|
||||
}
|
||||
|
||||
if (u.startsWith('/')) {
|
||||
const parts = u.split('/').filter(Boolean)
|
||||
const avatarIdx = parts.findIndex((p) => p === 'avatar')
|
||||
if (avatarIdx >= 0) return parts.slice(avatarIdx).join('/')
|
||||
}
|
||||
|
||||
return u
|
||||
}
|
||||
|
||||
/** 从用户信息对象读取原始头像字段(兼容 avatar / avatarUrl) */
|
||||
export function pickUserAvatarRaw(
|
||||
source: { avatarUrl?: string | null; avatar?: string | null } | null | undefined
|
||||
): string {
|
||||
if (!source) return ''
|
||||
const raw = source.avatarUrl ?? source.avatar
|
||||
return normalizeAvatarStorageKey(raw != null ? String(raw).trim() : '')
|
||||
}
|
||||
|
||||
/** 是否已设置自定义头像(非空即视为已设置) */
|
||||
export function hasCustomUserAvatar(avatarUrl: string | null | undefined): boolean {
|
||||
return Boolean(normalizeAvatarStorageKey(avatarUrl))
|
||||
}
|
||||
|
||||
/** 解析上传接口返回的图片地址 */
|
||||
export function pickUploadAvatarUrl(res: unknown): string {
|
||||
if (res == null) return ''
|
||||
if (typeof res === 'string') return normalizeAvatarStorageKey(res)
|
||||
const record = res as Record<string, unknown>
|
||||
const nested = record.data as Record<string, unknown> | undefined
|
||||
const raw =
|
||||
record.url ?? record.fileUrl ?? record.file_url ?? nested?.url ?? nested?.fileUrl
|
||||
return typeof raw === 'string' ? normalizeAvatarStorageKey(raw) : ''
|
||||
}
|
||||
|
||||
/** MinIO 相对路径或完整 URL → 浏览器可访问地址 */
|
||||
export function resolveStorageFileUrl(url: string | null | undefined): string {
|
||||
const key = normalizeAvatarStorageKey(url)
|
||||
if (!key) return ''
|
||||
if (/^https?:\/\//i.test(key)) return key
|
||||
if (key.startsWith('/')) return key
|
||||
return `${minioBaseUrl}/${key.replace(/^\//, '')}`
|
||||
}
|
||||
|
||||
/** 展示用头像:优先用户表头像,否则默认图 */
|
||||
export function resolveUserAvatarUrl(
|
||||
avatarUrl: string | null | undefined,
|
||||
role: string | undefined
|
||||
): string {
|
||||
const u = avatarUrl != null ? String(avatarUrl).trim() : ''
|
||||
if (u) return u
|
||||
const key = normalizeAvatarStorageKey(avatarUrl)
|
||||
if (key) return resolveStorageFileUrl(key)
|
||||
return defaultAvatarPathByRole(role)
|
||||
}
|
||||
|
||||
/** 从用户对象直接得到展示用头像 URL */
|
||||
export function resolveUserAvatarFromInfo(
|
||||
source: { avatarUrl?: string | null; avatar?: string | null; role?: string } | null | undefined
|
||||
): string {
|
||||
return resolveUserAvatarUrl(pickUserAvatarRaw(source), source?.role)
|
||||
}
|
||||
@@ -758,7 +758,7 @@
|
||||
step="any"
|
||||
:min="1"
|
||||
style="width: 100%"
|
||||
@change="tryGenerateInstallmentDetails"
|
||||
@change="handleFqParamsChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="每期间隔(月)">
|
||||
@@ -766,9 +766,9 @@
|
||||
v-model="formData.installmentIntervalMonths"
|
||||
type="number"
|
||||
step="any"
|
||||
:min="1"
|
||||
:min="0.1"
|
||||
style="width: 100%"
|
||||
@change="tryGenerateInstallmentDetails"
|
||||
@change="handleFqParamsChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="分期开始时间">
|
||||
@@ -780,7 +780,7 @@
|
||||
placeholder="选择开始时间"
|
||||
clearable
|
||||
style="width: 100%"
|
||||
@change="tryGenerateInstallmentDetails"
|
||||
@change="handleFqParamsChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</template>
|
||||
@@ -790,7 +790,11 @@
|
||||
<!-- 缴费明细 -->
|
||||
<div class="section-subtitle" style="margin-top: 20px">缴费明细</div>
|
||||
<div style="margin-bottom: 14px">
|
||||
<el-button type="primary" @click="addPaymentDetail">
|
||||
<el-button
|
||||
type="primary"
|
||||
:disabled="!canAddPaymentDetail(formData.payMode, formData.paymentDetails)"
|
||||
@click="addPaymentDetail"
|
||||
>
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加明细
|
||||
</el-button>
|
||||
@@ -834,6 +838,7 @@
|
||||
{{ paymentDetailSummary(detail) }}
|
||||
</span>
|
||||
<el-button
|
||||
v-if="!isPayDetailLocked(detail)"
|
||||
link
|
||||
type="danger"
|
||||
size="small"
|
||||
@@ -872,6 +877,7 @@
|
||||
<AmountInput
|
||||
v-model="detail.transferAmount"
|
||||
:min="0"
|
||||
:disabled="isPayDetailLocked(detail)"
|
||||
placeholder="请输入转账金额"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -882,6 +888,7 @@
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
placeholder="选择时间"
|
||||
clearable
|
||||
:disabled="isPayDetailLocked(detail)"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
@@ -889,6 +896,7 @@
|
||||
<el-select
|
||||
v-model="detail.payStatus"
|
||||
placeholder="状态"
|
||||
:disabled="isPayDetailLocked(detail)"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option label="待缴费" value="dfj" />
|
||||
@@ -906,12 +914,13 @@
|
||||
format="YYYY-MM-DD"
|
||||
placeholder="选择应缴费时间"
|
||||
clearable
|
||||
:disabled="isPayDetailLocked(detail)"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<!-- 每条明细的附件上传区 -->
|
||||
<div class="payment-detail-card__attachments">
|
||||
<div v-if="!isPayDetailLocked(detail)" class="payment-detail-card__attachments">
|
||||
<div class="attachment-upload">
|
||||
<div class="attachment-list">
|
||||
<el-upload
|
||||
@@ -1175,10 +1184,24 @@
|
||||
} from '@/api/admin'
|
||||
import { fetchEthnicList, type EthnicOption } from '@/api/ethnic'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
import { syncFqPaymentDetailRowCount } from '@/utils/protocol-payment-installment'
|
||||
import {
|
||||
calcFqInstallmentDueDate,
|
||||
syncFqPaymentDetailRowCount
|
||||
} from '@/utils/protocol-payment-installment'
|
||||
applyPayModeSwitch,
|
||||
canAddPaymentDetail,
|
||||
evaluatePayModeSwitch,
|
||||
isPayDetailLocked,
|
||||
markPayDetailLocks,
|
||||
sumPaidAmount,
|
||||
type PayMode
|
||||
} from '@/utils/protocol-pay-mode-switch'
|
||||
import {
|
||||
applyFqParamsChange,
|
||||
evaluateFqParamsChange,
|
||||
fqParamsSnapshot,
|
||||
generateInitialFqDetails,
|
||||
isSameFqParams,
|
||||
type FqParams
|
||||
} from '@/utils/protocol-fq-params-change'
|
||||
import AmountInput from '@/components/common/amount-input/index.vue'
|
||||
import { formatMoneyDisplay } from '@/utils/money-format'
|
||||
import {
|
||||
@@ -1199,6 +1222,16 @@
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
/** 上次确认生效的缴费模式(用于切换取消/拦截时回滚) */
|
||||
const lastConfirmedPayMode = ref<PayMode>('dj')
|
||||
|
||||
/** 上次确认生效的分期参数(用于编辑时修改期数/间隔/开始时间回滚) */
|
||||
const lastConfirmedFqParams = ref<FqParams>({
|
||||
installmentCount: null,
|
||||
installmentIntervalMonths: null,
|
||||
installmentStartDate: ''
|
||||
})
|
||||
|
||||
const customerId = ref<string | null>(null)
|
||||
const customerOptions = ref<
|
||||
Array<{ id: string; customerName: string; phoneNo: string; idCardNo: string }>
|
||||
@@ -1544,6 +1577,12 @@
|
||||
batchTransportVisible.value = false
|
||||
Object.assign(batchTransport, createEmptyTransport())
|
||||
activeFormTab.value = 'basic'
|
||||
lastConfirmedPayMode.value = 'dj'
|
||||
lastConfirmedFqParams.value = {
|
||||
installmentCount: null,
|
||||
installmentIntervalMonths: null,
|
||||
installmentStartDate: ''
|
||||
}
|
||||
}
|
||||
|
||||
function scrollToSection(key: string) {
|
||||
@@ -1627,6 +1666,7 @@
|
||||
}
|
||||
|
||||
function addPaymentDetail() {
|
||||
if (!canAddPaymentDetail(formData.payMode, formData.paymentDetails)) return
|
||||
const now = new Date()
|
||||
const pad = (n: number) => String(n).padStart(2, '0')
|
||||
const defaultTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
||||
@@ -1702,77 +1742,180 @@
|
||||
return Number.isFinite(n) ? Math.trunc(n) : undefined
|
||||
}
|
||||
|
||||
function toFloatOrUndefined(val: unknown): number | undefined {
|
||||
if (val == null || val === '') return undefined
|
||||
const n = Number(val)
|
||||
return Number.isFinite(n) ? n : undefined
|
||||
}
|
||||
|
||||
function fqPaymentContext() {
|
||||
return {
|
||||
payMode: formData.payMode,
|
||||
installmentCount: toIntOrUndefined(formData.installmentCount) ?? null,
|
||||
contractAmount: formData.contractAmount,
|
||||
installmentStartDate: formData.installmentStartDate,
|
||||
installmentIntervalMonths: toIntOrUndefined(formData.installmentIntervalMonths) ?? null
|
||||
installmentIntervalMonths: toFloatOrUndefined(formData.installmentIntervalMonths) ?? null
|
||||
}
|
||||
}
|
||||
|
||||
/** 分期模式:三个参数都填好后生成/补齐缴费明细行(已有明细时仅补齐期次,不整表覆盖) */
|
||||
function tryGenerateInstallmentDetails() {
|
||||
if (formData.payMode !== 'fq') return
|
||||
const count = formData.installmentCount
|
||||
const interval = formData.installmentIntervalMonths
|
||||
const startDate = formData.installmentStartDate
|
||||
if (!count || !interval || !startDate) return
|
||||
function payModeSwitchContext() {
|
||||
return {
|
||||
contractAmount: formData.contractAmount,
|
||||
lumpSumDeadline: formData.lumpSumDeadline,
|
||||
installmentCount: toIntOrUndefined(formData.installmentCount) ?? null,
|
||||
installmentIntervalMonths: toFloatOrUndefined(formData.installmentIntervalMonths) ?? null,
|
||||
installmentStartDate: formData.installmentStartDate
|
||||
}
|
||||
}
|
||||
|
||||
if (formData.paymentDetails.length) {
|
||||
syncFqPaymentDetailRowCount(fqPaymentContext(), formData.paymentDetails)
|
||||
syncPaymentDueAmounts()
|
||||
formData.paymentDetails.forEach((d, i) => {
|
||||
d.installmentNo = i + 1
|
||||
d.installmentDueDate = calcFqInstallmentDueDate(startDate, i, interval)
|
||||
})
|
||||
function getFqParamsFromForm(): FqParams {
|
||||
return {
|
||||
installmentCount: toIntOrUndefined(formData.installmentCount) ?? null,
|
||||
installmentIntervalMonths: toFloatOrUndefined(formData.installmentIntervalMonths) ?? null,
|
||||
installmentStartDate: formData.installmentStartDate || ''
|
||||
}
|
||||
}
|
||||
|
||||
function restoreFqParams(params: FqParams) {
|
||||
formData.installmentCount = params.installmentCount
|
||||
formData.installmentIntervalMonths = params.installmentIntervalMonths
|
||||
formData.installmentStartDate = params.installmentStartDate || ''
|
||||
}
|
||||
|
||||
function syncLastConfirmedFqParams() {
|
||||
lastConfirmedFqParams.value = fqParamsSnapshot(getFqParamsFromForm())
|
||||
}
|
||||
|
||||
/**
|
||||
* 分期参数变更(期数 / 间隔 / 开始时间):校验 → 确认 → 重建未缴期次
|
||||
* 与缴费模式切换独立;保留 yjf 已缴行,作废原 dfj 后按剩余金额重建。
|
||||
*/
|
||||
async function handleFqParamsChange() {
|
||||
if (formData.payMode !== 'fq') return
|
||||
|
||||
const newParams = getFqParamsFromForm()
|
||||
const oldParams = lastConfirmedFqParams.value
|
||||
|
||||
if (isSameFqParams(oldParams, newParams)) return
|
||||
|
||||
if (
|
||||
!newParams.installmentCount ||
|
||||
!newParams.installmentIntervalMonths ||
|
||||
!newParams.installmentStartDate
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
const dueAmounts = calcInstallmentDueAmounts(formData.contractAmount, count)
|
||||
const details = []
|
||||
for (let i = 0; i < count; i++) {
|
||||
details.push({
|
||||
transferType: '',
|
||||
dueAmount: dueAmounts[i] ?? null,
|
||||
transferAmount: null,
|
||||
transferTime: '',
|
||||
payStatus: 'dfj',
|
||||
installmentNo: i + 1,
|
||||
installmentDueDate: calcFqInstallmentDueDate(startDate, i, interval),
|
||||
attachments: [] as Array<{
|
||||
id?: string
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileSize: number
|
||||
fileSizeDisplay?: string
|
||||
fileType?: string
|
||||
_uploading?: boolean
|
||||
}>
|
||||
})
|
||||
if (formData.paymentDetails.length === 0) {
|
||||
formData.paymentDetails = generateInitialFqDetails(newParams, formData.contractAmount)
|
||||
initPaymentDetailExpandFlags(formData.paymentDetails)
|
||||
markPayDetailLocks(formData.paymentDetails)
|
||||
syncLastConfirmedFqParams()
|
||||
return
|
||||
}
|
||||
initPaymentDetailExpandFlags(details)
|
||||
formData.paymentDetails = details
|
||||
|
||||
const evaluation = evaluateFqParamsChange(
|
||||
oldParams,
|
||||
newParams,
|
||||
formData.paymentDetails,
|
||||
formData.contractAmount
|
||||
)
|
||||
|
||||
if (evaluation.action === 'noop') {
|
||||
syncLastConfirmedFqParams()
|
||||
return
|
||||
}
|
||||
|
||||
if (evaluation.action === 'blocked') {
|
||||
restoreFqParams(oldParams)
|
||||
await ElMessageBox.alert(evaluation.reason, '无法修改分期参数', { type: 'warning' })
|
||||
return
|
||||
}
|
||||
|
||||
if (evaluation.action === 'confirm') {
|
||||
try {
|
||||
await ElMessageBox.confirm(evaluation.summary, '修改分期参数', {
|
||||
confirmButtonText: '确认修改',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
restoreFqParams(oldParams)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
formData.paymentDetails = applyFqParamsChange(
|
||||
newParams,
|
||||
formData.paymentDetails,
|
||||
formData.contractAmount
|
||||
)
|
||||
initPaymentDetailExpandFlags(formData.paymentDetails)
|
||||
markPayDetailLocks(formData.paymentDetails)
|
||||
syncLastConfirmedFqParams()
|
||||
}
|
||||
|
||||
/** 缴费模式切换回调 */
|
||||
function onPayModeChange(val: string) {
|
||||
if (val === 'fq') {
|
||||
applyFqPaymentDefaults({ resetCountInterval: true })
|
||||
tryGenerateInstallmentDetails()
|
||||
} else {
|
||||
// 趸交模式:将趸交截止时间同步到所有明细的应缴费时间
|
||||
syncPaymentDueAmounts()
|
||||
/** 缴费模式切换:校验 → 确认 → 变换明细 */
|
||||
async function onPayModeChange(val: string) {
|
||||
const toMode = val as PayMode
|
||||
const fromMode = lastConfirmedPayMode.value
|
||||
if (toMode === fromMode) return
|
||||
|
||||
const evaluation = evaluatePayModeSwitch(
|
||||
fromMode,
|
||||
toMode,
|
||||
formData.paymentDetails,
|
||||
payModeSwitchContext()
|
||||
)
|
||||
|
||||
if (evaluation.action === 'blocked') {
|
||||
formData.payMode = fromMode
|
||||
await ElMessageBox.alert(evaluation.reason, '无法切换缴费模式', { type: 'warning' })
|
||||
return
|
||||
}
|
||||
|
||||
if (evaluation.action === 'confirm') {
|
||||
try {
|
||||
await ElMessageBox.confirm(evaluation.summary, '切换缴费模式', {
|
||||
confirmButtonText: '确认切换',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
})
|
||||
} catch {
|
||||
formData.payMode = fromMode
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (toMode === 'fq') {
|
||||
applyFqPaymentDefaults({ resetCountInterval: false })
|
||||
}
|
||||
|
||||
formData.paymentDetails = applyPayModeSwitch(
|
||||
fromMode,
|
||||
toMode,
|
||||
formData.paymentDetails,
|
||||
payModeSwitchContext()
|
||||
)
|
||||
initPaymentDetailExpandFlags(formData.paymentDetails)
|
||||
markPayDetailLocks(formData.paymentDetails)
|
||||
|
||||
if (toMode === 'dj') {
|
||||
syncLumpSumDueDate()
|
||||
}
|
||||
|
||||
lastConfirmedPayMode.value = toMode
|
||||
if (toMode === 'fq') {
|
||||
syncLastConfirmedFqParams()
|
||||
}
|
||||
}
|
||||
|
||||
/** 趸交模式:将趸交截止时间同步到所有缴费明细的应缴费时间 */
|
||||
/** 趸交模式:将趸交截止时间同步到待缴明细的应缴费时间 */
|
||||
function syncLumpSumDueDate() {
|
||||
if (formData.payMode !== 'dj') return
|
||||
const deadline = formData.lumpSumDeadline || ''
|
||||
formData.paymentDetails.forEach((d) => {
|
||||
if (isPayDetailLocked(d)) return
|
||||
d.installmentDueDate = deadline
|
||||
})
|
||||
}
|
||||
@@ -1885,6 +2028,7 @@
|
||||
formData.installmentStartDate = String(pay.installmentStartDate || '')
|
||||
if (formData.payMode === 'fq') {
|
||||
applyFqPaymentDefaults()
|
||||
syncLastConfirmedFqParams()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1896,8 +2040,10 @@
|
||||
}))
|
||||
initPaymentDetailExpandFlags(details)
|
||||
formData.paymentDetails = details
|
||||
markPayDetailLocks(formData.paymentDetails)
|
||||
}
|
||||
syncFqPaymentDetailRowCount(fqPaymentContext(), formData.paymentDetails)
|
||||
lastConfirmedPayMode.value = (formData.payMode === 'fq' ? 'fq' : 'dj') as PayMode
|
||||
|
||||
const pa =
|
||||
(row as any).protocolAttachments || (bundle.protocol as any)?.protocolAttachments || ''
|
||||
@@ -2057,11 +2203,13 @@
|
||||
contractAmount: formData.contractAmount ?? undefined,
|
||||
lumpSumDeadline: formData.lumpSumDeadline || undefined,
|
||||
installmentCount: toIntOrUndefined(formData.installmentCount),
|
||||
installmentIntervalMonths: toIntOrUndefined(formData.installmentIntervalMonths),
|
||||
installmentIntervalMonths: toFloatOrUndefined(formData.installmentIntervalMonths),
|
||||
installmentStartDate: formData.installmentStartDate || undefined
|
||||
},
|
||||
paymentDetails: formData.paymentDetails.map(({ _expanded, ...d }) => ({
|
||||
transferType: d.transferType,
|
||||
paymentDetails: formData.paymentDetails.map(
|
||||
({ _expanded, _payModeLocked, _voided, ...d }) => ({
|
||||
id: d.id,
|
||||
transferType: d.transferType,
|
||||
dueAmount: d.dueAmount,
|
||||
transferAmount: d.transferAmount,
|
||||
transferTime: d.transferTime,
|
||||
@@ -2087,7 +2235,7 @@
|
||||
fileSizeDisplay: a.fileSizeDisplay,
|
||||
fileType: a.fileType
|
||||
}))
|
||||
}))
|
||||
}))
|
||||
}
|
||||
|
||||
if (isEdit.value && editingId.value) {
|
||||
@@ -2527,21 +2675,29 @@
|
||||
return amounts
|
||||
}
|
||||
|
||||
/** 按缴费模式同步各明细应缴费金额 */
|
||||
/** 按缴费模式同步各明细应缴费金额(跳过已锁定明细) */
|
||||
function syncPaymentDueAmounts() {
|
||||
const contract = formData.contractAmount
|
||||
if (contract == null) return
|
||||
if (formData.payMode === 'dj') {
|
||||
formData.paymentDetails.forEach((d) => {
|
||||
d.dueAmount = contract
|
||||
const paidSum = sumPaidAmount(formData.paymentDetails)
|
||||
const remaining = Math.round((Number(contract) - paidSum) * 100) / 100
|
||||
const dfjRows = formData.paymentDetails.filter(
|
||||
(d) => !isPayDetailLocked(d) && String(d.payStatus || 'dfj') === 'dfj'
|
||||
)
|
||||
const targetAmount = paidSum > 0 ? remaining : contract
|
||||
dfjRows.forEach((d, i) => {
|
||||
if (i === 0) d.dueAmount = targetAmount
|
||||
})
|
||||
return
|
||||
}
|
||||
if (formData.payMode === 'fq') {
|
||||
if (formData.paymentDetails.some((d) => isPayDetailLocked(d))) return
|
||||
const count = formData.installmentCount || formData.paymentDetails.length
|
||||
if (!count) return
|
||||
const amounts = calcInstallmentDueAmounts(Number(contract), count)
|
||||
const amounts = calcInstallmentDueAmounts(Number(contract), Number(count))
|
||||
formData.paymentDetails.forEach((d, i) => {
|
||||
if (isPayDetailLocked(d)) return
|
||||
if (amounts[i] !== undefined) d.dueAmount = amounts[i]
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user