This commit is contained in:
zlwu committed 2026-07-12 18:23:02 +08:00
1 parent 2142b33cfa
commit 3520f9ce90
27 files changed
+248507 -251995

No files matched your search

+1 -1
View File
@@ -1 +1 @@
27076
38943
+34 -1
View File
@@ -23,7 +23,7 @@ from app.core.auth import (
from app.core.response import success_response, error_response
from app.core.config import settings
from app.models.models import SysUser
from app.crud.user import user_crud
from app.crud.user import user_crud, change_password
from app.core.utils import generate_uuid
from app.core import login_crypto
from app.services.web_auth_roles import (
@@ -300,6 +300,39 @@ def get_web_auth_menu_codes(request: Request, db: Session = Depends(get_db)):
return error_response(401, "Token无效或已过期")
@router.post("/web/auth/change-password", response_model=dict)
def change_current_user_password(
request: Request,
body: dict,
db: Session = Depends(get_db),
):
"""当前用户修改密码。"""
authorization = request.headers.get("Authorization", "")
if not authorization.startswith("Bearer "):
return error_response(401, "未授权")
token = authorization.replace("Bearer ", "")
try:
current_user = get_current_user_by_token(token=token, db=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))
@router.get("/public/crm/quote/share/{share_code}")
def public_quote_share(
share_code: str,
+20
View File
@@ -426,6 +426,26 @@ def soft_delete_user(db: Session, user_id: str, *, user_info: dict = None) -> No
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位")
if old_password == new_pw:
raise ValueError("新密码不能与原密码相同")
obj.password = _hash_password(new_pw)
obj.update_time = datetime.now()
db.add(obj)
db.commit()
def reset_password(db: Session, user_id: str, new_password: str) -> None:
obj = get_user(db, user_id)
if not obj:
+10 -1
View File
@@ -157,5 +157,14 @@
"155": "Community 155",
"156": "Community 156",
"157": "Community 157",
"162": "Community 162"
"158": "Community 158",
"159": "Community 159",
"160": "Community 160",
"161": "Community 161",
"162": "Community 162",
"163": "Community 163",
"164": "Community 164",
"165": "Community 165",
"166": "Community 166",
"167": "Community 167"
}
+310 -409
View File
@@ -1,16 +1,16 @@
# Graph Report - backend (2026-07-12)
## Corpus Check
- 248 files · ~173,666 words
- 248 files · ~172,565 words
- Verdict: corpus is large enough that graph structure adds value.
## Summary
- 5502 nodes · 38811 edges · 159 communities (157 shown, 2 thin omitted)
- Extraction: 51% EXTRACTED · 49% INFERRED · 0% AMBIGUOUS · INFERRED: 18852 edges (avg confidence: 0.5)
- 5520 nodes · 39168 edges · 140 communities (137 shown, 3 thin omitted)
- Extraction: 51% EXTRACTED · 49% INFERRED · 0% AMBIGUOUS · INFERRED: 19039 edges (avg confidence: 0.5)
- Token cost: 0 input · 0 output
## Graph Freshness
- Built from commit: `c2cba3e6`
- Built from commit: `2142b33c`
- Run `git rev-parse HEAD` and compare to check if the graph is stale.
- Run `graphify update .` after code changes (no API cost).
@@ -143,329 +143,310 @@
- [[_COMMUNITY_Community 125|Community 125]]
- [[_COMMUNITY_Community 126|Community 126]]
- [[_COMMUNITY_Community 127|Community 127]]
- [[_COMMUNITY_Community 128|Community 128]]
- [[_COMMUNITY_Community 129|Community 129]]
- [[_COMMUNITY_Community 130|Community 130]]
- [[_COMMUNITY_Community 131|Community 131]]
- [[_COMMUNITY_Community 132|Community 132]]
- [[_COMMUNITY_Community 134|Community 134]]
- [[_COMMUNITY_Community 135|Community 135]]
- [[_COMMUNITY_Community 136|Community 136]]
- [[_COMMUNITY_Community 137|Community 137]]
- [[_COMMUNITY_Community 138|Community 138]]
- [[_COMMUNITY_Community 148|Community 148]]
- [[_COMMUNITY_Community 149|Community 149]]
- [[_COMMUNITY_Community 150|Community 150]]
- [[_COMMUNITY_Community 151|Community 151]]
- [[_COMMUNITY_Community 152|Community 152]]
- [[_COMMUNITY_Community 153|Community 153]]
- [[_COMMUNITY_Community 154|Community 154]]
- [[_COMMUNITY_Community 155|Community 155]]
- [[_COMMUNITY_Community 156|Community 156]]
- [[_COMMUNITY_Community 157|Community 157]]
- [[_COMMUNITY_Community 162|Community 162]]
## God Nodes (most connected - your core abstractions)
1. `Session` - 1521 edges
2. `int` - 460 edges
3. `BaseModel` - 433 edges
4. `bool` - 370 edges
5. `Any` - 364 edges
6. `get_tenant_no()` - 347 edges
7. `DbUserContext` - 317 edges
8. `DbUserContext` - 316 edges
9. `SysUser` - 306 edges
10. `success_response()` - 259 edges
1. `str` - 1679 edges
2. `Session` - 1551 edges
3. `int` - 475 edges
4. `BaseModel` - 433 edges
5. `bool` - 379 edges
6. `Any` - 364 edges
7. `get_tenant_no()` - 347 edges
8. `DbUserContext` - 322 edges
9. `DbUserContext` - 321 edges
10. `SysUser` - 306 edges
## Surprising Connections (you probably didn't know these)
- `bool` --uses--> `DbUserContext` [INFERRED]
scripts/migrate_dibang_data.py → app/core/db_auth.py
- `date` --uses--> `DbUserContext` [INFERRED]
scripts/migrate_dibang_data.py → app/core/db_auth.py
- `int` --uses--> `DbUserContext` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/core/db_auth.py
- `int` --uses--> `ApiRequestLogMiddleware` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/core/api_request_log_middleware.py
- `Any` --uses--> `OperLogMeta` [INFERRED]
scripts/migrate_dibang_data.py → app/core/oper_log_context.py
- `int` --uses--> `ApiCryptoMiddleware` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/core/api_crypto_middleware.py
- `int` --uses--> `OperLogMeta` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/core/oper_log_context.py
- `int` --uses--> `SysApiRequestLog` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/models/models.py
- `int` --uses--> `BxReimburseApply` [INFERRED]
scripts/run_db_auto_generate_plans.py → app/models/bx_models.py
## Communities (159 total, 2 thin omitted)
## Communities (140 total, 3 thin omitted)
### Community 0 - "Community 0"
Cohesion: 0.12
Nodes (102): date, DbUserContext, int, Session, str, VehicleMaintenanceApplyCreate, VehicleMaintenanceApplyRead, VehicleMaintenanceApplyReminder (+94 more)
Cohesion: 0.35
Nodes (220): Any, bool, str, UploadFile, CRM 线索管理 Pydantic Schemas, CRM 客户管理 Pydantic Schemas, CRM 商机管理 Pydantic Schemas, CRM 客户公海池规则 Pydantic Schemas (+212 more)
### Community 1 - "Community 1"
Cohesion: 0.35
Nodes (219): Any, bool, str, UploadFile, CRM 线索管理 Pydantic Schemas, CRM 客户管理 Pydantic Schemas, CRM 商机管理 Pydantic Schemas, CRM 客户公海池规则 Pydantic Schemas (+211 more)
Cohesion: 0.03
Nodes (190): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, MenuCreateBody (+182 more)
### Community 2 - "Community 2"
Cohesion: 0.08
Nodes (54): CrmContract, CrmContractProductPriceTier, date, datetime, Decimal, Query, _apply_contract_entity_fields(), _apply_contract_scalar_fields() (+46 more)
Cohesion: 0.06
Nodes (167): _apply_default_invoice_info_to_customers(), category_add(), category_delete(), category_tree(), category_update(), clue_assign(), clue_check_convert(), clue_check_duplicate() (+159 more)
### Community 3 - "Community 3"
Cohesion: 0.06
Nodes (53): str, CRM 合同 Pydantic Schemas — 对照 CrmContractBo / CrmContractVo, ContractApprovalActionBody, ContractApprovalApproveBody, ContractApprovalByContractBody, ContractApprovalExportBody, ContractApprovalListBody, ContractApprovalListQuery (+45 more)
Cohesion: 0.05
Nodes (152): register_contract_routes(), Any, bool, CRM 合同 CRUD — 对照 CrmContractServiceImpl.java(列表/详情 P1), CrmContract, CrmContractProductPriceTier, date, datetime (+144 more)
### Community 4 - "Community 4"
Cohesion: 0.05
Nodes (109): DbUserContext, int, 运输计划管理 - 基础数据 API(承运商、车辆、人员), PlVehicle, Session, str, VehicleRead, date (+101 more)
Cohesion: 0.03
Nodes (150): register_quote_routes(), Any, bool, CRM 报价单 CRUD — 对照 CrmQuoteServiceImpl.java(P2 全量), datetime, Decimal, int, Session (+142 more)
### Community 5 - "Community 5"
Cohesion: 0.16
Nodes (44): register_quote_routes(), bool, CRM 报价单 CRUD — 对照 CrmQuoteServiceImpl.java(P2 全量), Session, str, accept_quote(), create_quote(), _enrich_contact_fields() (+36 more)
Cohesion: 0.06
Nodes (140): bool, CertRead, DbUserContext, int, 运输计划管理 - 基础数据 API(承运商、车辆、人员), PlCarrier, PlVehicle, Session (+132 more)
### Community 6 - "Community 6"
Cohesion: 0.16
Nodes (12): Decimal, str, VehicleRechargeApplyCreate, VehicleRechargeApplyListResponse, VehicleRechargeApplyOption, VehicleRechargeApplyRead, VehicleRechargeApplyUpdate, VehicleRechargeDisburseBoardListResponse (+4 more)
Cohesion: 0.05
Nodes (133): bool, Decimal, int, PlanCreateFull, PlanDriverFeedbackUpdateBody, PlanSiteFeedbackUpdateBody, PlPlan, PlPlanProduct (+125 more)
### Community 7 - "Community 7"
Cohesion: 0.06
Nodes (163): bool, PlCarrier, VehicleCreate, VehicleUpdate, bool, DbUserContext, float, int (+155 more)
Cohesion: 0.04
Nodes (127): bool, DbInboundOutbound, int, PublicInventoryFeedback, PublicInventoryPageRead, Session, str, UploadFile (+119 more)
### Community 8 - "Community 8"
Cohesion: 0.04
Nodes (117): Any, bool, CRM 产品模块 CRUD(产品分类 + 产品 + 附件), int, Session, str, SysOss, int (+109 more)
Cohesion: 0.06
Nodes (124): DbUserContext, FreightSettlementDisburseBody, FreightSettlementSubmitApprovalBody, FreightSettlementUpdate, int, Session, str, bool (+116 more)
### Community 9 - "Community 9"
Cohesion: 0.04
Nodes (107): Any, bool, CertRow, Session, str, VehiclePersonnelRow, CertRead, CertRow (+99 more)
Cohesion: 0.08
Nodes (101): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+93 more)
### Community 10 - "Community 10"
Cohesion: 0.03
Nodes (137): Decimal, PlPlanProduct, Session, str, Decimal, PlPlanChange, 计划变更记录表 pl_plan_change, 计划产品明细表 pl_plan_product (+129 more)
Cohesion: 0.09
Nodes (115): date, DbUserContext, int, Session, str, VehicleRechargeApplyCreate, VehicleRechargeApplyRead, VehicleRechargeApplyUpdate (+107 more)
### Community 11 - "Community 11"
Cohesion: 0.11
Nodes (101): date, DbUserContext, int, Session, str, VehicleUreaApplyCreate, VehicleUreaApplyRead, VehicleUreaApplyUpdate (+93 more)
Cohesion: 0.09
Nodes (112): bool, DbUserContext, float, int, PlPlan, PlTransport, Session, str (+104 more)
### Community 12 - "Community 12"
Cohesion: 0.05
Nodes (227): attachment_preview_url(), create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post(), create_role_management(), create_site() (+219 more)
Cohesion: 0.1
Nodes (103): date, DbUserContext, int, Session, str, VehicleUreaApplyCreate, VehicleUreaApplyRead, VehicleUreaApplyUpdate (+95 more)
### Community 13 - "Community 13"
Cohesion: 0.04
Nodes (46): get_plan_arrange_info(), patch_plan_product_certs(), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输) (+38 more)
Cohesion: 0.11
Nodes (104): date, DbUserContext, int, Session, str, VehicleMaintenanceApplyCreate, VehicleMaintenanceApplyRead, VehicleMaintenanceApplyReminder (+96 more)
### Community 14 - "Community 14"
Cohesion: 0.06
Nodes (60): Any, bool, bytes, int, str, Exception, bool, bytes (+52 more)
Nodes (94): str, Any, Decimal, Session, str, 解析列表查询参数,供 API 与 CRUD 共用。, _add_user_info_kwarg(), patch_file() (+86 more)
### Community 15 - "Community 15"
Cohesion: 0.10
Nodes (132): date, DbUserContext, int, PlanCreateFull, PlanDriverFeedbackUpdateBody, PlanSiteFeedbackUpdateBody, PlPlan, Session (+124 more)
Cohesion: 0.09
Nodes (78): Any, bool, date, int, Session, str, Any, int (+70 more)
### Community 16 - "Community 16"
Cohesion: 0.02
Nodes (104): 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list (+96 more)
Cohesion: 0.05
Nodes (69): 运输计划管理 - 基础数据 Schema(承运商、车辆、人员、证书), Decimal, str, CarrierAuditReject, CarrierBase, CarrierCreate, CarrierListResponse, CarrierQualificationBase (+61 more)
### Community 17 - "Community 17"
Cohesion: 0.08
Nodes (70): CRM 合同子模块路由 — 变更/模板/审批独立页, register_contract_sub_routes(), Any, bool, CrmContract, datetime, int, Query (+62 more)
Cohesion: 0.06
Nodes (66): Any, bool, bytes, int, Request, str, Any, int (+58 more)
### Community 18 - "Community 18"
Cohesion: 0.16
Nodes (36): Any, bool, BxUserContext, BxWorkflowNode, float, int, ReimburseApplyOut, Session (+28 more)
Cohesion: 0.09
Nodes (74): attachment_download_url(), attachment_preview_url(), create_dept(), create_dict_data(), create_dict_type(), create_menu(), create_post(), create_role_management() (+66 more)
### Community 19 - "Community 19"
Cohesion: 0.06
Nodes (31): 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo (+23 more)
Cohesion: 0.15
Nodes (37): Any, bool, BxUserContext, BxWorkflowNode, float, int, ReimburseApplyOut, Session (+29 more)
### Community 20 - "Community 20"
Cohesion: 0.07
Nodes (41): AttachmentUploadResponse, ChangePasswordRequest, Config, LoginRequest, LoginResponse, Pydantic schemas - 用户认证, ResetPasswordRequest, UserCreate (+33 more)
Cohesion: 0.03
Nodes (69): PlDocumentReminder, PlInventoryTransaction, PlInventoryWarning, 计划-运输关联表 pl_plan_transport, 运费结算表 pl_freight_settlement, 库存流水表 pl_inventory_transaction, 结算单-运输关联表 pl_freight_settlement_transport, 结算单-运输关联表 pl_freight_settlement_transport (+61 more)
### Community 21 - "Community 21"
Cohesion: 0.11
Nodes (58): Any, bool, int, Session, str, Any, bool, CRM 线索 CRUD(线索主表 + 转化/分配/无效/等级操作) (+50 more)
Cohesion: 0.25
Nodes (68): date, DbUserContext, int, PlanCreateFull, PlanDriverFeedbackUpdateBody, PlanSiteFeedbackUpdateBody, PlPlan, Session (+60 more)
### Community 22 - "Community 22"
Cohesion: 0.09
Nodes (75): bool, DbInboundOutbound, int, PublicInventoryFeedback, PublicInventoryPageRead, Session, str, UploadFile (+67 more)
Cohesion: 0.3
Nodes (63): date, DbUserContext, int, Session, str, DocumentReminderRead, DocumentReminderUpdate, InventoryLedgerResponse (+55 more)
### Community 23 - "Community 23"
Cohesion: 0.11
Nodes (108): date, DbUserContext, int, Session, str, VehicleRechargeApplyCreate, VehicleRechargeApplyRead, VehicleRechargeApplyUpdate (+100 more)
Cohesion: 0.09
Nodes (58): Any, bool, CrmContract, datetime, int, Query, Session, str (+50 more)
### Community 24 - "Community 24"
Cohesion: 0.25
Nodes (18): BxUserContext, Session, str, bool, BxUserContext, Session, str, create_expense_item() (+10 more)
Cohesion: 0.11
Nodes (57): Any, bool, int, Session, str, Any, bool, CRM 线索 CRUD(线索主表 + 转化/分配/无效/等级操作) (+49 more)
### Community 25 - "Community 25"
Cohesion: 0.11
Nodes (35): Any, bool, BxUserContext, BxWorkflowNode, float, int, Session, str (+27 more)
Cohesion: 0.09
Nodes (55): bool, Session, str, Any, bool, int, Session, str (+47 more)
### Community 26 - "Community 26"
Cohesion: 0.18
Nodes (49): Any, CRM 商机 CRUD(主表 + 阶段/赢输单/统计/看板/漏斗), CrmOpportunity, date, datetime, Decimal, int, Session (+41 more)
Cohesion: 0.1
Nodes (55): bool, date, DbPurchasePlan, float, PlPlan, PlPlanProduct, PlTransport, Session (+47 more)
### Community 27 - "Community 27"
Cohesion: 0.10
Nodes (58): bool, date, datetime, DbInboundOutbound, DbPurchasePlan, float, PlPlan, PlPlanProduct (+50 more)
Cohesion: 0.09
Nodes (21): Exception, bool, bytes, int, str, bytes, BytesIO, BaseStorage (+13 more)
### Community 28 - "Community 28"
Cohesion: 0.12
Nodes (32): bool, Session, str, _append_user_scope_conditions(), apply_data_scope(), assert_row_in_data_scope(), _collect_scope_ids(), _get_child_dept_ids() (+24 more)
Cohesion: 0.04
Nodes (51): invoice_info_list(), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 供方全量列表(下拉)— Java: CrmSupplierInfoController.listAll, 供方全量列表(下拉)— Java: CrmSupplierInfoController.listAll (+43 more)
### Community 29 - "Community 29"
Cohesion: 0.08
Nodes (85): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, register_contract_routes(), bool, CRM 合同 CRUD — 对照 CrmContractServiceImpl.java(列表/详情 P1), Session, str, batch_assign_owner(), batch_submit_approval() (+77 more)
Nodes (47): CRM 合同 API 路由 — GET/PUT/DELETE/POST 对齐原 Java CRM, CRM 合同子模块路由 — 变更/模板/审批独立页, register_contract_sub_routes(), CRM 合同 Pydantic Schemas — 对照 CrmContractBo / CrmContractVo, ContractApprovalActionBody, ContractApprovalApproveBody, ContractApprovalByContractBody, ContractApprovalExportBody (+39 more)
### Community 30 - "Community 30"
Cohesion: 0.36
Nodes (31): AdvanceApplyCreate, AdvanceApplyOut, AdvanceApplyUpdate, AdvanceApprovalCreate, BxUserContext, int, Session, str (+23 more)
Cohesion: 0.18
Nodes (49): Any, CRM 商机 CRUD(主表 + 阶段/赢输单/统计/看板/漏斗), CrmOpportunity, date, datetime, Decimal, int, Session (+41 more)
### Community 31 - "Community 31"
Cohesion: 0.13
Nodes (43): 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/shanxia2.0.sql 基线), refresh_token(), bool, Redis, Request, str, _T, bool (+35 more)
Cohesion: 0.04
Nodes (50): create_plan_full(), _generate_plan_no(), 创建运输计划(完整表单:合同产品 + 可选运输安排), 创建运输计划(完整表单:合同产品 + 可选运输安排), 创建运输计划(完整表单:合同产品 + 可选运输安排), 创建运输计划(完整表单:合同产品 + 可选预选车辆,不自动安排运输), 创建运输计划(完整表单:合同产品 + 可选预选车辆,不自动安排运输), 创建运输计划(完整表单:合同产品 + 可选预选车辆,不自动安排运输) (+42 more)
### Community 32 - "Community 32"
Cohesion: 0.07
Nodes (123): DbUserContext, FreightSettlementDisburseBody, FreightSettlementSubmitApprovalBody, FreightSettlementUpdate, int, Session, str, bool (+115 more)
Cohesion: 0.11
Nodes (45): bool, str, Any, bool, int, Session, str, SysUser (+37 more)
### Community 33 - "Community 33"
Cohesion: 0.15
Nodes (30): Any, bool, int, Session, str, approve_quote(), can_user_approve(), create_approval_records() (+22 more)
Cohesion: 0.12
Nodes (42): Any, Any, str, Session, str, Any, bool, CrmOpportunity (+34 more)
### Community 34 - "Community 34"
Cohesion: 0.04
Nodes (48): PlInventoryTransaction, PlInventoryWarning, 计划-运输关联表 pl_plan_transport, 运费结算表 pl_freight_settlement, 库存流水表 pl_inventory_transaction, 运费结算表 pl_freight_settlement, 结算单-运输关联表 pl_freight_settlement_transport, 结算单-运输关联表 pl_freight_settlement_transport (+40 more)
Cohesion: 0.07
Nodes (39): datetime, int, str, datetime, int, Session, str, date (+31 more)
### Community 35 - "Community 35"
Cohesion: 0.17
Nodes (39): DbPurchasePlan, DbUserContext, Session, str, InboundOutboundRead, _apply_plan_product_update(), _apply_plan_update(), _base_query() (+31 more)
Cohesion: 0.07
Nodes (42): _db_pool_keepalive_loop(), _error_json(), lifespan(), _mask_secret(), Exception, int, Request, str (+34 more)
### Community 36 - "Community 36"
Cohesion: 0.40
Nodes (5): bool, str, get_password_hash(), 验证密码(哈希非 bcrypt 或损坏时返回 False,避免抛错), verify_password()
Cohesion: 0.12
Nodes (42): pool_rule_delete(), pool_rule_update(), Any, bool, CRM 公海池规则 CRUD + 规则执行逻辑, int, Session, str (+34 more)
### Community 37 - "Community 37"
Cohesion: 0.13
Nodes (40): Any, bool, date, int, Session, str, Session, str (+32 more)
Cohesion: 0.28
Nodes (44): InboundOutboundRead, bool, DbPurchasePlan, PurchasePlanRead, PurchasePlanWithFillLink, WeighingSlipRead, bool, date (+36 more)
### Community 38 - "Community 38"
Cohesion: 0.17
Nodes (64): AdvanceIssueRequest, BxUserContext, int, ReimburseApplyOut, Session, str, BxUserContext, int (+56 more)
Cohesion: 0.11
Nodes (44): int, PlPlan, PlTransport, Session, str, UploadFile, Any, PlPlanProduct (+36 more)
### Community 39 - "Community 39"
Cohesion: 0.21
Nodes (37): DbInboundOutbound, DbUserContext, Session, str, CreateLinkForPlanPayload, _apply_inventory_product_update(), _apply_inventory_update(), _base_query() (+29 more)
Cohesion: 0.04
Nodes (46): get_plan_arrange_info(), patch_plan_product_certs(), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输), 更新计划危化品产品购买证/运输证(不触发安排运输) (+38 more)
### Community 40 - "Community 40"
Cohesion: 0.12
Nodes (31): CRM 报价单 API 路由 — 挂接到 crm.router, CRM 报价单 Pydantic Schemas, QuoteAcceptBody, QuoteApprovalApproveBody, QuoteApprovalListBody, QuoteApprovalRefreshNamesBody, QuoteApprovalWithdrawBody, QuoteCreateBody (+23 more)
Cohesion: 0.04
Nodes (45): 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list, 分页查询供方列表 — Java: CrmSupplierInfoController.list (+37 more)
### Community 41 - "Community 41"
Cohesion: 0.07
Nodes (41): _db_pool_keepalive_loop(), _error_json(), lifespan(), _mask_secret(), Exception, int, Request, str (+33 more)
Cohesion: 0.13
Nodes (32): BxUserContext, int, Session, str, Any, str, bool, BxUserContext (+24 more)
### Community 42 - "Community 42"
Cohesion: 0.05
Nodes (44): Any, datetime, Decimal, calculate_quote_amount(), _decimal_value(), _parse_optional_datetime(), _period_key(), Java: statisticsOverview (+36 more)
Cohesion: 0.17
Nodes (21): Any, bool, BxUserContext, BxWorkflowNode, float, int, Session, str (+13 more)
### Community 43 - "Community 43"
Cohesion: 0.13
Nodes (37): Any, bool, Decimal, int, Session, str, batch_insert_quote_products(), calculate_subtotal() (+29 more)
Cohesion: 0.08
Nodes (41): Any, bool, CRM 供方信息 CRUD — 对照 CrmSupplierInfoServiceImpl.java, int, Session, str, generate_contract_no(), Java: generateContractNo — {供方编码}/X-JT + yyyyMMdd + 3位流水 (+33 more)
### Community 44 - "Community 44"
Cohesion: 0.07
Nodes (98): pool_rule_toggle(), Any, int, Session, str, Any, bool, CRM 客户 CRUD(客户主表 + 转移/成交/公海池操作) (+90 more)
Cohesion: 0.08
Nodes (41): _avatar_url_field(), _build_user_info_payload(), change_current_user_password(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), public_quote_share() (+33 more)
### Community 45 - "Community 45"
Cohesion: 0.13
Nodes (15): Any, bool, int, str, get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.html, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total_amo (+7 more)
Cohesion: 0.11
Nodes (38): str, T, bool, date, datetime, int, Session, str (+30 more)
### Community 46 - "Community 46"
Cohesion: 0.18
Nodes (11): generate_contract_no(), Java: generateContractNo — {供方编码}/X-JT + yyyyMMdd + 3位流水, Java: generateContractNo — {供方编码}/X-JT + yyyyMMdd + 3位流水, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号}, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号}, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号}, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号}, Java: generateContractNo — {供方编码}/X-JT{yyyyMMdd}{3位序号} (+3 more)
Nodes (40): DbInboundOutbound, DbUserContext, Session, str, CreateLinkForPlanPayload, _apply_inventory_product_update(), _apply_inventory_update(), _base_query() (+32 more)
### Community 47 - "Community 47"
Cohesion: 0.11
Nodes (40): DbUserContext, Session, str, Session, str, plan_to_read(), plan_to_read_with_fill_link(), _apply_plan_product_update() (+32 more)
### Community 48 - "Community 48"
Cohesion: 0.15
Nodes (39): bool, CertRow, Session, str, VehiclePersonnelRow, Session, str, VehiclePersonnelRow (+31 more)
### Community 49 - "Community 49"
Cohesion: 0.13
Nodes (38): bool, Redis, Request, str, _T, bool, Redis, extend_session() (+30 more)
### Community 50 - "Community 50"
Cohesion: 0.14
Nodes (25): bool, BxUserContext, int, Session, str, Any, bool, int (+17 more)
### Community 51 - "Community 51"
Cohesion: 0.13
Nodes (37): Any, bool, Decimal, int, Session, str, batch_insert_quote_products(), calculate_subtotal() (+29 more)
### Community 52 - "Community 52"
Cohesion: 0.13
Nodes (35): Any, bool, int, Session, str, date, Query, approve_quote() (+27 more)
### Community 53 - "Community 53"
Cohesion: 0.28
Nodes (33): AdvanceIssueRequest, BxUserContext, int, ReimburseApplyOut, Session, str, BatchOffsetRequest, AdvanceFinanceIssueStatsOut (+25 more)
### Community 54 - "Community 54"
Cohesion: 0.13
Nodes (15): Any, bool, int, str, get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.html, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total_amo (+7 more)
### Community 55 - "Community 55"
Cohesion: 0.16
Nodes (33): Any, bool, int, Session, str, Any, Session, str (+25 more)
### Community 48 - "Community 48"
Cohesion: 0.16
Nodes (94): date, DbUserContext, int, Session, str, DocumentReminderRead, DocumentReminderUpdate, InventoryLedgerResponse (+86 more)
### Community 49 - "Community 49"
Cohesion: 0.38
Nodes (22): DbUserContext, int, Session, str, PlTransportAddress, 运输通用地址库 pl_transport_address, 运输通用地址库 pl_transport_address, 运输通用地址库 pl_transport_address (+14 more)
### Community 50 - "Community 50"
Cohesion: 0.12
Nodes (35): datetime, int, str, datetime, date, datetime, str, 审批轮次过滤 — 驳回后重新提交时,进度接口仅展示当前轮次。 (+27 more)
### Community 51 - "Community 51"
Cohesion: 0.17
Nodes (32): Any, bool, CrmContractProductPriceTier, date, Decimal, int, Session, str (+24 more)
### Community 52 - "Community 52"
Cohesion: 0.25
Nodes (8): Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, Java Controller TODO — 保持 pending,记录备注, submit_change_approval()
### Community 53 - "Community 53"
Cohesion: 0.14
Nodes (39): Any, bool, int, Session, str, SysUser, create_user(), get_user() (+31 more)
### Community 54 - "Community 54"
Cohesion: 0.23
Nodes (10): Any, bool, int, Session, str, camel_to_snake(), CRUDBase, get_model_attr() (+2 more)
### Community 55 - "Community 55"
Cohesion: 0.15
Nodes (35): Engine, Path, build_id_maps(), clip_text(), count_rows(), export_mapping(), fetch_rows(), legacy_id_to_str() (+27 more)
### Community 56 - "Community 56"
Cohesion: 0.22
Nodes (29): Any, int, Session, str, create_instance(), create_process_def(), create_task(), get_all_tasks_for_business() (+21 more)
Cohesion: 0.16
Nodes (33): Any, bool, CrmContractProductPriceTier, date, Decimal, int, Session, str (+25 more)
### Community 57 - "Community 57"
Cohesion: 0.22
Nodes (49): InboundOutboundRead, bool, PurchasePlanRead, PurchasePlanWithFillLink, DbUserContext, DbWeighingSlip, Session, str (+41 more)
Cohesion: 0.35
Nodes (31): AdvanceApplyCreate, AdvanceApplyOut, AdvanceApplyUpdate, AdvanceApprovalCreate, BxUserContext, int, Session, str (+23 more)
### Community 58 - "Community 58"
Cohesion: 0.19
Nodes (21): DbUserContext, Session, str, Session, str, int, Session, str (+13 more)
Cohesion: 0.21
Nodes (29): Any, bool, int, Session, str, int, Session, str (+21 more)
### Community 59 - "Community 59"
Cohesion: 0.24
Nodes (20): Any, bool, str, _actor_ids(), _actor_names(), assert_row_deletable_by_creator(), assert_rows_deletable_by_creator(), can_delete_by_creator() (+12 more)
Cohesion: 0.06
Nodes (31): 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo, 供方详情 — Java: CrmSupplierInfoController.getInfo (+23 more)
### Community 60 - "Community 60"
Cohesion: 0.19
Nodes (18): str, Any, bool, Session, str, CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _yes_no(), _build_workbook() (+10 more)
Cohesion: 0.35
Nodes (30): BxUserContext, int, Session, str, approve_reimburse(), approved_by_me(), _build_details_data(), create_reimburse() (+22 more)
### Community 61 - "Community 61"
Cohesion: 0.24
Nodes (25): DbUserContext, float, Session, str, Session, str, DashboardCargoStat, DashboardPartnerCargoStat (+17 more)
Cohesion: 0.23
Nodes (28): Engine, build_id_maps(), clip_text(), count_rows(), export_mapping(), fetch_rows(), legacy_id_to_str(), main() (+20 more)
### Community 62 - "Community 62"
Cohesion: 0.08
Nodes (40): Any, Any, str, Any, 与门户 JWT / apply_data_scope 所需的 user_info 字段对齐。, _build_customer_address(), _change_row_to_dict(), contract_row_to_dict() (+32 more)
Cohesion: 0.22
Nodes (26): DbUserContext, float, Session, str, Session, str, get_db_current_user(), DashboardCargoStat (+18 more)
### Community 63 - "Community 63"
Cohesion: 0.09
Nodes (27): Any, _build_category_tree(), _category_row_to_dict(), _collect_category_with_ancestors(), list_categories(), list_category_tree(), list_oss_by_biz(), list_product_options() (+19 more)
### Community 64 - "Community 64"
Cohesion: 0.25
Nodes (18): BxUserContext, Session, str, bool, BxUserContext, Session, str, create_expense_item() (+10 more)
### Community 65 - "Community 65"
Cohesion: 0.15
Nodes (22): API 路由包 — 山峡化工生产一体化门户, create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), submit_leave() (+14 more)
### Community 66 - "Community 66"
Cohesion: 0.08
Nodes (25): 技术栈, 1. 创建虚拟环境, 项目结构, 1. 创建虚拟环境, 2. 安装依赖, 2. 安装依赖, 3. 配置环境变量, 快速开始 (+17 more)
### Community 64 - "Community 64"
Cohesion: 0.21
Nodes (27): approve_task(), _assert_wf_instance_in_scope(), _business_type_label(), create_process_def(), delete_process_def(), _enrich_task_list(), get_business_all_tasks(), _get_business_form_fields() (+19 more)
### Community 65 - "Community 65"
Cohesion: 0.12
Nodes (33): BxUserContext, int, Session, str, Any, str, bool, BxUserContext (+25 more)
### Community 66 - "Community 66"
Cohesion: 0.18
Nodes (24): bool, date, datetime, int, Session, str, ReimburseApplyOut, allocate_reimburse_title_seq() (+16 more)
### Community 67 - "Community 67"
Cohesion: 0.20
Nodes (18): bool, int, Redis, Request, str, _claims_from_auth(), _coerce_post_method_override_to_get(), _get_redis_client() (+10 more)
Cohesion: 0.3
Nodes (25): DbUserContext, DbWeighingSlip, Session, str, datetime_end_of_day(), parse_datetime_str(), weighing_to_read(), apply_product_snapshot_to_weighing() (+17 more)
### Community 68 - "Community 68"
Cohesion: 0.25
Nodes (23): Any, bool, int, Session, str, create_role(), get_role(), get_role_data_scope() (+15 more)
Cohesion: 0.08
Nodes (25): batch_assign_owner(), download_contract_pdf(), Java: batchAssignOwner, Java: downloadContractPdf — 返回合同文件 URL/路径, Java: batchAssignOwner, Java: batchAssignOwner, Java: batchAssignOwner, Java: batchAssignOwner (+17 more)
### Community 69 - "Community 69"
Cohesion: 0.21
@@ -473,54 +454,54 @@ Nodes (16): Any, int, str, BusinessException, InvalidStatusTransitionException,
### Community 70 - "Community 70"
Cohesion: 0.14
Nodes (25): bool, BxUserContext, int, Session, str, Any, bool, int (+17 more)
Nodes (22): Session, str, bool, Session, str, get_user_menu_codes(), 菜单 code 权限守卫(V0.3:通过 sys_user_role → sys_role_menu → sys_menu.perms), 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。 (+14 more)
### Community 71 - "Community 71"
Cohesion: 0.16
Nodes (16): bool, date, Session, str, get_last_month_range(), month_range(), 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生 (+8 more)
### Community 72 - "Community 72"
Cohesion: 0.26
Nodes (22): Any, bool, datetime, int, Session, str, BizSampleCode, batch_generate_sample_codes() (+14 more)
### Community 72 - "Community 72"
Cohesion: 0.23
Nodes (10): Any, bool, int, Session, str, camel_to_snake(), CRUDBase, get_model_attr() (+2 more)
### Community 73 - "Community 73"
Cohesion: 0.32
Nodes (22): Any, CrmOpportunity, Decimal, int, Session, str, batch_add_opportunity_products(), _calc_subtotal() (+14 more)
Cohesion: 0.18
Nodes (19): bytes, int, str, download_file_bytes(), file_stream(), get_access_url(), get_download_url(), get_preview_url() (+11 more)
### Community 74 - "Community 74"
Cohesion: 0.06
Nodes (88): Any, Decimal, Session, str, _advance_after_approval(), _approval_to_dict(), can_user_approve_settlement(), cancel_draft_settlement() (+80 more)
Cohesion: 0.19
Nodes (18): str, Any, bool, Session, str, CRM 模块 Excel 导出列定义(字段与字典类型对齐 Java *Vo @ExcelDictFormat)。, _yes_no(), _build_workbook() (+10 more)
### Community 75 - "Community 75"
Cohesion: 0.28
Nodes (11): operlog_detail(), operlog_list(), 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), 操作日志分页列表(基于 API 请求日志适配 RuoYi OperLog 结构), _user_info(), Session, OperLogDetailBody, OperLogListBody (+3 more)
Cohesion: 0.09
Nodes (23): generate_barcode(), generate_product_no(), _max_sxwl_product_seq(), 生成产品编号(格式:CP + yyyyMMdd + 3位序号,如 CP20260530001), 生成产品编号(格式:CP + yyyyMMdd + 3位序号,如 CP20260530001), 生成产品编号(格式:CP + yyyyMMdd + 3位序号,如 CP20260530001), 生成产品编号(格式:CP + yyyyMMdd + 3位序号,如 CP20260530001), 生成产品编号(格式:CP + yyyyMMdd + 3位序号,如 CP20260530001) (+15 more)
### Community 76 - "Community 76"
Cohesion: 0.27
Nodes (17): create_leave(), delete_leave(), get_leave(), _leave_local_callback(), leave_workflow_callback(), list_leaves(), submit_leave(), update_leave() (+9 more)
### Community 77 - "Community 77"
Cohesion: 0.19
Nodes (20): int, str, Any, bool, int, Session, str, business_type_from_path() (+12 more)
### Community 78 - "Community 78"
Cohesion: 0.28
Nodes (18): Any, int, Session, str, _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept() (+10 more)
### Community 79 - "Community 79"
Cohesion: 0.34
Nodes (16): Any, bool, int, Session, str, create_dict_type(), dict_type_code_exists(), get_dict_type() (+8 more)
### Community 80 - "Community 80"
Cohesion: 0.31
Nodes (20): Any, bool, CrmOpportunity, datetime, int, Session, str, create_opportunity_follow() (+12 more)
### Community 81 - "Community 81"
Cohesion: 0.09
Nodes (23): product_delete(), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids), 删除产品(支持单条 body.id 和批量 body.ids) (+15 more)
### Community 77 - "Community 77"
Cohesion: 0.28
Nodes (22): bool, CRM 产品模块 CRUD(产品分类 + 产品 + 附件), Session, str, barcode_exists(), category_code_exists(), create_category(), create_product() (+14 more)
### Community 78 - "Community 78"
Cohesion: 0.32
Nodes (22): Any, CrmOpportunity, Decimal, int, Session, str, batch_add_opportunity_products(), _calc_subtotal() (+14 more)
### Community 79 - "Community 79"
Cohesion: 0.38
Nodes (22): DbUserContext, int, Session, str, PlTransportAddress, 运输通用地址库 pl_transport_address, 运输通用地址库 pl_transport_address, 运输通用地址库 pl_transport_address (+14 more)
### Community 80 - "Community 80"
Cohesion: 0.24
Nodes (20): Any, bool, str, _actor_ids(), _actor_names(), assert_row_deletable_by_creator(), assert_rows_deletable_by_creator(), can_delete_by_creator() (+12 more)
### Community 81 - "Community 81"
Cohesion: 0.14
Nodes (19): Any, bool, str, Decimal, str, decrypt_login_payload(), ensure_initialized(), extract_login_credentials() (+11 more)
### Community 82 - "Community 82"
Cohesion: 0.10
Cohesion: 0.1
Nodes (20): 1. 上传到服务器, 1. 上传到服务器, 2. 服务器首次启动, 2. 服务器首次启动, 3. 日常运维, 3. 日常运维, 4. 配置文件, 4. 配置文件 (+12 more)
### Community 83 - "Community 83"
@@ -528,152 +509,152 @@ Cohesion: 0.18
Nodes (11): float, int, str, 发送订单状态通知 Args: openid: 用户openid order_n, 发送支付成功通知 Args: openid: 用户openid order_n, 发送配送通知 Args: openid: 配送员openid task_no:, 发送配送时效预警 Args: openid: 配送员openid task_n, 发送退款结果通知 Args: openid: 用户openid order_n (+3 more)
### Community 84 - "Community 84"
Cohesion: 0.1
Nodes (20): create_from_quote(), _quote_products_to_contract_products(), Java: createFromQuote — 返回合同 id, Java: renewContract — 基础续签, Java: createFromQuote — 返回合同 id, Java: renewContract — 基础续签, Java: createFromQuote — 返回合同 id, Java: createFromQuote — 返回合同 id (+12 more)
### Community 85 - "Community 85"
Cohesion: 0.34
Nodes (19): check_python(), create_venv(), ensure_dirs(), ensure_valid_venv(), ensure_venv_and_runtime(), install_dependencies(), is_running(), log_error() (+11 more)
### Community 85 - "Community 85"
Cohesion: 0.29
Nodes (16): Any, int, Session, str, BizLeaveRequest, create_leave(), get_leave(), list_leaves() (+8 more)
### Community 86 - "Community 86"
Cohesion: 0.16
Nodes (16): bool, date, Session, str, get_last_month_range(), month_range(), 地磅计划按月自动生成 — 迁移自 simple-dibang-xiaoshou/auto-create-plan/auto_create_monthly_pla, 按月自动生成采购计划。 - 默认仅在每月 1 日执行(force=True 时跳过该限制,供手动触发验收) - 遍历所有租户,按上月计划模板生 (+8 more)
### Community 87 - "Community 87"
Cohesion: 0.28
Nodes (18): Any, int, Session, str, _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept() (+10 more)
### Community 88 - "Community 88"
Cohesion: 0.21
Nodes (17): bool, int, Redis, Request, str, _claims_from_auth(), _coerce_post_method_override_to_get(), _get_redis_client() (+9 more)
### Community 89 - "Community 89"
Cohesion: 0.35
Nodes (17): Any, bool, int, Session, str, _build_tree(), _cascade_soft_delete(), create_menu() (+9 more)
### Community 87 - "Community 87"
Cohesion: 0.09
Nodes (22): cancel_plan(), 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。, 作废运输计划:取消跟进状态、作废关联地磅出入库单、取消运输单。 (+14 more)
### Community 88 - "Community 88"
Cohesion: 0.37
Nodes (17): check_env(), check_python(), create_venv(), init_env(), install_dependencies(), log_error(), log_info(), log_success() (+9 more)
### Community 89 - "Community 89"
### Community 90 - "Community 90"
Cohesion: 0.22
Nodes (17): Any, bool, Session, str, list_share_logs(), _parse_user_agent(), CRM 报价单分享访问日志 CRUD — 对照 CrmQuoteShareLogServiceImpl.java, Java: statisticsVisits (+9 more)
### Community 90 - "Community 90"
Cohesion: 0.38
Nodes (15): Any, bool, int, Session, str, create_site(), get_site(), list_sites() (+7 more)
### Community 91 - "Community 91"
Cohesion: 0.10
Nodes (21): _generate_plan_no(), 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD######, 生成计划编号 SXDDHYYYYMMDD###### (+13 more)
Cohesion: 0.12
Nodes (16): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), Session, Session, get_current_user(), get_current_user_by_token(), 根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期), 根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期) (+8 more)
### Community 92 - "Community 92"
Cohesion: 0.10
Nodes (21): create_new_version(), Java: createNewVersion — 返回新报价单 id, Java: toContract — 返回 contractId, Java: createNewVersion — 返回新报价单 id, Java: createNewVersion — 返回新报价单 id, Java: createNewVersion — 返回新报价单 id, Java: createNewVersion — 返回新报价单 id, Java: createNewVersion — 返回新报价单 id (+13 more)
Cohesion: 0.37
Nodes (17): check_env(), check_python(), create_venv(), init_env(), install_dependencies(), log_error(), log_info(), log_success() (+9 more)
### Community 93 - "Community 93"
Cohesion: 0.34
Nodes (16): Any, bool, int, Session, str, create_tenant(), get_tenant(), list_tenants() (+8 more)
Nodes (16): Any, bool, int, Session, str, create_dict_type(), dict_type_code_exists(), get_dict_type() (+8 more)
### Community 94 - "Community 94"
Cohesion: 0.41
Nodes (13): BxUserContext, Session, str, UploadFile, bind_biz(), delete_attachment(), download_file(), list_by_biz() (+5 more)
Cohesion: 0.29
Nodes (16): Any, int, Session, str, BizLeaveRequest, create_leave(), get_leave(), list_leaves() (+8 more)
### Community 95 - "Community 95"
Cohesion: 0.23
Nodes (14): int, Session, str, _allocate_inbound_outbound_id(), _ensure_sequence_row(), max_numeric_inbound_outbound_id(), next_inbound_outbound_id(), 出入库单 id 生成 — 租户内纯数字自增,并发安全。 (+6 more)
### Community 96 - "Community 96"
Cohesion: 0.20
Nodes (10): Decimal, VehicleUreaApplyCreate, VehicleUreaApplyListResponse, VehicleUreaApplyRead, VehicleUreaApplyUpdate, VehicleUreaDisburseBoardListResponse, VehicleUreaDisburseCreate, VehicleUreaDisburseListResponse (+2 more)
### Community 97 - "Community 97"
Cohesion: 0.38
Nodes (15): Any, bool, int, Session, str, create_post(), get_post(), list_posts() (+7 more)
### Community 98 - "Community 98"
Cohesion: 0.41
Nodes (11): Any, str, build_quote_html(), _default_value(), _format_date(), _format_discount(), _format_money(), generate_quote_pdf() (+3 more)
### Community 96 - "Community 96"
Cohesion: 0.38
Nodes (15): Any, bool, int, Session, str, create_site(), get_site(), list_sites() (+7 more)
### Community 99 - "Community 99"
### Community 97 - "Community 97"
Cohesion: 0.36
Nodes (15): Any, bool, Session, str, ensure_crm_customer_linked_row_in_scope(), 客户子表(开票信息等):先校验关联客户 owner scope,否则校验 create_by。, _clear_default_for_customer(), create_invoice_info() (+7 more)
### Community 98 - "Community 98"
Cohesion: 0.33
Nodes (14): Any, int, Session, str, create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options() (+6 more)
### Community 100 - "Community 100"
### Community 99 - "Community 99"
Cohesion: 0.29
Nodes (14): is_valid_dict_type(), load_portal_baseline(), load_sx(), load_zkxw(), main(), map_tag_type(), normalize_row(), parse_insert() (+6 more)
### Community 100 - "Community 100"
Cohesion: 0.28
Nodes (13): int, Session, str, _allocate_inbound_outbound_id(), _ensure_sequence_row(), max_numeric_inbound_outbound_id(), next_inbound_outbound_id(), 出入库单 id 生成 — 租户内纯数字自增,并发安全。 (+5 more)
### Community 101 - "Community 101"
Cohesion: 0.22
Nodes (18): Any, bool, bytes, int, Request, str, _claims_from_auth(), _format_body_bytes() (+10 more)
Cohesion: 0.3
Nodes (13): Any, bool, bytes, int, str, ApiCryptoError, _b64url_decode(), _b64url_encode() (+5 more)
### Community 102 - "Community 102"
Cohesion: 0.35
Nodes (5): Any, str, WfProcessInstance, WorkflowEngine, WfProcessInstance
Cohesion: 0.19
Nodes (11): DbUserContext, Session, str, _auto_fill_create_dept_id(), get_db(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID, ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID, ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID (+3 more)
### Community 103 - "Community 103"
Cohesion: 0.12
Nodes (16): int, _fill_contract_linked_count(), list_quotes(), Java: fillContractLinkedCount, Java: fillContractLinkedCount, Java: fillContractLinkedCount, Java: fillContractLinkedCount, Java: fillContractLinkedCount (+8 more)
Cohesion: 0.41
Nodes (13): BxUserContext, Session, str, UploadFile, bind_biz(), delete_attachment(), download_file(), list_by_biz() (+5 more)
### Community 104 - "Community 104"
Cohesion: 0.14
Nodes (15): date, Query, _build_quote_filters(), _parse_optional_date(), Java: toContract — 返回 contractId, Java: toContract — 返回 contractId, Java: buildQueryWrapper, Java: buildQueryWrapper (+7 more)
Cohesion: 0.44
Nodes (13): bool, date, PlCarrier, str, PlCarrier, assert_carrier_eligible_for_transport(), carrier_agreement_expired(), carrier_audit_approved() (+5 more)
### Community 105 - "Community 105"
Cohesion: 0.17
Nodes (20): Any, int, str, get_oper_log_meta(), OperLogMeta, 请求级操作日志元数据(ContextVar), 供异步落库线程使用,避免 ContextVar 跨线程丢失。, set_oper_log_meta() (+12 more)
### Community 106 - "Community 106"
Cohesion: 0.36
Nodes (10): add_scope_before_order(), ensure_import(), patch_base_data(), patch_get_helper(), patch_inventory(), patch_plan(), patch_transport(), str (+2 more)
### Community 107 - "Community 107"
Cohesion: 0.60
Nodes (10): Any, Session, str, _apply_create_range(), _base_query(), get_clue_level_statistics(), get_clue_overview_statistics(), get_clue_owner_statistics() (+2 more)
### Community 108 - "Community 108"
Cohesion: 0.22
Nodes (12): Any, bool, str, WfProcessInstance, _LocalCallbackFn, _dispatch_local(), 工作流回调服务 —— 流程状态变更时通知业务系统, 注册本地回调函数。当 callback_url 以 path 开头时直接调用 fn。 (+4 more)
### Community 106 - "Community 106"
Cohesion: 0.24
Nodes (8): Path, Path, _inject_user_info_after_tenant(), patch_contract_routes(), patch_quote_routes(), patch_route_file(), Path, str
### Community 107 - "Community 107"
Cohesion: 0.17
Nodes (12): generate_auto_product_no(), Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符, Java: generateAutoProductNo — SXWL + 8位随机大写字符 (+4 more)
### Community 108 - "Community 108"
Cohesion: 0.17
Nodes (12): _get_quote_item_field(), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配), Java: resolveProductIdForQuoteItem(CrmProduct 无 tax_rate,跳过税率匹配) (+4 more)
### Community 109 - "Community 109"
Cohesion: 0.14
Nodes (22): Session, str, bool, Session, str, get_user_menu_codes(), 菜单 code 权限守卫(V0.3:通过 sys_user_role → sys_role_menu → sys_menu.perms), 读取用户授权的菜单权限标识集合(与前端 meta.menuCode / perms 对齐)。 (+14 more)
Cohesion: 0.18
Nodes (10): Any, Request, str, str, parse_admin_request_json(), 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, 统一解析接口请求载荷(明文 / 密文信封)。 (+2 more)
### Community 110 - "Community 110"
Cohesion: 0.33
Nodes (10): Any, int, Session, str, list_ethnics(), 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), 民族码表 sys_ethnic(国标 GB/T 3304,全局) (+2 more)
### Community 111 - "Community 111"
Cohesion: 0.18
Nodes (11): generate_contract_name(), Java: generateContractName, Java: generateContractName, Java: generateContractName, Java: generateContractName, Java: generateContractName, Java: generateContractName, Java: generateContractName (+3 more)
### Community 111 - "Community 111"
Cohesion: 0.19
Nodes (38): ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody, StartInstanceBody, Any, bool, WfProcessInstance, bool (+30 more)
### Community 112 - "Community 112"
Cohesion: 0.26
Nodes (27): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, MenuCreateBody (+19 more)
Cohesion: 0.4
Nodes (10): SysOss, int, Session, str, SysOss, create_oss(), create_oss(), get_oss_by_url() (+2 more)
### Community 113 - "Community 113"
Cohesion: 0.10
Nodes (20): create_from_quote(), _quote_products_to_contract_products(), Java: createFromQuote — 返回合同 id, Java: renewContract — 基础续签, Java: createFromQuote — 返回合同 id, Java: renewContract — 基础续签, Java: createFromQuote — 返回合同 id, Java: createFromQuote — 返回合同 id (+12 more)
Cohesion: 0.18
Nodes (9): 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, 报销(bx)Pydantic 模型 — 响应协议与 bx 原系统保持一致, bx_health(), 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。 (+1 more)
### Community 114 - "Community 114"
Cohesion: 0.19
Nodes (11): Decimal, VehicleMaintenanceApplyCreate, VehicleMaintenanceApplyListResponse, VehicleMaintenanceApplyRead, VehicleMaintenanceApplyReminder, VehicleMaintenanceApplyUpdate, VehicleMaintenanceProcessBoardListResponse, VehicleMaintenanceProcessCreate (+3 more)
Cohesion: 0.6
Nodes (10): Any, Session, str, _apply_create_range(), _base_query(), get_clue_level_statistics(), get_clue_overview_statistics(), get_clue_owner_statistics() (+2 more)
### Community 115 - "Community 115"
Cohesion: 0.29
Nodes (9): AST, expr, field_has_alias(), iter_field_assignments(), main(), bool, int, str (+1 more)
Cohesion: 0.36
Nodes (10): add_scope_before_order(), ensure_import(), patch_base_data(), patch_get_helper(), patch_inventory(), patch_plan(), patch_transport(), str (+2 more)
### Community 116 - "Community 116"
Cohesion: 0.15
Nodes (13): ORM → camelCase(单点真相), ORM → camelCase(单点真相), ORM → camelCase(单点真相), ORM → camelCase(单点真相), Java: viewByShareCode, Java: viewByShareCode, Java: viewByShareCode, Java: viewByShareCode (+5 more)
Cohesion: 0.2
Nodes (10): export_contracts(), Java: queryList for export, Java: queryList for export, Java: queryList for export, Java: queryList for export, Java: queryList for export, Java: queryList for export, Java: queryList for export (+2 more)
### Community 117 - "Community 117"
Cohesion: 0.44
Nodes (8): bool, int, Session, str, ApiRequestLogCRUD, SysApiRequestLog, SysApiRequestLogHis, SysApiRequestLog
Cohesion: 0.2
Nodes (10): create_from_opportunity(), _opportunity_products_to_contract_products(), Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id (+2 more)
### Community 118 - "Community 118"
Cohesion: 0.20
Nodes (10): create_from_opportunity(), _opportunity_products_to_contract_products(), Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id, Java: createFromOpportunity — 返回合同 id (+2 more)
Cohesion: 0.2
Nodes (10): int, list_products(), _product_row_to_dict(), 产品 ORM 对象转 dict(camelCase 键名), 产品 ORM 对象转 dict(camelCase 键名), 产品 ORM 对象转 dict(camelCase 键名), 产品 ORM 对象转 dict(camelCase 键名), 产品 ORM 对象转 dict(camelCase 键名) (+2 more)
### Community 119 - "Community 119"
Cohesion: 0.29
Nodes (10): datetime, int, Session, str, BizNoKind, allocate_next_biz_no(), _format_biz_no(), _prefix_for() (+2 more)
Nodes (9): AST, expr, field_has_alias(), iter_field_assignments(), main(), bool, int, str (+1 more)
### Community 120 - "Community 120"
Cohesion: 0.27
Nodes (11): Any, bool, str, decrypt_login_payload(), ensure_initialized(), extract_login_credentials(), get_public_pem(), 登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。 (+3 more)
Cohesion: 0.22
Nodes (9): generate_template_no(), Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号} (+1 more)
### Community 121 - "Community 121"
Cohesion: 0.22
@@ -684,120 +665,40 @@ Cohesion: 0.32
Nodes (7): str, eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci()
### Community 123 - "Community 123"
Cohesion: 0.33
Nodes (10): Any, int, Session, str, list_ethnics(), 民族码表 CRUD(全局 sys_ethnic), _row_to_dict(), 民族码表 sys_ethnic(国标 GB/T 3304,全局) (+2 more)
### Community 124 - "Community 124"
Cohesion: 0.18
Nodes (9): 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, 报销(bx)Pydantic 模型 — 响应协议与 bx 原系统保持一致, bx_health(), 报销(bx)API 路由聚合 — REST 风格,协议对齐 bx 原系统。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。, P0 健康检查:验证 bx 路由已挂载且响应协议为 code=0。 (+1 more)
### Community 125 - "Community 125"
Cohesion: 0.22
Nodes (9): generate_template_no(), Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号}, Java: generateTemplateNo — TMPL{yyyyMMdd}{4位序号} (+1 more)
### Community 126 - "Community 126"
Cohesion: 0.05
Nodes (48): BaseModel, AdvanceApplyOut, AdvanceApprovalCreate, AttachmentOut, PagedQuery, PagedResponse, ReimburseApplyCreate, ReimburseApplyUpdate (+40 more)
### Community 127 - "Community 127"
Cohesion: 0.32
Nodes (7): Session, str, apply_product_snapshot_to_weighing(), ProductSnapshot, 地磅模块 — CRM 产品解析与快照写入。, 校验 CRM 产品并返回名称/规格快照。新建单据 product_id 必填。, resolve_crm_product()
### Community 128 - "Community 128"
Cohesion: 0.29
Nodes (5): API 路由包 — 山峡化工生产一体化门户, get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,14 个一级菜单), 运营端角色守卫:admin / super_admin 可访问。, require_admin_or_super_admin()
### Community 129 - "Community 129"
Cohesion: 0.38
Nodes (6): date, datetime, str, _date_to_str(), _dt_to_str(), bx 原系统 API 响应包装(code=0 / msg / data.rows),与门户 success_response 分离。
### Community 130 - "Community 130"
Cohesion: 0.09
Nodes (29): _avatar_url_field(), _build_user_info_payload(), get_current_user_profile(), _jwt_user_payload(), logout(), public_quote_share(), 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。, 登出:吊销 Redis 会话(若已配置 REDIS_HOST)。 (+21 more)
### Community 131 - "Community 131"
Cohesion: 0.40
Nodes (3): BaseSettings, Config, Settings
### Community 132 - "Community 132"
Cohesion: 0.33
Nodes (5): _coerce_optional_id(), WorkflowDefCreate, WorkflowDefUpdate, WorkflowNodeCreate, WorkflowNodeOut
### Community 134 - "Community 134"
Cohesion: 0.33
Nodes (6): attachment_download_url(), 返回带 Content-Disposition 的下载 URL,保证浏览器使用原始文件名。, 返回带 Content-Disposition 的下载 URL,保证浏览器使用原始文件名。, 返回带 Content-Disposition 的下载 URL,保证浏览器使用原始文件名。, 返回带 Content-Disposition 的下载 URL,保证浏览器使用原始文件名。, 返回带 Content-Disposition 的下载 URL,保证浏览器使用原始文件名。
### Community 135 - "Community 135"
Cohesion: 0.33
Nodes (3): 地磅 API 路由聚合 — REST 风格,协议对齐原 simple-dibang-xiaoshou。, 地磅(db)Pydantic schemas — 对齐原 simple-dibang-xiaoshou 契约。, 地磅 API 路由聚合 — REST 风格,协议对齐原 simple-dibang-xiaoshou。
### Community 136 - "Community 136"
Cohesion: 0.18
Nodes (10): Any, Request, str, str, parse_admin_request_json(), 运营 Web(/web/admin)JSON 请求体解析。 与 ApiCryptoMiddleware 配合:中间件未改写 body 时,在路由内解密 `{, 读取 JSON body;dict 时走 resolve_request_payload(明文 / 密文 / data 包装)。 Returns:, 统一解析接口请求载荷(明文 / 密文信封)。 (+2 more)
### Community 137 - "Community 137"
Cohesion: 0.33
Nodes (8): Decimal, str, derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 148 - "Community 148"
Cohesion: 0.38
Nodes (4): str, _coerce_id(), ExpenseItemCreate, ExpenseItemUpdate
### Community 149 - "Community 149"
### Community 124 - "Community 124"
Cohesion: 0.33
Nodes (3): _coerce_id(), OffsetItem, ReimburseDetailCreate
Nodes (3): 地磅 API 路由聚合 — REST 风格,协议对齐原 simple-dibang-xiaoshou。, 地磅(db)Pydantic schemas — 对齐原 simple-dibang-xiaoshou 契约。, 地磅 API 路由聚合 — REST 风格,协议对齐原 simple-dibang-xiaoshou。
### Community 150 - "Community 150"
Cohesion: 0.40
Nodes (5): list_roles_for_designer(), 返回角色下拉选项(label=角色名,value=角色ID UUID),供流程设计器审批人选择使用。 与 /roles 不同,此端点返回角色 UUID, 返回角色下拉选项(label=角色名,value=角色ID UUID),供流程设计器审批人选择使用。 与 /roles 不同,此端点返回角色 UUID, 返回角色下拉选项(label=角色名,value=角色ID UUID),供流程设计器审批人选择使用。 与 /roles 不同,此端点返回角色 UUID, 返回角色下拉选项(label=角色名,value=角色ID UUID),供流程设计器审批人选择使用。 与 /roles 不同,此端点返回角色 UUID
### Community 125 - "Community 125"
Cohesion: 0.4
Nodes (3): BaseSettings, Config, Settings
### Community 151 - "Community 151"
Cohesion: 0.10
Nodes (21): invoice_info_list(), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价), 按客户ID查询开票信息(与 by-customer 等价) (+13 more)
### Community 152 - "Community 152"
Cohesion: 0.38
Nodes (5): TransportAddressBase, TransportAddressCreate, TransportAddressListResponse, TransportAddressRead, TransportAddressUpdate
### Community 153 - "Community 153"
Cohesion: 0.40
### Community 127 - "Community 127"
Cohesion: 0.4
Nodes (5): Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), Web 端登录用 RSA 公钥(PKCS#1 v1.5,与 JSEncrypt 一致), web_login_rsa_public_key()
### Community 154 - "Community 154"
Cohesion: 0.40
Nodes (5): get_web_auth_menu_codes(), 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。, 获取当前用户菜单权限标识(sys_menu.perms,经角色继承)。
### Community 156 - "Community 156"
Cohesion: 0.40
Nodes (3): AdvanceApplyCreate, AdvanceApplyUpdate, _coerce_optional_id()
### Community 157 - "Community 157"
Cohesion: 0.50
Nodes (4): list_roles_for_select(), 返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。, 返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。, 返回运营端角色下拉选项(label=库中角色名,value=Web 角色码)。
### Community 162 - "Community 162"
Cohesion: 0.12
Nodes (17): Session, Session, get_current_user(), get_current_user_by_token(), 根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期), 根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期), 根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期), 获取当前用户(sync 依赖,配合 sync 路由在线程池执行,避免阻塞事件循环)。 (+9 more)
## Knowledge Gaps
- **77 isolated node(s):** `Session`, `Request`, `bool`, `bool`, `Config` (+72 more)
- **1529 isolated node(s):** `定期 ping MySQL,避免远程库/NAT 回收空闲 TCP 后首请求长时间卡住。`, `数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误`, `未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin`, `每月 1 日凌晨执行:按上月计划模板生成本月计划。`, `每天凌晨1点:检查保护期到期客户,跟进次数不足则退回公海` (+1524 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **2 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
- **3 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `Session` connect `Community 12` to `Community 0`, `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 13`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 35`, `Community 37`, `Community 38`, `Community 39`, `Community 42`, `Community 43`, `Community 44`, `Community 46`, `Community 47`, `Community 48`, `Community 49`, `Community 50`, `Community 51`, `Community 52`, `Community 53`, `Community 54`, `Community 56`, `Community 57`, `Community 58`, `Community 60`, `Community 61`, `Community 62`, `Community 64`, `Community 65`, `Community 66`, `Community 68`, `Community 70`, `Community 71`, `Community 72`, `Community 73`, `Community 74`, `Community 75`, `Community 76`, `Community 77`, `Community 78`, `Community 79`, `Community 80`, `Community 81`, `Community 85`, `Community 86`, `Community 87`, `Community 89`, `Community 90`, `Community 91`, `Community 92`, `Community 93`, `Community 94`, `Community 95`, `Community 97`, `Community 99`, `Community 102`, `Community 103`, `Community 104`, `Community 107`, `Community 109`, `Community 111`, `Community 112`, `Community 113`, `Community 116`, `Community 117`, `Community 118`, `Community 119`, `Community 121`, `Community 123`, `Community 125`, `Community 126`, `Community 127`, `Community 130`, `Community 134`, `Community 150`, `Community 151`, `Community 154`, `Community 157`, `Community 162`?**
_High betweenness centrality (0.257) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 3` to `Community 0`, `Community 1`, `Community 132`, `Community 4`, `Community 6`, `Community 7`, `Community 9`, `Community 11`, `Community 15`, `Community 17`, `Community 18`, `Community 148`, `Community 149`, `Community 22`, `Community 23`, `Community 24`, `Community 152`, `Community 20`, `Community 155`, `Community 156`, `Community 30`, `Community 32`, `Community 35`, `Community 38`, `Community 39`, `Community 40`, `Community 48`, `Community 57`, `Community 58`, `Community 61`, `Community 64`, `Community 65`, `Community 66`, `Community 75`, `Community 76`, `Community 96`, `Community 111`, `Community 112`, `Community 114`, `Community 126`?**
_High betweenness centrality (0.055) - this node is a cross-community bridge._
- **Why does `int` connect `Community 38` to `Community 0`, `Community 1`, `Community 2`, `Community 4`, `Community 5`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 14`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 21`, `Community 22`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 29`, `Community 30`, `Community 32`, `Community 33`, `Community 37`, `Community 41`, `Community 43`, `Community 44`, `Community 45`, `Community 47`, `Community 48`, `Community 49`, `Community 50`, `Community 51`, `Community 53`, `Community 54`, `Community 55`, `Community 56`, `Community 57`, `Community 62`, `Community 64`, `Community 65`, `Community 66`, `Community 67`, `Community 68`, `Community 69`, `Community 70`, `Community 71`, `Community 72`, `Community 73`, `Community 74`, `Community 76`, `Community 77`, `Community 78`, `Community 79`, `Community 80`, `Community 83`, `Community 85`, `Community 86`, `Community 90`, `Community 93`, `Community 95`, `Community 97`, `Community 99`, `Community 101`, `Community 102`, `Community 103`, `Community 105`, `Community 111`, `Community 112`, `Community 117`, `Community 119`, `Community 121`, `Community 123`?**
_High betweenness centrality (0.044) - this node is a cross-community bridge._
- **Are the 337 inferred relationships involving `str` (e.g. with `AdvanceApplyCreate` and `AdvanceApplyOut`) actually correct?**
_`str` has 337 INFERRED edges - model-reasoned connections that need verification._
- **Are the 333 inferred relationships involving `Session` (e.g. with `AdvanceApplyCreate` and `AdvanceApplyOut`) actually correct?**
_`Session` has 333 INFERRED edges - model-reasoned connections that need verification._
- **Are the 222 inferred relationships involving `int` (e.g. with `AdvanceApplyCreate` and `AdvanceApplyOut`) actually correct?**
_`int` has 222 INFERRED edges - model-reasoned connections that need verification._
- **Why does `str` connect `Community 14` to `Community 0`, `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 15`, `Community 16`, `Community 17`, `Community 18`, `Community 19`, `Community 20`, `Community 21`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`, `Community 39`, `Community 41`, `Community 42`, `Community 43`, `Community 44`, `Community 45`, `Community 46`, `Community 47`, `Community 48`, `Community 49`, `Community 50`, `Community 51`, `Community 52`, `Community 53`, `Community 54`, `Community 55`, `Community 56`, `Community 57`, `Community 58`, `Community 60`, `Community 61`, `Community 62`, `Community 63`, `Community 64`, `Community 65`, `Community 67`, `Community 68`, `Community 69`, `Community 70`, `Community 71`, `Community 72`, `Community 73`, `Community 74`, `Community 75`, `Community 77`, `Community 78`, `Community 79`, `Community 80`, `Community 81`, `Community 83`, `Community 84`, `Community 86`, `Community 87`, `Community 88`, `Community 89`, `Community 90`, `Community 91`, `Community 93`, `Community 94`, `Community 95`, `Community 96`, `Community 97`, `Community 98`, `Community 100`, `Community 101`, `Community 102`, `Community 103`, `Community 104`, `Community 105`, `Community 106`, `Community 107`, `Community 108`, `Community 109`, `Community 110`, `Community 111`, `Community 112`, `Community 114`, `Community 115`, `Community 116`, `Community 117`, `Community 118`, `Community 120`, `Community 121`, `Community 122`, `Community 123`?**
_High betweenness centrality (0.344) - this node is a cross-community bridge._
- **Why does `Session` connect `Community 18` to `Community 0`, `Community 1`, `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 15`, `Community 17`, `Community 19`, `Community 20`, `Community 21`, `Community 23`, `Community 24`, `Community 25`, `Community 26`, `Community 28`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 36`, `Community 37`, `Community 38`, `Community 39`, `Community 40`, `Community 41`, `Community 42`, `Community 43`, `Community 44`, `Community 45`, `Community 46`, `Community 47`, `Community 48`, `Community 50`, `Community 51`, `Community 52`, `Community 53`, `Community 55`, `Community 56`, `Community 57`, `Community 58`, `Community 59`, `Community 60`, `Community 62`, `Community 63`, `Community 64`, `Community 65`, `Community 67`, `Community 68`, `Community 70`, `Community 71`, `Community 72`, `Community 74`, `Community 75`, `Community 76`, `Community 77`, `Community 78`, `Community 79`, `Community 84`, `Community 86`, `Community 87`, `Community 89`, `Community 90`, `Community 91`, `Community 93`, `Community 94`, `Community 95`, `Community 96`, `Community 97`, `Community 98`, `Community 100`, `Community 102`, `Community 103`, `Community 107`, `Community 108`, `Community 110`, `Community 112`, `Community 114`, `Community 116`, `Community 117`, `Community 118`, `Community 120`, `Community 121`?**
_High betweenness centrality (0.270) - this node is a cross-community bridge._
- **Why does `BaseModel` connect `Community 1` to `Community 0`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 16`, `Community 19`, `Community 21`, `Community 22`, `Community 29`, `Community 37`, `Community 38`, `Community 46`, `Community 48`, `Community 53`, `Community 57`, `Community 60`, `Community 62`, `Community 64`, `Community 65`, `Community 67`, `Community 102`, `Community 123`, `Community 126`?**
_High betweenness centrality (0.059) - this node is a cross-community bridge._
- **Are the 341 inferred relationships involving `str` (e.g. with `ApiRequestLogMiddleware` and `ApiCryptoMiddleware`) actually correct?**
_`str` has 341 INFERRED edges - model-reasoned connections that need verification._
- **Are the 337 inferred relationships involving `Session` (e.g. with `CrmCustomer` and `CrmCustomerPool`) actually correct?**
_`Session` has 337 INFERRED edges - model-reasoned connections that need verification._
- **Are the 225 inferred relationships involving `int` (e.g. with `ApiRequestLogMiddleware` and `ApiCryptoMiddleware`) actually correct?**
_`int` has 225 INFERRED edges - model-reasoned connections that need verification._
- **What connects `定期 ping MySQL,避免远程库/NAT 回收空闲 TCP 后首请求长时间卡住。`, `数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误`, `未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin` to the rest of the system?**
_1525 weakly-connected nodes found - possible documentation gaps or missing edges._
_1529 weakly-connected nodes found - possible documentation gaps or missing edges._
@@ -0,0 +1 @@
{"nodes": [{"id": "users_zlwu_work_00code_shanxia2_0_backend_app_api_pl_base_data_py", "label": "base_data.py", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L1"}, {"id": "pl_base_data_list_carriers", "label": "list_carriers()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "int", "label": "int", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "dbusercontext", "label": "DbUserContext", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "carrierlistresponse", "label": "CarrierListResponse", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L76"}, {"id": "pl_base_data_create_carrier", "label": "create_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L121"}, {"id": "carriercreate", "label": "CarrierCreate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L121"}, {"id": "carrierread", "label": "CarrierRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L121"}, {"id": "pl_base_data_get_carrier", "label": "get_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L151"}, {"id": "pl_base_data_update_carrier", "label": "update_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L162"}, {"id": "carrierupdate", "label": "CarrierUpdate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L162"}, {"id": "pl_base_data_delete_carrier", "label": "delete_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L196"}, {"id": "pl_base_data_approve_carrier", "label": "approve_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L210"}, {"id": "pl_base_data_reject_carrier", "label": "reject_carrier()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L234"}, {"id": "carrierauditreject", "label": "CarrierAuditReject", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L234"}, {"id": "plcarrier", "label": "PlCarrier", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L256"}, {"id": "pl_base_data_vehicle_to_read", "label": "_vehicle_to_read()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L277"}, {"id": "plvehicle", "label": "PlVehicle", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L277"}, {"id": "certread", "label": "CertRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L277"}, {"id": "vehicleread", "label": "VehicleRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L277"}, {"id": "pl_base_data_vehicle_to_detail", "label": "_vehicle_to_detail()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L294"}, {"id": "vehicledetailread", "label": "VehicleDetailRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L294"}, {"id": "pl_base_data_list_vehicles", "label": "list_vehicles()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L312"}, {"id": "bool", "label": "bool", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/pl/base_data.py", "source_location": "L312"}, {"id": "vehiclelistresponse", "label": "VehicleListResponse", "Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_zlwu_work_00code_shanxia2_0_backend_app_api_public_py", "label": "public.py", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_avatar_url_field", "label": "_avatar_url_field()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L39"}, {"id": "sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L39"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/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/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L47"}, {"id": "api_public_jwt_user_payload", "label": "_jwt_user_payload()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L63"}, {"id": "api_public_web_login_rsa_public_key", "label": "web_login_rsa_public_key()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L76"}, {"id": "api_public_web_login", "label": "web_login()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L83"}, {"id": "request", "label": "Request", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L83"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L83"}, {"id": "api_public_refresh_token", "label": "refresh_token()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L141"}, {"id": "api_public_logout", "label": "logout()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L203"}, {"id": "api_public_get_current_user_profile", "label": "get_current_user_profile()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L222"}, {"id": "api_public_get_web_auth_menu_codes", "label": "get_web_auth_menu_codes()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L255"}, {"id": "api_public_change_current_user_password", "label": "change_current_user_password()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L304"}, {"id": "api_public_public_quote_share", "label": "public_quote_share()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L337"}, {"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/shanxia2.0.sql \u57fa\u7ebf\uff09", "file_type": "rationale", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L1"}, {"id": "api_public_rationale_48", "label": "\u4e0e web-admin `userInfo` \u5b57\u6bb5\u7ea6\u5b9a\u4e00\u81f4\u3002", "file_type": "rationale", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L48"}, {"id": "api_public_rationale_77", "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/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L77"}, {"id": "api_public_rationale_88", "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/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L88"}, {"id": "api_public_rationale_204", "label": "\u767b\u51fa\uff1a\u540a\u9500 Redis \u4f1a\u8bdd\uff08\u82e5\u5df2\u914d\u7f6e REDIS_HOST\uff09\u3002", "file_type": "rationale", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L204"}, {"id": "api_public_rationale_223", "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/zlwu/work/00code/shanxia2.0/backend/app/api/public.py", "source_location": "L223"}, {"id": "api_public_rationale_256", "label": "\u83b7\u53d6\u5f53\u524d\u7528\u6237\u83dc\u5355\u6743\u9650\u6807\u8bc6\uff08sys_menu.perms\uff0c\u7Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_zlwu_work_00code_shanxia2_0_backend_app_schemas_pl_base_data_py", "label": "base_data.py", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L1"}, {"id": "pl_base_data_carrierbase", "label": "CarrierBase", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L19"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "pl_base_data_carrierqualificationbase", "label": "CarrierQualificationBase", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L27"}, {"id": "pl_base_data_carriercreate", "label": "CarrierCreate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L45"}, {"id": "pl_base_data_carriercreate_validate_qualification", "label": ".validate_qualification()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L56"}, {"id": "pl_base_data_carrierupdate", "label": "CarrierUpdate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L66"}, {"id": "pl_base_data_carrierupdate_validate_qualification_patch", "label": ".validate_qualification_patch()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L88"}, {"id": "pl_base_data_carrierauditreject", "label": "CarrierAuditReject", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L109"}, {"id": "pl_base_data_carrierread", "label": "CarrierRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L115"}, {"id": "pl_base_data_carrier_to_read", "label": "carrier_to_read()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L134"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L134"}, {"id": "pl_base_data_vehiclepersonnelrow", "label": "VehiclePersonnelRow", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L170"}, {"id": "pl_base_data_certrow", "label": "CertRow", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L181"}, {"id": "pl_base_data_certread", "label": "CertRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L196"}, {"id": "pl_base_data_vehiclebase", "label": "VehicleBase", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L212"}, {"id": "pl_base_data_vehiclecreate", "label": "VehicleCreate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L225"}, {"id": "pl_base_data_vehicleupdate", "label": "VehicleUpdate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L231"}, {"id": "pl_base_data_vehicleread", "label": "VehicleRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L245"}, {"id": "pl_base_data_vehicledetailread", "label": "VehicleDetailRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L260"}, {"id": "pl_base_data_personnelbase", "label": "PersonnelBase", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L271"}, {"id": "pl_base_data_personnelcreate", "label": "PersonnelCreate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L292"}, {"id": "pl_base_data_personnelupdate", "label": "PersonnelUpdate", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L297"}, {"id": "pl_base_data_personnelread", "label": "PersonnelRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/schemas/pl/base_data.py", "source_location": "L312"}, {"id": "pl_base_data_personneldetailread", "label": "PersonnelDetailRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_zlwu_work_00code_shanxia2_0_backend_app_services_pl_cert_service_py", "label": "pl_cert_service.py", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L1"}, {"id": "services_pl_cert_service_list_owner_certs", "label": "list_owner_certs()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L14"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L14"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L14"}, {"id": "plcert", "label": "PlCert", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L14"}, {"id": "services_pl_cert_service_list_owner_certs_batch", "label": "list_owner_certs_batch()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L30"}, {"id": "services_pl_cert_service_certs_to_read", "label": "certs_to_read()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L52"}, {"id": "certread", "label": "CertRead", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L52"}, {"id": "services_pl_cert_service_normalize_cert_row", "label": "_normalize_cert_row()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L74"}, {"id": "certrow", "label": "CertRow", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L74"}, {"id": "services_pl_cert_service_save_owner_certs", "label": "save_owner_certs()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L80"}, {"id": "services_pl_cert_service_nearest_expire_date", "label": "nearest_expire_date()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L138"}, {"id": "date", "label": "date", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L138"}, {"id": "services_pl_cert_service_resolve_owner_label", "label": "_resolve_owner_label()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L156"}, {"id": "services_pl_cert_service_scan_cert_expiry", "label": "scan_cert_expiry()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L183"}, {"id": "int", "label": "int", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L183"}, {"id": "services_pl_cert_service_rationale_90", "label": "\u6309 cert_id upsert\uff1b\u672a\u51fa\u73b0\u5728\u5217\u8868\u4e2d\u7684\u65e7\u8bc1\u8f6f\u5220\u3002", "file_type": "rationale", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L90"}, {"id": "services_pl_cert_service_rationale_184", "label": "\u626b\u63cf pl_cert \u751f\u6210\u5230\u671f\u63d0\u9192\uff0c\u8fd4\u56de\u65b0\u5efa\u6761\u6570\u3002", "file_type": "rationale", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L184"}], "edges": [{"source": "users_zlwu_work_00code_shanxia2_0_backend_app_services_pl_cert_service_py", "target": "datetime", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L4", "weight": 1.0}, {"source": "users_zlwu_work_00code_shanxia2_0_backend_app_services_pl_cert_service_py", "target": "typing", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L5", "weight": 1.0}, {"source": "users_zlwu_work_00code_shanxia2_0_backend_app_services_pl_cert_service_py", "target": "sqlalchemy_orm", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/services/pl_cert_service.py", "source_location": "L7", "weight": 1.0}, {"source": "users_zlwu_work_00code_shanxia2_0_backend_app_services_pl_cert_serviLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_zlwu_work_00code_shanxia2_0_backend_app_crud_user_py", "label": "user.py", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L1"}, {"id": "crud_user_hash_password", "label": "_hash_password()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L19"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L19"}, {"id": "crud_user_usercrudcompat", "label": "_UserCRUDCompat", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L23"}, {"id": "crud_user_usercrudcompat_get_by_user_no", "label": ".get_by_user_no()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L24"}, {"id": "session", "label": "Session", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L24"}, {"id": "sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L24"}, {"id": "crud_user_usercrudcompat_get_by_user_no_for_web_login", "label": ".get_by_user_no_for_web_login()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L35"}, {"id": "crud_user_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L54"}, {"id": "any", "label": "Any", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L54"}, {"id": "crud_user_list_users", "label": "list_users()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L75"}, {"id": "int", "label": "int", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L75"}, {"id": "crud_user_get_user", "label": "get_user()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L126"}, {"id": "crud_user_list_post_ids_for_user", "label": "list_post_ids_for_user()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L134"}, {"id": "crud_user_set_user_post_ids_only", "label": "set_user_post_ids_only()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L144"}, {"id": "crud_user_list_user_ids_bound_to_post", "label": "list_user_ids_bound_to_post()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L176"}, {"id": "crud_user_sync_post_user_bindings", "label": "sync_post_user_bindings()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L191"}, {"id": "crud_user_get_user_with_relations", "label": "get_user_with_relations()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L219"}, {"id": "crud_user_user_no_exists", "label": "user_no_exists()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L244"}, {"id": "bool", "label": "bool", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L244"}, {"id": "crud_user_replace_associations", "label": "_replace_associations()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L253"}, {"id": "crud_user_create_user", "label": "create_user()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L304"}, {"id": "crud_user_update_user", "label": "update_user()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L363"}, {"id": "crud_user_soft_delete_user", "label": "soft_delete_user()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L418"}, {"id": "crud_user_change_password", "label": "change_password()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L429"}, {"id": "crud_user_reset_password", "label": "reset_password()", "file_type": "code", "source_file": "/Users/zlwu/work/00code/shanxia2.0/backend/app/crud/user.py", "source_location": "L449"}, {"id": "crud_user_total_pages", "label": "total_pages()", "filLine truncated
+1 -1
View File
@@ -1 +1 @@
{"/Users/zlwu/work/00code/shanxia2.0/backend/start-prod.sh":{"size":7357,"mtime_ns":1782639355476060453,"hash":"ca89869446be74a2bf2367b3b28f448580220859a39a84ad9613ac5fe35a8433"},"/Users/zlwu/work/00code/shanxia2.0/backend/start.sh":{"size":9548,"mtime_ns":1780114661446983244,"hash":"4d632863e8a0cd81194b491d83a0218a4157435ae812dec76a6f6197b4d48e57"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/__init__.py":{"size":21,"mtime_ns":1780113982281973984,"hash":"60a04ff08fd97084e83ea809fd13feda6d2848be20ebf309e31fc1dad7523230"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/main.py":{"size":6280,"mtime_ns":1782790852770448643,"hash":"8f9da799977bee7134d87a26ff8434ac5ef8eabb0b7368dd537eee49ad7fd00b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/tasks/__init__.py":{"size":2207,"mtime_ns":1783208067881286091,"hash":"313e6da0e91d743ce891dd283458c79b50b24c4d909dc96ca7b3fd9d2bfa5013"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/auth.py":{"size":7457,"mtime_ns":1782790841500516545,"hash":"34bac56e1c2cb6215f4b5fa2dc32d77d4b4abca51428819eebf4afd269cc51cf"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto.py":{"size":1870,"mtime_ns":1780108930724444498,"hash":"c04b748aea86890a5971f749523c7b17dbad1ddd6f9f7f07a5679d159c984e33"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/login_crypto.py":{"size":3858,"mtime_ns":1780108930725155710,"hash":"b82d51afabf2293a9cb1fb2e5f994c383948e7f47ea95fe674686b4f3f3342b1"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/config.py":{"size":6716,"mtime_ns":1783761682571576393,"hash":"bbe64081c9790941eb2fa8f9c18ee39daf151068b3503f1fdb74c2cb9f7b5b45"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_pay.py":{"size":23585,"mtime_ns":1780108930725768130,"hash":"3d52265ce65d21e7103f94afa1e8547aee0823b5ea6d65c50317436ac81fb4fc"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_request_log_middleware.py":{"size":11971,"mtime_ns":1782701669198208175,"hash":"0b84c32828939e6102bb3647691fa8f04b1f68e0e0e9f28127374cc44e19a11c"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/database.py":{"size":1510,"mtime_ns":1782790847265601586,"hash":"8bc9c8ae62e2be2c6920036582ba448dfcd1711c41cebb62274ff6bc6ee14b0b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/security.py":{"size":728,"mtime_ns":1780108930725470004,"hash":"df0f01115064f7b8de1c81dbe9a6db39360c236610b68c33b3234a51d7f0025b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/request_payload.py":{"size":2842,"mtime_ns":1780108930725350836,"hash":"e9937151530ab1417ef297aef59111977725cf90be2a8fa76c00a0618789aba0"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/__init__.py":{"size":61,"mtime_ns":1780108930724312414,"hash":"3dd1842ee59b0c804176b03b4b8a323bd4a252b7feb1bbc32db64f3a8928570e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/response.py":{"size":1824,"mtime_ns":1780108930725412462,"hash":"f1739352d65ea8287d76e282a59553aa8d63c97e35764c64ac378aa5bd9c347e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/menu_guard.py":{"size":1611,"mtime_ns":1780108930725223002,"hash":"3e26077288c3620a4780038b891a326206b45bffe00aca545bdae30172487235"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/db_collation.py":{"size":548,"mtime_ns":1780108930725025043,"hash":"0c680e25a18244ca839a7de6ed1f4313b33bc8da118d89c463aee1b6af00c6f9"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/context.py":{"size":421,"mtime_ns":1780108930724824458,"hash":"83a10aee67162374993c10a30bf8bb8bd9c4b35cf48f42c832415ccebd91660f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/utils.py":{"size":1498,"mtime_ns":1780108930725607296,"hash":"09323693661c1d4560458b86a954128ccff82bbaf6522da0b44f24da99ddf9ea"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/storage.py":{"size":14141,"mtime_ns":1782855136810943216,"hash":"3ae2c413c10898a8adb3d6773870bafbfbc18c739c10e0e8b4f765b4b5ca6c08"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/order_status_compat.py":{"size":2828,"mtime_ns":1780108930725284669,"hash":"5349e5a0745ee6734c4a995337779307adefc46f453906171988a77de2081540"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/exceptions.py":{"size":4946,"mtime_ns":1780108930725084335,"hash":"79c997d964bca1a4f12f2b92fb1f181fdb9e2b3cf72eae39f4cc164d23794fd7"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/data_scope.py":{"size":8043,"mtime_ns":1782648925694296304,"hash":"626dff86937e5cacec634ecbc61cd53d3763d760223a1d4ec7cd11f64e59a220"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/admin_request_json.py":{"size":2669,"mtime_ns":1780108930724378914,"hash":"4f68b3cf84291e7bddad6ecf4bb4d29ca5e1ec246a9f7f9c4cf5909d0ec1174a"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto_middleware.py":{"size":10876,"mtime_ns":1782790001926627098,"hash":"b39f128b6612589ea6ac5babd30752e9585b3af07b82bb1ad53c9e3c0d90816f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_message.py":{"size":11194,"mtime_ns":1780108930725684255,"hash":"5086070deb14d99d1a69e419b2299ec4Line truncated
{"/Users/zlwu/work/00code/shanxia2.0/backend/start-prod.sh":{"size":7357,"mtime_ns":1782639355476060453,"hash":"ca89869446be74a2bf2367b3b28f448580220859a39a84ad9613ac5fe35a8433"},"/Users/zlwu/work/00code/shanxia2.0/backend/start.sh":{"size":9548,"mtime_ns":1780114661446983244,"hash":"4d632863e8a0cd81194b491d83a0218a4157435ae812dec76a6f6197b4d48e57"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/__init__.py":{"size":21,"mtime_ns":1780113982281973984,"hash":"60a04ff08fd97084e83ea809fd13feda6d2848be20ebf309e31fc1dad7523230"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/main.py":{"size":6280,"mtime_ns":1782790852770448643,"hash":"8f9da799977bee7134d87a26ff8434ac5ef8eabb0b7368dd537eee49ad7fd00b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/tasks/__init__.py":{"size":2207,"mtime_ns":1783208067881286091,"hash":"313e6da0e91d743ce891dd283458c79b50b24c4d909dc96ca7b3fd9d2bfa5013"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/auth.py":{"size":7457,"mtime_ns":1782790841500516545,"hash":"34bac56e1c2cb6215f4b5fa2dc32d77d4b4abca51428819eebf4afd269cc51cf"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto.py":{"size":1870,"mtime_ns":1780108930724444498,"hash":"c04b748aea86890a5971f749523c7b17dbad1ddd6f9f7f07a5679d159c984e33"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/login_crypto.py":{"size":3858,"mtime_ns":1780108930725155710,"hash":"b82d51afabf2293a9cb1fb2e5f994c383948e7f47ea95fe674686b4f3f3342b1"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/config.py":{"size":6716,"mtime_ns":1783761682571576393,"hash":"bbe64081c9790941eb2fa8f9c18ee39daf151068b3503f1fdb74c2cb9f7b5b45"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_pay.py":{"size":23585,"mtime_ns":1780108930725768130,"hash":"3d52265ce65d21e7103f94afa1e8547aee0823b5ea6d65c50317436ac81fb4fc"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_request_log_middleware.py":{"size":11971,"mtime_ns":1782701669198208175,"hash":"0b84c32828939e6102bb3647691fa8f04b1f68e0e0e9f28127374cc44e19a11c"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/database.py":{"size":1510,"mtime_ns":1782790847265601586,"hash":"8bc9c8ae62e2be2c6920036582ba448dfcd1711c41cebb62274ff6bc6ee14b0b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/security.py":{"size":728,"mtime_ns":1780108930725470004,"hash":"df0f01115064f7b8de1c81dbe9a6db39360c236610b68c33b3234a51d7f0025b"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/request_payload.py":{"size":2842,"mtime_ns":1780108930725350836,"hash":"e9937151530ab1417ef297aef59111977725cf90be2a8fa76c00a0618789aba0"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/__init__.py":{"size":61,"mtime_ns":1780108930724312414,"hash":"3dd1842ee59b0c804176b03b4b8a323bd4a252b7feb1bbc32db64f3a8928570e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/response.py":{"size":1824,"mtime_ns":1780108930725412462,"hash":"f1739352d65ea8287d76e282a59553aa8d63c97e35764c64ac378aa5bd9c347e"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/menu_guard.py":{"size":1611,"mtime_ns":1780108930725223002,"hash":"3e26077288c3620a4780038b891a326206b45bffe00aca545bdae30172487235"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/db_collation.py":{"size":548,"mtime_ns":1780108930725025043,"hash":"0c680e25a18244ca839a7de6ed1f4313b33bc8da118d89c463aee1b6af00c6f9"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/context.py":{"size":421,"mtime_ns":1780108930724824458,"hash":"83a10aee67162374993c10a30bf8bb8bd9c4b35cf48f42c832415ccebd91660f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/utils.py":{"size":1498,"mtime_ns":1780108930725607296,"hash":"09323693661c1d4560458b86a954128ccff82bbaf6522da0b44f24da99ddf9ea"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/storage.py":{"size":14141,"mtime_ns":1782855136810943216,"hash":"3ae2c413c10898a8adb3d6773870bafbfbc18c739c10e0e8b4f765b4b5ca6c08"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/order_status_compat.py":{"size":2828,"mtime_ns":1780108930725284669,"hash":"5349e5a0745ee6734c4a995337779307adefc46f453906171988a77de2081540"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/exceptions.py":{"size":4946,"mtime_ns":1780108930725084335,"hash":"79c997d964bca1a4f12f2b92fb1f181fdb9e2b3cf72eae39f4cc164d23794fd7"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/data_scope.py":{"size":8043,"mtime_ns":1782648925694296304,"hash":"626dff86937e5cacec634ecbc61cd53d3763d760223a1d4ec7cd11f64e59a220"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/admin_request_json.py":{"size":2669,"mtime_ns":1780108930724378914,"hash":"4f68b3cf84291e7bddad6ecf4bb4d29ca5e1ec246a9f7f9c4cf5909d0ec1174a"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/api_crypto_middleware.py":{"size":10876,"mtime_ns":1782790001926627098,"hash":"b39f128b6612589ea6ac5babd30752e9585b3af07b82bb1ad53c9e3c0d90816f"},"/Users/zlwu/work/00code/shanxia2.0/backend/app/core/wechat_message.py":{"size":11194,"mtime_ns":1780108930725684255,"hash":"5086070deb14d99d1a69e419b2299ec4Line truncated
+246825 -242932
View File
File diff suppressed because it is too large. Load diff
@@ -1,3 +0,0 @@
-- 运输联动贡献量(吨),用于地磅月计划量累加/回减
ALTER TABLE pl_transport_db_link
ADD COLUMN contributed_qty DECIMAL(15,3) NULL COMMENT '本次联动贡献量(吨)' AFTER db_inventory_id;
@@ -1,19 +0,0 @@
-- 修复商机 follow_count 与跟进记录数不一致(历史数据回填)
-- 原因:创建跟进时 recalc 发生在 flush 之前,导致冗余字段长期少 1
UPDATE crm_opportunity o
LEFT JOIN (
SELECT opportunity_id, COUNT(*) AS cnt
FROM crm_opportunity_follow
WHERE del_flag = 0
GROUP BY opportunity_id
) f ON f.opportunity_id = o.id
SET o.follow_count = IFNULL(f.cnt, 0),
o.last_time = (
SELECT MAX(COALESCE(f2.follow_time, f2.create_time))
FROM crm_opportunity_follow f2
WHERE f2.opportunity_id = o.id
AND f2.del_flag = 0
)
WHERE o.del_flag = 0
AND IFNULL(o.follow_count, 0) <> IFNULL(f.cnt, 0);
@@ -1,24 +0,0 @@
-- pl_personnel 增加人员归属:self-山峡 carrier-非山峡
SET @col_exists := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'pl_personnel'
AND COLUMN_NAME = 'personnel_affiliation'
);
SET @ddl := IF(
@col_exists = 0,
'ALTER TABLE `pl_personnel`
ADD COLUMN `personnel_affiliation` varchar(20) NOT NULL DEFAULT ''self''
COMMENT ''人员归属 self-山峡 carrier-非山峡''
AFTER `personnel_type`',
'SELECT ''personnel_affiliation already exists'' AS msg'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
UPDATE `pl_personnel`
SET `personnel_affiliation` = 'self'
WHERE `personnel_affiliation` IS NULL OR `personnel_affiliation` = '';
@@ -1,52 +0,0 @@
-- pl_personnel 增加人员类型;历史数据按车辆关联推断
-- 可重复执行(列已存在则跳过加列,UPDATE 可重复跑)
SET @col_exists := (
SELECT COUNT(*)
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'pl_personnel'
AND COLUMN_NAME = 'personnel_type'
);
SET @ddl := IF(
@col_exists = 0,
'ALTER TABLE `pl_personnel`
ADD COLUMN `personnel_type` varchar(20) NOT NULL DEFAULT ''both''
COMMENT ''人员类型 driver-驾驶员 escort-押运员 both-驾驶员兼押运员''
AFTER `id_card_no`',
'SELECT 1'
);
PREPARE stmt FROM @ddl;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- 仅有 driver 关联
UPDATE pl_personnel p
SET p.personnel_type = 'driver'
WHERE p.del_flag = 0
AND (p.personnel_type IS NULL OR p.personnel_type = '' OR p.personnel_type = 'both')
AND EXISTS (
SELECT 1 FROM pl_vehicle_personnel vp
WHERE vp.personnel_id = p.id AND vp.del_flag = 0 AND vp.role = 'driver'
)
AND NOT EXISTS (
SELECT 1 FROM pl_vehicle_personnel vp
WHERE vp.personnel_id = p.id AND vp.del_flag = 0 AND vp.role = 'escort'
);
-- 仅有 escort 关联
UPDATE pl_personnel p
SET p.personnel_type = 'escort'
WHERE p.del_flag = 0
AND (p.personnel_type IS NULL OR p.personnel_type = '' OR p.personnel_type = 'both')
AND EXISTS (
SELECT 1 FROM pl_vehicle_personnel vp
WHERE vp.personnel_id = p.id AND vp.del_flag = 0 AND vp.role = 'escort'
)
AND NOT EXISTS (
SELECT 1 FROM pl_vehicle_personnel vp
WHERE vp.personnel_id = p.id AND vp.del_flag = 0 AND vp.role = 'driver'
);
-- 同时有 driver + escort 或无关联保持 both(默认)
-873
View File
@@ -1,873 +0,0 @@
-- =============================================================================
-- 运输计划管理模块 DDL
-- 生成时间: 2026-06-11
-- 说明: pl_ 前缀,所有计划相关表
-- =============================================================================
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- -----------------------------------------------------------------------------
-- 1. 基础数据:承运商、车辆、人员、证书
-- -----------------------------------------------------------------------------
-- ----------------------------
-- Table structure for pl_carrier (承运商表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_carrier`;
CREATE TABLE `pl_carrier` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`carrier_name` varchar(200) NOT NULL COMMENT '承运商名称',
`contact_name` varchar(100) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) DEFAULT NULL COMMENT '联系电话',
`status` char(1) NOT NULL DEFAULT '1' COMMENT '合作状态 1-合作中 0-已终止',
`business_license_urls` varchar(2000) DEFAULT NULL COMMENT '营业执照附件URL,逗号分隔',
`road_transport_license_urls` varchar(2000) DEFAULT NULL COMMENT '道路经营许可证附件URL,逗号分隔',
`transport_agreement_urls` varchar(2000) DEFAULT NULL COMMENT '运输协议附件URL,逗号分隔',
`transport_agreement_expire_date` date DEFAULT NULL COMMENT '运输协议有效期',
`audit_status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '审核状态 pending-待审核 approved-已通过 rejected-已驳回',
`audit_by` varchar(64) DEFAULT NULL COMMENT '审核人id',
`audit_time` datetime DEFAULT NULL COMMENT '审核时间',
`audit_remark` varchar(512) DEFAULT NULL COMMENT '审核备注(驳回原因等)',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='承运商表';
-- ----------------------------
-- Table structure for pl_vehicle (车辆表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle`;
CREATE TABLE `pl_vehicle` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`vehicle_type` varchar(20) NOT NULL COMMENT '车辆类型 self-自有 carrier-承运商',
`carrier_id` varchar(64) DEFAULT NULL COMMENT '承运商ID(类型为承运商时必填)',
`carrier_name` varchar(200) DEFAULT NULL COMMENT '承运商名称(冗余)',
`license_plate` varchar(20) NOT NULL COMMENT '车牌号',
`load_capacity` decimal(10,2) DEFAULT NULL COMMENT '载重(吨)',
`vehicle_status` varchar(20) NOT NULL DEFAULT 'available' COMMENT '车辆状态 available-可用 maintaining-维修中 scrapped-报废',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_license_plate` (`license_plate`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_vehicle_type` (`vehicle_type`),
KEY `idx_carrier_id` (`carrier_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆表';
-- ----------------------------
-- Table structure for pl_personnel (人员表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_personnel`;
CREATE TABLE `pl_personnel` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`personnel_name` varchar(100) NOT NULL COMMENT '姓名',
`phone_no` varchar(32) DEFAULT NULL COMMENT '手机号(非必填)',
`age` int(11) DEFAULT NULL COMMENT '年龄',
`id_card_no` varchar(32) DEFAULT NULL COMMENT '身份证号',
`personnel_type` varchar(20) NOT NULL DEFAULT 'both' COMMENT '人员类型 driver-驾驶员 escort-押运员 both-驾驶员兼押运员',
`personnel_affiliation` varchar(20) NOT NULL DEFAULT 'self' COMMENT '人员归属 self-山峡 carrier-非山峡',
`status` char(1) NOT NULL DEFAULT '1' COMMENT '状态 1-在职 0-停用',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_phone` (`phone_no`),
KEY `idx_personnel_name` (`personnel_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运输计划-人员表';
-- ----------------------------
-- Table structure for pl_cert (证书表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_cert`;
CREATE TABLE `pl_cert` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`owner_type` varchar(20) NOT NULL COMMENT '归属类型 vehicle-车辆 personnel-人员',
`owner_id` varchar(64) NOT NULL COMMENT '归属主体ID',
`vehicle_part` varchar(20) DEFAULT NULL COMMENT '车辆部位 head-主车 trailer-挂车,人员证书为空',
`cert_name` varchar(100) NOT NULL COMMENT '证书名称',
`cert_no` varchar(64) DEFAULT NULL COMMENT '证号',
`expire_date` date DEFAULT NULL COMMENT '有效期',
`remind_days` int(11) NOT NULL DEFAULT 30 COMMENT '提前提醒天数',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL(逗号分隔)',
`status` varchar(20) NOT NULL DEFAULT 'valid' COMMENT '状态 valid-有效 expired-已过期 revoked-已作废',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_owner` (`owner_type`, `owner_id`),
KEY `idx_expire_date` (`expire_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运输计划-证书表';
-- ----------------------------
-- Table structure for pl_vehicle_personnel (车辆-人员关联表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_personnel`;
CREATE TABLE `pl_vehicle_personnel` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`vehicle_id` varchar(64) NOT NULL COMMENT '车辆ID',
`personnel_id` varchar(64) NOT NULL COMMENT '人员ID',
`role` varchar(20) NOT NULL DEFAULT 'driver' COMMENT '角色 driver-司机 escort-押运员',
`is_default` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否默认司机 0-否 1-是',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '关联备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_vehicle_id` (`vehicle_id`),
KEY `idx_personnel_id` (`personnel_id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_vehicle_role` (`vehicle_id`, `role`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆-人员关联表';
-- -----------------------------------------------------------------------------
-- 2. 计划管理:计划主表、产品明细、变更记录
-- -----------------------------------------------------------------------------
-- ----------------------------
-- Table structure for pl_plan (计划主表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_plan`;
CREATE TABLE `pl_plan` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`plan_no` varchar(32) NOT NULL COMMENT '计划订单编号 SXDDHYYYYMMDD######',
`plan_date` date NOT NULL COMMENT '计划日期',
`belongs_company` varchar(20) NOT NULL COMMENT '归属公司 shanxia-安庆山峡 yundong-安徽云栋',
`plan_type` varchar(20) NOT NULL COMMENT '单据类型 direct-直销单 inbound-入库单 outbound-出库单',
`follow_status` varchar(30) NOT NULL DEFAULT 'draft' COMMENT '跟进状态',
`transport_status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '运输安排状态 pending-待安排 arranged-已安排',
`archive_status` varchar(20) NOT NULL DEFAULT 'unarchived' COMMENT '归档状态 unarchived-未归档 archived-已归档',
`complete_status` varchar(10) NOT NULL DEFAULT 'no' COMMENT '完成状态 yes-是 no-否',
`contract_id` varchar(64) DEFAULT NULL COMMENT 'CRM合同ID',
`contract_no` varchar(50) DEFAULT NULL COMMENT '合同编号',
`supplier_id` varchar(64) DEFAULT NULL COMMENT '供应商ID',
`supplier_name` varchar(200) DEFAULT NULL COMMENT '供应商名称',
`destination_id` varchar(64) DEFAULT NULL COMMENT '目的地ID',
`destination_name` varchar(200) DEFAULT NULL COMMENT '目的地名称',
`customer_id` varchar(64) DEFAULT NULL COMMENT '客户ID',
`customer_name` varchar(200) DEFAULT NULL COMMENT '客户名称',
`contact_name` varchar(100) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) DEFAULT NULL COMMENT '联系电话',
`party_a` varchar(200) DEFAULT NULL COMMENT '甲方',
`party_b` varchar(200) DEFAULT NULL COMMENT '乙方',
`contract_start_date` date DEFAULT NULL COMMENT '合同开始日期',
`contract_end_date` date DEFAULT NULL COMMENT '合同结束日期',
`delivery_method` varchar(20) DEFAULT NULL COMMENT '送货方式 self_pick-山峡自提 one_ticket-一票制 customer_pick-客户自提',
`settlement_method` varchar(50) DEFAULT NULL COMMENT '结算方式',
`has_freight` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否有运输费用 0-否 1-是',
`transport_id` varchar(64) DEFAULT NULL COMMENT '运输ID',
`transport_no` varchar(32) DEFAULT NULL COMMENT '运输编号',
`vehicle_id` varchar(64) DEFAULT NULL COMMENT '车辆ID',
`license_plate` varchar(20) DEFAULT NULL COMMENT '车牌号',
`trailer_no` varchar(20) DEFAULT NULL COMMENT '挂车号(安排运输时快照)',
`driver_id` varchar(64) DEFAULT NULL COMMENT '司机ID',
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机姓名',
`personnel_summary` varchar(500) DEFAULT NULL COMMENT '关联人员摘要(安排运输时快照)',
`resource_snapshot` text COMMENT '车辆/人员/证件整包快照 JSON',
`total_amount` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT '计划总金额',
`freight_amount` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT '运费合计',
`notify_message` text COMMENT '通知信息(标准模板)',
`slip_template_content` longtext COMMENT '入库单打印模板内容(富文本HTML)',
`delivery_slip_template_content` longtext COMMENT '送(提)货单打印模板内容(富文本HTML)',
`subpack_slip_template_content` longtext COMMENT '分装单打印模板内容(富文本HTML)',
`subpack_slip_no` varchar(32) DEFAULT NULL COMMENT '分装单号 NO:SXFZ-YYYY-MM-DD-序号',
`follow_user_id` varchar(64) DEFAULT NULL COMMENT '跟进人ID',
`follow_user_name` varchar(100) DEFAULT NULL COMMENT '跟进人姓名',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_plan_no` (`plan_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_plan_type` (`plan_type`),
KEY `idx_follow_status` (`follow_status`),
KEY `idx_plan_date` (`plan_date`),
KEY `idx_contract_id` (`contract_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计划主表';
-- ----------------------------
-- Table structure for pl_plan_product (计划产品明细表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_plan_product`;
CREATE TABLE `pl_plan_product` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`plan_id` varchar(64) NOT NULL COMMENT '计划ID',
`product_id` varchar(64) NOT NULL COMMENT '产品ID',
`product_no` varchar(50) NOT NULL COMMENT '产品编号',
`product_name` varchar(200) NOT NULL COMMENT '产品名称',
`model` varchar(100) DEFAULT NULL COMMENT '规格型号',
`unit` varchar(20) NOT NULL DEFAULT '吨' COMMENT '单位',
`is_explosive` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否易制爆 0-否 1-是',
`is_toxic` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否易制毒 0-否 1-是',
`purchase_cert_url` varchar(500) DEFAULT NULL COMMENT '购买证URL',
`transport_cert_url` varchar(500) DEFAULT NULL COMMENT '运输证URL',
`legal_use_cert_url` varchar(500) DEFAULT NULL COMMENT '合法使用证明URL',
`inbound_estimate_qty` decimal(15,3) DEFAULT NULL COMMENT '入库预估数',
`inbound_qty` decimal(15,3) DEFAULT NULL COMMENT '入库数',
`inbound_price` decimal(15,4) DEFAULT NULL COMMENT '入库价',
`inbound_amount` decimal(15,2) DEFAULT NULL COMMENT '入库金额',
`outbound_estimate_qty` decimal(15,3) DEFAULT NULL COMMENT '出库预估数',
`outbound_qty` decimal(15,3) DEFAULT NULL COMMENT '出库数',
`outbound_price` decimal(15,4) DEFAULT NULL COMMENT '出库单价',
`outbound_amount` decimal(15,2) DEFAULT NULL COMMENT '出库金额',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_plan_id` (`plan_id`),
KEY `idx_product_id` (`product_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计划产品明细表';
-- ----------------------------
-- Table structure for pl_plan_change (计划变更记录表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_plan_change`;
CREATE TABLE `pl_plan_change` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`plan_id` varchar(64) NOT NULL COMMENT '计划ID',
`change_type` varchar(30) NOT NULL COMMENT '变更类型',
`change_content` text COMMENT '变更内容',
`change_user_id` varchar(64) DEFAULT NULL COMMENT '变更人ID',
`change_user_name` varchar(100) DEFAULT NULL COMMENT '变更人姓名',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_plan_id` (`plan_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计划变更记录表';
-- -----------------------------------------------------------------------------
-- 3. 运输管理:运输表、审批记录
-- -----------------------------------------------------------------------------
-- ----------------------------
-- Table structure for pl_transport (运输表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_transport`;
CREATE TABLE `pl_transport` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`transport_no` varchar(32) NOT NULL COMMENT '运输编号 SXYS######',
`vehicle_id` varchar(64) DEFAULT NULL COMMENT '车辆ID',
`license_plate` varchar(20) DEFAULT NULL COMMENT '车牌号',
`trailer_no` varchar(20) DEFAULT NULL COMMENT '挂车号(安排运输时快照)',
`driver_id` varchar(64) DEFAULT NULL COMMENT '司机ID',
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机姓名',
`driver_phone` varchar(32) DEFAULT NULL COMMENT '司机电话',
`resource_snapshot` text COMMENT '车辆/人员/证件整包快照 JSON',
`carrier_id` varchar(64) DEFAULT NULL COMMENT '承运商ID',
`carrier_name` varchar(200) DEFAULT NULL COMMENT '承运商名称',
`transport_medium` varchar(100) DEFAULT NULL COMMENT '运输介质',
`start_point` varchar(200) DEFAULT NULL COMMENT '运输起点',
`end_point` varchar(200) DEFAULT NULL COMMENT '运输终点',
`distance_km` decimal(10,2) DEFAULT NULL COMMENT '运输公里数',
`unit` varchar(20) DEFAULT NULL COMMENT '计量单位 吨/趟',
`freight_price` decimal(15,4) DEFAULT NULL COMMENT '运输单价',
`freight_amount` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT '运输费用',
`freight_type` varchar(20) NOT NULL DEFAULT 'by_weight' COMMENT '运费计算方式 by_weight-按重量 by_trip-按趟次',
`has_invoice` smallint(6) NOT NULL DEFAULT 0 COMMENT '是否开票 0-否 1-是',
`qr_code` varchar(500) DEFAULT NULL COMMENT '二维码内容',
`qr_expire_date` date DEFAULT NULL COMMENT '二维码有效期',
`driver_access_token` varchar(64) DEFAULT NULL COMMENT '司机免登录访问令牌',
`transport_status` varchar(20) NOT NULL DEFAULT 'draft' COMMENT '运输状态 draft-草稿 pending-待执行 executing-执行中 completed-已完成 cancelled-已取消',
`approval_status` varchar(20) NOT NULL DEFAULT 'none' COMMENT '审批状态 none-无需 pending-审批中 approved-已通过 rejected-已拒绝',
`feedback_time` datetime DEFAULT NULL COMMENT '回传时间',
`feedback_qty` decimal(15,3) DEFAULT NULL COMMENT '回传数量',
`feedback_images` text COMMENT '回传图片URLs(JSON数组)',
`feedback_remark` varchar(500) DEFAULT NULL COMMENT '回传备注',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_transport_no` (`transport_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_transport_status` (`transport_status`),
KEY `idx_vehicle_id` (`vehicle_id`),
KEY `idx_driver_id` (`driver_id`),
UNIQUE KEY `uk_pl_transport_driver_token` (`driver_access_token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运输表';
-- ----------------------------
-- Table structure for pl_transport_db_link (运输-地磅出入库关联)
-- ----------------------------
DROP TABLE IF EXISTS `pl_transport_db_link`;
CREATE TABLE `pl_transport_db_link` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`transport_id` varchar(64) NOT NULL COMMENT '运输单ID',
`plan_id` varchar(64) NOT NULL COMMENT '运输计划ID',
`plan_product_id` varchar(64) NOT NULL COMMENT '计划产品行ID',
`db_purchase_plan_id` varchar(64) NOT NULL COMMENT '地磅计划ID',
`db_inventory_id` varchar(64) NOT NULL COMMENT '出入库单ID',
`contributed_qty` decimal(15,3) DEFAULT NULL COMMENT '本次联动贡献量(吨)',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_pl_tdb_link_transport` (`transport_id`),
KEY `idx_pl_tdb_link_plan` (`plan_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运输-地磅出入库关联';
-- ----------------------------
-- Table structure for pl_plan_transport (计划-运输关联表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_plan_transport`;
CREATE TABLE `pl_plan_transport` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`plan_id` varchar(64) NOT NULL COMMENT '计划ID',
`transport_id` varchar(64) NOT NULL COMMENT '运输ID',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_plan_id` (`plan_id`),
KEY `idx_transport_id` (`transport_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='计划-运输关联表';
-- ----------------------------
-- Table structure for pl_transport_approval (运输审批记录表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_transport_approval`;
CREATE TABLE `pl_transport_approval` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`transport_id` varchar(64) NOT NULL COMMENT '运输ID',
`approver_id` varchar(64) NOT NULL COMMENT '审批人ID',
`approver_name` varchar(100) NOT NULL COMMENT '审批人姓名',
`approval_order` int(11) NOT NULL COMMENT '审批顺序',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '审批状态 pending-待审批 approved-已通过 rejected-已拒绝',
`comment` varchar(500) DEFAULT NULL COMMENT '审批意见',
`approval_time` datetime DEFAULT NULL COMMENT '审批时间',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_transport_id` (`transport_id`),
KEY `idx_approver_id` (`approver_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运输审批记录表';
-- -----------------------------------------------------------------------------
-- 4. 运费结算
-- -----------------------------------------------------------------------------
-- ----------------------------
-- Table structure for pl_freight_settlement (运费结算表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_freight_settlement`;
CREATE TABLE `pl_freight_settlement` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`settlement_no` varchar(32) NOT NULL COMMENT '结算单编号',
`total_freight` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT '运费合计',
`invoice_amount` decimal(15,2) DEFAULT NULL COMMENT '发票金额',
`invoice_no` varchar(50) DEFAULT NULL COMMENT '发票号',
`invoice_date` date DEFAULT NULL COMMENT '开票日期',
`invoice_attachment_urls` text DEFAULT NULL COMMENT '发票附件URLs,逗号分隔',
`settlement_status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '结算状态 pending-待提交 submitted-已提交 approved-审核通过 confirmed-已确认',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_settlement_no` (`settlement_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_settlement_status` (`settlement_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运费结算表';
-- ----------------------------
-- Table structure for pl_freight_settlement_transport (结算单-运输关联表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_freight_settlement_transport`;
CREATE TABLE `pl_freight_settlement_transport` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`settlement_id` varchar(64) NOT NULL COMMENT '结算单ID',
`transport_id` varchar(64) NOT NULL COMMENT '运输ID',
`freight_amount` decimal(15,2) NOT NULL COMMENT '运费金额',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_settlement_id` (`settlement_id`),
KEY `idx_transport_id` (`transport_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='结算单-运输关联表';
-- ----------------------------
-- Table structure for pl_freight_settlement_approval (运费结算审批记录)
-- ----------------------------
DROP TABLE IF EXISTS `pl_freight_settlement_approval`;
CREATE TABLE `pl_freight_settlement_approval` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`settlement_id` varchar(64) NOT NULL COMMENT '结算单ID',
`step` int(11) NOT NULL DEFAULT 1 COMMENT '步骤序号',
`step_name` varchar(50) DEFAULT NULL COMMENT '步骤名称',
`approver_id` varchar(64) NOT NULL COMMENT '审批人ID',
`approver_name` varchar(64) DEFAULT NULL COMMENT '审批人姓名',
`approval_type` varchar(20) NOT NULL DEFAULT 'sequential' COMMENT 'sequential/parallel/or',
`approval_result` varchar(20) NOT NULL DEFAULT 'pending' COMMENT 'pending/approved/rejected/skipped',
`approval_opinion` varchar(500) DEFAULT NULL COMMENT '审批意见',
`approval_time` datetime DEFAULT NULL COMMENT '审批时间',
`is_current` tinyint(4) NOT NULL DEFAULT 0 COMMENT '是否当前节点',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` tinyint(4) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_pl_fsa_settlement` (`settlement_id`, `del_flag`),
KEY `idx_pl_fsa_approver` (`approver_id`, `approval_result`, `is_current`, `del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运费结算审批记录';
-- ----------------------------
-- Table structure for pl_remittance_voucher (汇款凭证表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_remittance_voucher`;
CREATE TABLE `pl_remittance_voucher` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`settlement_id` varchar(64) NOT NULL COMMENT '结算单ID',
`voucher_no` varchar(32) DEFAULT NULL COMMENT '凭证编号',
`remittance_date` date DEFAULT NULL COMMENT '汇款日期',
`remittance_amount` decimal(15,2) DEFAULT NULL COMMENT '汇款金额',
`voucher_urls` text COMMENT '凭证文件URLs(JSON数组)',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_settlement_id` (`settlement_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='汇款凭证表';
-- -----------------------------------------------------------------------------
-- 5. 库存管理
-- -----------------------------------------------------------------------------
-- ----------------------------
-- Table structure for pl_inventory (库存表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_inventory`;
CREATE TABLE `pl_inventory` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`product_id` varchar(64) NOT NULL COMMENT '产品ID',
`product_no` varchar(50) NOT NULL COMMENT '产品编号',
`product_name` varchar(200) NOT NULL COMMENT '产品名称',
`model` varchar(100) DEFAULT NULL COMMENT '规格型号',
`unit` varchar(20) NOT NULL DEFAULT '吨' COMMENT '单位',
`stock_qty` decimal(15,3) NOT NULL DEFAULT 0.000 COMMENT '库存数量',
`stock_amount` decimal(15,2) NOT NULL DEFAULT 0.00 COMMENT '库存金额',
`low_stock_warning` decimal(15,3) DEFAULT NULL COMMENT '最低库存预警值',
`high_stock_warning` decimal(15,3) DEFAULT NULL COMMENT '最高库存预警值',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_product_id` (`product_id`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存表';
-- ----------------------------
-- Table structure for pl_inventory_transaction (库存流水表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_inventory_transaction`;
CREATE TABLE `pl_inventory_transaction` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`product_id` varchar(64) NOT NULL COMMENT '产品ID',
`product_name` varchar(200) NOT NULL COMMENT '产品名称',
`transaction_type` varchar(20) NOT NULL COMMENT '事务类型 inbound-入库 outbound-出库',
`plan_id` varchar(64) DEFAULT NULL COMMENT '计划ID',
`plan_no` varchar(32) DEFAULT NULL COMMENT '计划编号',
`qty` decimal(15,3) NOT NULL COMMENT '变动数量(正数入库/负数出库)',
`unit_price` decimal(15,4) NOT NULL COMMENT '单价',
`amount` decimal(15,2) NOT NULL COMMENT '金额',
`stock_after` decimal(15,3) NOT NULL COMMENT '变动后库存',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`),
KEY `idx_transaction_type` (`transaction_type`),
KEY `idx_plan_id` (`plan_id`),
KEY `idx_create_time` (`create_time`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存流水表';
-- ----------------------------
-- Table structure for pl_inventory_warning (库存预警表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_inventory_warning`;
CREATE TABLE `pl_inventory_warning` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`product_id` varchar(64) NOT NULL COMMENT '产品ID',
`product_name` varchar(200) NOT NULL COMMENT '产品名称',
`warning_type` varchar(20) NOT NULL COMMENT '预警类型 low-低于最低 high-高于最高',
`current_qty` decimal(15,3) NOT NULL COMMENT '当前库存',
`threshold_value` decimal(15,3) NOT NULL COMMENT '阈值',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '状态 pending-待处理 resolved-已处理',
`resolve_time` datetime DEFAULT NULL COMMENT '处理时间',
`resolve_remark` varchar(500) DEFAULT NULL COMMENT '处理备注',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_product_id` (`product_id`),
KEY `idx_warning_type` (`warning_type`),
KEY `idx_status` (`status`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='库存预警表';
-- ----------------------------
-- Table structure for pl_document_reminder (证件到期提醒表)
-- ----------------------------
DROP TABLE IF EXISTS `pl_document_reminder`;
CREATE TABLE `pl_document_reminder` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`cert_id` varchar(64) DEFAULT NULL COMMENT '证书ID',
`owner_type` varchar(20) DEFAULT NULL COMMENT '归属类型 vehicle/personnel',
`owner_id` varchar(64) DEFAULT NULL COMMENT '归属主体ID',
`owner_label` varchar(200) DEFAULT NULL COMMENT '归属展示名(车牌/姓名)',
`driver_id` varchar(64) DEFAULT NULL COMMENT '司机/人员ID(兼容)',
`driver_name` varchar(100) DEFAULT NULL COMMENT '司机/人员姓名(兼容)',
`document_type` varchar(100) NOT NULL COMMENT '证件类型/证书名称',
`document_no` varchar(50) DEFAULT NULL COMMENT '证件号',
`expire_date` date NOT NULL COMMENT '到期日期',
`days_remaining` int(11) NOT NULL COMMENT '剩余天数',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT '状态 pending-待处理 resolved-已处理',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
`create_by` varchar(64) DEFAULT NULL COMMENT '创建人id',
`create_dept_id` varchar(64) NOT NULL DEFAULT '' COMMENT '创建人部门ID',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_by` varchar(64) DEFAULT NULL COMMENT '更新人id',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`del_flag` smallint(6) NOT NULL DEFAULT 0 COMMENT '删除标记:0-正常 1-已删除',
PRIMARY KEY (`id`),
KEY `idx_cert_id` (`cert_id`),
KEY `idx_driver_id` (`driver_id`),
KEY `idx_document_type` (`document_type`),
KEY `idx_expire_date` (`expire_date`),
KEY `idx_status` (`status`),
KEY `idx_tenant` (`tenant_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='证件到期提醒表';
-- ----------------------------
-- Table structure for pl_vehicle_recharge_apply (车辆ETC/加油充值申请)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_recharge_apply`;
CREATE TABLE `pl_vehicle_recharge_apply` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`apply_no` varchar(32) NOT NULL COMMENT '申请单号 ETC+YYYYMMDD+2位',
`license_plate` varchar(20) NOT NULL COMMENT '车牌号',
`recharge_type` varchar(20) NOT NULL COMMENT '充值类型 etc-ETC fuel-加油',
`apply_date` date NOT NULL COMMENT '申请日期',
`odometer_km` decimal(10,1) DEFAULT NULL COMMENT '期初公里数',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`applicant_id` varchar(64) NOT NULL COMMENT '申请人用户ID',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT 'pending-待发放 disbursed-已发放 cancelled-已作废',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_apply_no` (`apply_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_license_plate` (`license_plate`),
KEY `idx_status` (`status`),
KEY `idx_apply_date` (`apply_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆ETC/加油充值申请';
-- ----------------------------
-- Table structure for pl_vehicle_recharge_record (车辆ETC/加油充值发放登记)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_recharge_record`;
CREATE TABLE `pl_vehicle_recharge_record` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`recharge_order_no` varchar(32) NOT NULL COMMENT '充值订单号 SXCL+YYYYMMDD+6位',
`recharge_date` date NOT NULL COMMENT '充值日期',
`recharge_type` varchar(20) NOT NULL COMMENT '充值类型 etc-ETC fuel-加油',
`card_no` varchar(64) DEFAULT NULL COMMENT '卡号',
`gas_station` varchar(200) DEFAULT NULL COMMENT '加油站/充值渠道',
`amount` decimal(10,2) NOT NULL COMMENT '充值金额(元)',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`apply_id` varchar(64) DEFAULT NULL COMMENT '关联申请单ID',
`license_plate` varchar(20) DEFAULT NULL COMMENT '车牌号冗余',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_recharge_order_no` (`recharge_order_no`),
UNIQUE KEY `uk_apply_id` (`apply_id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_recharge_date` (`recharge_date`),
KEY `idx_license_plate` (`license_plate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆ETC/加油充值发放登记';
-- ----------------------------
-- Table structure for pl_vehicle_maintenance_apply (车辆维保申请)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_maintenance_apply`;
CREATE TABLE `pl_vehicle_maintenance_apply` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`apply_no` varchar(32) NOT NULL COMMENT '申请单号 WB+YYYYMMDD+2位',
`license_plate` varchar(20) NOT NULL COMMENT '车牌号',
`applicant_id` varchar(64) NOT NULL COMMENT '申请人用户ID',
`apply_date` date NOT NULL COMMENT '申请时间',
`maintenance_type` varchar(64) NOT NULL COMMENT '维保类型',
`start_date` date NOT NULL COMMENT '维保开始时间',
`expected_pickup_date` date DEFAULT NULL COMMENT '预计取车时间',
`maintenance_content` varchar(1000) DEFAULT NULL COMMENT '维保内容',
`shop_address` varchar(500) DEFAULT NULL COMMENT '维保店铺地址',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT 'pending-待处理 processed-已处理 cancelled-已作废',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_apply_no` (`apply_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_license_plate` (`license_plate`),
KEY `idx_status` (`status`),
KEY `idx_apply_date` (`apply_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆维保申请';
-- ----------------------------
-- Table structure for pl_vehicle_maintenance_process (车辆维保处理登记)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_maintenance_process`;
CREATE TABLE `pl_vehicle_maintenance_process` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`process_no` varchar(32) NOT NULL COMMENT '处理单号 SXWC+YYYYMMDD+6位',
`apply_id` varchar(64) DEFAULT NULL COMMENT '关联申请单ID',
`license_plate` varchar(20) DEFAULT NULL COMMENT '车牌号冗余',
`amount` decimal(10,2) DEFAULT NULL COMMENT '金额(元)',
`handler_id` varchar(64) NOT NULL COMMENT '处理人用户ID',
`process_date` date NOT NULL COMMENT '处理时间',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_process_no` (`process_no`),
UNIQUE KEY `uk_apply_id` (`apply_id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_process_date` (`process_date`),
KEY `idx_license_plate` (`license_plate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆维保处理登记';
-- ----------------------------
-- Table structure for pl_vehicle_urea_apply (车辆尿素申请)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_urea_apply`;
CREATE TABLE `pl_vehicle_urea_apply` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`apply_no` varchar(32) NOT NULL COMMENT '申请单号 SXNS+YYYYMMDD+6位',
`license_plate` varchar(20) NOT NULL COMMENT '车牌号',
`applicant_id` varchar(64) NOT NULL COMMENT '申请人用户ID',
`apply_date` date NOT NULL COMMENT '申请时间',
`warehouse_in_date` date NOT NULL COMMENT '入库时间',
`unit` varchar(32) NOT NULL COMMENT '单位',
`quantity` decimal(10,2) NOT NULL COMMENT '入库数',
`apply_amount` decimal(10,2) NOT NULL COMMENT '申请金额(元)',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`status` varchar(20) NOT NULL DEFAULT 'pending' COMMENT 'pending-待发放 disbursed-已发放 cancelled-已作废',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_apply_no` (`apply_no`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_license_plate` (`license_plate`),
KEY `idx_status` (`status`),
KEY `idx_apply_date` (`apply_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆尿素申请';
-- ----------------------------
-- Table structure for pl_vehicle_urea_disburse (车辆尿素发放登记)
-- ----------------------------
DROP TABLE IF EXISTS `pl_vehicle_urea_disburse`;
CREATE TABLE `pl_vehicle_urea_disburse` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`disburse_no` varchar(32) NOT NULL COMMENT '发放单号 SXUF+YYYYMMDD+6位',
`apply_id` varchar(64) DEFAULT NULL COMMENT '关联申请单ID',
`license_plate` varchar(20) DEFAULT NULL COMMENT '车牌号冗余',
`amount` decimal(10,2) NOT NULL COMMENT '发放金额(元)',
`handler_id` varchar(64) NOT NULL COMMENT '处理人用户ID',
`disburse_date` date NOT NULL COMMENT '发放时间',
`attachment_urls` varchar(2000) DEFAULT NULL COMMENT '附件URL,逗号分隔',
`tenant_no` varchar(64) NOT NULL DEFAULT 'shanxia2.0',
`order_num` int(11) DEFAULT NULL,
`remark` varchar(512) DEFAULT NULL,
`create_by` varchar(64) DEFAULT NULL,
`create_dept_id` varchar(64) NOT NULL DEFAULT '',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_by` varchar(64) DEFAULT NULL,
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`del_flag` smallint(6) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_disburse_no` (`disburse_no`),
UNIQUE KEY `uk_apply_id` (`apply_id`),
KEY `idx_tenant` (`tenant_no`),
KEY `idx_disburse_date` (`disburse_date`),
KEY `idx_license_plate` (`license_plate`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='车辆尿素发放登记';
SET FOREIGN_KEY_CHECKS = 1;
-- =============================================================================
-- 增量迁移(已有库执行)
-- ALTER TABLE `pl_plan` ADD COLUMN `personnel_summary` varchar(500) DEFAULT NULL COMMENT '关联人员摘要(安排运输时快照)' AFTER `driver_name`;
-- ALTER TABLE `pl_plan` ADD COLUMN `trailer_no` varchar(20) DEFAULT NULL COMMENT '挂车号(安排运输时快照)' AFTER `license_plate`;
-- ALTER TABLE `pl_plan` ADD COLUMN `resource_snapshot` text COMMENT '车辆/人员/证件整包快照 JSON' AFTER `personnel_summary`;
-- ALTER TABLE `pl_transport` ADD COLUMN `trailer_no` varchar(20) DEFAULT NULL COMMENT '挂车号(安排运输时快照)' AFTER `license_plate`;
-- ALTER TABLE `pl_transport` ADD COLUMN `resource_snapshot` text COMMENT '车辆/人员/证件整包快照 JSON' AFTER `driver_phone`;
-- =============================================================================
-- =============================================================================
-- DDL 完成
-- 共计 22 张表(含 pl_cert;pl_driver 已由 pl_personnel 替代)
-- =============================================================================
-445
View File
@@ -1,445 +0,0 @@
/*
Navicat Premium Dump SQL
Source Server : 47.99.164.66 hn02le.34lkdLKD
Source Server Type : MySQL
Source Server Version : 50736 (5.7.36)
Source Host : 47.99.164.66:3306
Source Schema : vehicle_management
Target Server Type : MySQL
Target Server Version : 50736 (5.7.36)
File Encoding : 65001
Date: 05/05/2026 10:14:43
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for certificates
-- ----------------------------
DROP TABLE IF EXISTS `certificates`;
CREATE TABLE `certificates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL COMMENT '用户ID',
`certificate_type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '证件类型: driving_license(驾驶证), escort_license(押运证)等',
`file_url` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件URL',
`file_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '原文件名',
`expiry_date` date DEFAULT NULL COMMENT '证件过期日期',
`uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_certificates_expiry` (`expiry_date`),
CONSTRAINT `certificates_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='证件表';
-- ----------------------------
-- Records of certificates
-- ----------------------------
BEGIN;
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (5, 11, 'driving_license', 'http://localhost:8000/files/uploads/general/2026/01/15/7cbec2b6-6bef-4b57-90fc-b85460f99fd8.png', 'Snipaste_2025-12-27_16-03-25.png', '2026-01-21', '2026-01-15 16:50:44', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (6, 12, 'driving_license', 'http://121.43.228.102:9000/clgl/ed678c29-239d-46d4-a03b-75d1bbca6d1c.png', 'Snipaste_2025-12-27_16-03-21.png', '2026-02-04', '2026-01-15 17:05:56', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (7, 12, 'id_card', 'http://121.43.228.102:9000/clgl/4dbae2be-ab0b-43ca-b7f1-d9f1cdf9bbc1.png', 'Snipaste_2025-12-27_16-03-11.png', '2025-12-30', '2026-01-15 17:06:14', 1);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (8, 12, 'escort_license', 'http://121.43.228.102:9000/clgl/6f20a27a-7399-47f3-aa23-5e30d74f507b.png', 'Snipaste_2025-12-27_16-03-06.png', '2026-01-14', '2026-01-15 17:10:05', 1);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (9, 12, 'id_card', 'http://121.43.228.102:9000/clgl/736349d7-9443-4677-aacf-8ced1396c14c.png', 'Snipaste_2025-12-27_16-03-33.png', '2026-01-21', '2026-01-15 17:10:13', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (10, 12, 'id_card', 'http://121.43.228.102:9000/clgl/5e3203df-b0c3-45d5-a6b2-0a83c6ea7cda.png', 'Snipaste_2025-12-27_16-03-21.png', '2025-12-30', '2026-01-15 17:10:40', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (11, 12, 'qualification_certificate', 'http://121.43.228.102:9000/clgl/3b3bf250-62ab-42b9-920e-79401538ead2.png', 'Snipaste_2025-12-27_16-03-17.png', '2025-12-30', '2026-01-15 17:10:47', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (12, 12, 'escort_license', 'http://121.43.228.102:9000/clgl/bb416d90-8ce1-43bb-841d-ff86bb192190.png', 'Snipaste_2025-12-27_16-03-21.png', '2026-01-14', '2026-01-15 17:10:56', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (13, 9, 'driving_license', 'http://121.43.228.102:9000/clgl/ac003234-a437-4a18-92cf-5260ac71ec07.png', 'Snipaste_2025-12-27_16-03-33.png', '2026-01-14', '2026-01-15 22:53:09', 0);
INSERT INTO `certificates` (`id`, `user_id`, `certificate_type`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (14, 10, 'escort_license', 'http://121.43.228.102:9000/clgl/4907c641-d10e-4016-a517-65d1824df918.png', 'Snipaste_2025-12-27_16-03-21.png', '2025-12-31', '2026-01-15 22:53:21', 0);
COMMIT;
-- ----------------------------
-- Table structure for manufacturers
-- ----------------------------
DROP TABLE IF EXISTS `manufacturers`;
CREATE TABLE `manufacturers` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '厂商名称',
`safety_notice` text COLLATE utf8mb4_unicode_ci COMMENT '厂商安全须知',
`address` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '厂商地址',
`is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `idx_name` (`name`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='厂商表';
-- ----------------------------
-- Records of manufacturers
-- ----------------------------
BEGIN;
INSERT INTO `manufacturers` (`id`, `name`, `safety_notice`, `address`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (1, '山峡水泥厂', '注意安全,戴好安全帽,禁止在装卸区吸烟', '山峡市工业区A区', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `manufacturers` (`id`, `name`, `safety_notice`, `address`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (2, '山峡钢材厂', '注意防火,禁止明火,穿戴好防护装备', '山峡市工业区B区', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `manufacturers` (`id`, `name`, `safety_notice`, `address`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (3, '山峡物流中心', '注意交通安全,服从指挥', '山峡市物流园区', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `manufacturers` (`id`, `name`, `safety_notice`, `address`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (4, 'a s d f da s', '<h1><span style=\"color: rgb(225, 60, 57);\">123123123123123123213</span></h1><p><br></p><p>1额啊范德萨范德萨</p>', '啊是否撒点发三顿饭撒的范德萨发撒点饭撒的饭都是法师123123123123', 1, '2026-01-16 00:20:08', '2026-01-16 00:20:24', 1);
COMMIT;
-- ----------------------------
-- Table structure for plan_photos
-- ----------------------------
DROP TABLE IF EXISTS `plan_photos`;
CREATE TABLE `plan_photos` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plan_id` int(11) NOT NULL COMMENT '计划ID',
`photo_type` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '照片类型: loading_arrival(装货到场), loading_departure(装货离场), unloading_arrival(卸货到场), unloading_departure(卸货离场), waybill(运单)',
`file_url` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件URL',
`file_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '原文件名',
`uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_plan_id` (`plan_id`),
CONSTRAINT `plan_photos_ibfk_1` FOREIGN KEY (`plan_id`) REFERENCES `vehicle_plans` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='计划照片表';
-- ----------------------------
-- Records of plan_photos
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for products
-- ----------------------------
DROP TABLE IF EXISTS `products`;
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品名称',
`specification` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商品规格',
`is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_name` (`name`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品表';
-- ----------------------------
-- Records of products
-- ----------------------------
BEGIN;
INSERT INTO `products` (`id`, `name`, `specification`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (1, '水泥', '425号普通硅酸盐水泥', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `products` (`id`, `name`, `specification`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (2, '钢筋', '直径12mm HRB400钢筋', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `products` (`id`, `name`, `specification`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (3, '砂石', '中砂(细度模数2.3-1.6)', 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `products` (`id`, `name`, `specification`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (4, '混凝土', 'C30商品混凝土', 1, '2026-01-13 07:14:49', '2026-01-16 00:33:18', 1);
INSERT INTO `products` (`id`, `name`, `specification`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (5, '12344', '12344', 0, '2026-01-16 00:36:27', '2026-01-16 00:36:34', 1);
COMMIT;
-- ----------------------------
-- Table structure for schema_version
-- ----------------------------
DROP TABLE IF EXISTS `schema_version`;
CREATE TABLE `schema_version` (
`version` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '数据库版本',
`description` text COLLATE utf8mb4_unicode_ci COMMENT '版本描述',
`applied_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '应用时间',
PRIMARY KEY (`version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ----------------------------
-- Records of schema_version
-- ----------------------------
BEGIN;
INSERT INTO `schema_version` (`version`, `description`, `applied_at`) VALUES ('2.0.0', '添加证件过期时间管理功能,完善车辆证件分类系统', '2026-01-13 07:14:49');
COMMIT;
-- ----------------------------
-- Table structure for users
-- ----------------------------
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '登录工号',
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码',
`role` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'operator' COMMENT '角色: operator(操作员), admin(管理员), driver(司机), escort(押运员)',
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '姓名',
`phone` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '手机号码(司机、押运员必填)',
`id_card` varchar(18) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '身份证号(司机、押运员必填)',
`is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `idx_username` (`username`),
KEY `idx_role` (`role`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表';
-- ----------------------------
-- Records of users
-- ----------------------------
BEGIN;
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (1, 'admin', 'admin123', 'admin', '系统管理员', NULL, NULL, 1, '2026-01-13 07:14:49', '2026-01-13 07:14:49', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (2, 'testuser1768458386083', '123456', 'operator', '测试用户', NULL, NULL, 1, '2026-01-15 14:26:26', '2026-01-15 14:26:26', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (3, 'testuser1768458429763', '123456', 'operator', '测试用户', NULL, NULL, 1, '2026-01-15 14:27:09', '2026-01-15 14:27:09', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (7, 'test422', '123456', 'operator', '测试422', '13877711221', NULL, 1, '2026-01-15 14:37:18', '2026-01-15 14:37:18', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (8, 'czy03', '123456', 'operator', '操作员03', '13899001122', NULL, 1, '2026-01-15 14:39:18', '2026-01-15 14:39:18', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (9, '1231', '123456', 'escort', '王五', '13899112232', '340822198111221122', 1, '2026-01-15 14:43:18', '2026-01-15 19:01:50', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (10, '3', '123456', 'driver', 'lisan', '13877112211', '340822198811223344', 1, '2026-01-15 14:43:41', '2026-01-15 15:09:56', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (11, '4', '123456', 'operator', '4', '13511223311', NULL, 1, '2026-01-15 14:49:14', '2026-01-15 14:49:14', 0);
INSERT INTO `users` (`id`, `username`, `password`, `role`, `name`, `phone`, `id_card`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (12, '5', '123456', 'operator', '5', '13611332211', NULL, 0, '2026-01-15 14:49:23', '2026-01-15 17:19:18', 0);
COMMIT;
-- ----------------------------
-- Table structure for vehicle_certificates
-- ----------------------------
DROP TABLE IF EXISTS `vehicle_certificates`;
CREATE TABLE `vehicle_certificates` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`vehicle_id` int(11) NOT NULL COMMENT '车辆ID',
`certificate_category` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '证件类别: license(车牌), registration(行驶证), transport(运输证), insurance(保险), inspection(罐检)',
`vehicle_part` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '车辆部位: head(车头), tail(车尾), tank(罐体)',
`file_url` varchar(500) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '文件URL',
`file_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '原文件名',
`expiry_date` date DEFAULT NULL COMMENT '证件过期日期',
`uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '上传时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_vehicle_id` (`vehicle_id`),
KEY `idx_vehicle_certificates_expiry` (`expiry_date`),
KEY `idx_vehicle_certificates_part_category` (`vehicle_part`,`certificate_category`),
CONSTRAINT `vehicle_certificates_ibfk_1` FOREIGN KEY (`vehicle_id`) REFERENCES `vehicles` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆证件表';
-- ----------------------------
-- Records of vehicle_certificates
-- ----------------------------
BEGIN;
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (1, 1, 'license', 'head', 'http://121.43.228.102:9000/clgl/77ccdee8-1e0e-47fc-a34f-d9d06574a335.png', 'Snipaste_2025-12-27_16-03-25.png', '2026-01-13', '2026-01-15 20:00:52', 1);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (2, 1, 'registration', 'head', 'http://example.com/test.pdf', 'test.pdf', '2025-12-31', '2026-01-15 20:01:02', 1);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (3, 1, 'registration', 'head', 'http://121.43.228.102:9000/clgl/40194dc8-62f9-49eb-9e13-b5a7fefb9ed0.png', 'Snipaste_2025-12-27_16-03-25.png', '2026-01-21', '2026-01-15 20:28:36', 0);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (4, 1, 'inspection', 'head', 'http://121.43.228.102:9000/clgl/56f3c3a2-355f-4ffb-b59a-63db99d82ad3.png', 'Snipaste_2025-12-27_16-03-21.png', '2026-01-06', '2026-01-15 20:32:47', 1);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (5, 1, 'insurance', 'head', 'http://121.43.228.102:9000/clgl/350bad8b-ce21-42f4-913c-b279a0347f92.png', 'Snipaste_2025-12-27_16-03-33.png', '2025-12-30', '2026-01-15 20:33:01', 1);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (6, 1, 'registration', 'head', 'http://121.43.228.102:9000/clgl/b799d8e6-8b94-439a-8402-1fc11016b90e.png', 'Snipaste_2025-12-27_16-03-25.png', '2025-12-30', '2026-01-15 20:52:21', 1);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (7, 1, 'transport', 'tail', 'http://121.43.228.102:9000/clgl/86b2b5f4-938f-4bac-9621-eebcc5522b08.png', 'Snipaste_2025-12-27_16-03-25.png', '2026-01-28', '2026-01-15 21:28:56', 0);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (8, 1, 'registration', 'tail', 'http://121.43.228.102:9000/clgl/9468380e-9f5d-44a3-ba22-b5805570e8bc.png', 'Snipaste_2025-12-27_16-03-17.png', '2026-01-07', '2026-01-15 21:29:10', 0);
INSERT INTO `vehicle_certificates` (`id`, `vehicle_id`, `certificate_category`, `vehicle_part`, `file_url`, `file_name`, `expiry_date`, `uploaded_at`, `is_deleted`) VALUES (9, 1, 'license', 'tail', 'http://121.43.228.102:9000/clgl/b17330dc-1c32-4408-8f2d-bbcae00a3046.jpg', 'avatar.jpg', '2026-01-22', '2026-01-15 21:29:21', 0);
COMMIT;
-- ----------------------------
-- Table structure for vehicle_heads
-- ----------------------------
DROP TABLE IF EXISTS `vehicle_heads`;
CREATE TABLE `vehicle_heads` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plate_number` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`is_active` tinyint(1) DEFAULT '1',
`is_deleted` tinyint(1) DEFAULT '0',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`category` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT 'owned' COMMENT '车辆分类: owned(自有车辆), other(其他车辆)',
PRIMARY KEY (`id`),
UNIQUE KEY `plate_number` (`plate_number`),
KEY `idx_plate_number` (`plate_number`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车头表';
-- ----------------------------
-- Records of vehicle_heads
-- ----------------------------
BEGIN;
INSERT INTO `vehicle_heads` (`id`, `plate_number`, `is_active`, `is_deleted`, `created_at`, `updated_at`, `category`) VALUES (1, '皖P13231', 1, 0, '2026-01-15 19:18:40', '2026-01-15 19:18:40', 'owned');
INSERT INTO `vehicle_heads` (`id`, `plate_number`, `is_active`, `is_deleted`, `created_at`, `updated_at`, `category`) VALUES (2, '皖D13223', 1, 1, '2026-01-15 21:16:13', '2026-01-15 21:30:24', 'owned');
INSERT INTO `vehicle_heads` (`id`, `plate_number`, `is_active`, `is_deleted`, `created_at`, `updated_at`, `category`) VALUES (3, '皖S12222', 1, 0, '2026-01-15 22:28:32', '2026-01-15 22:28:32', 'owned');
COMMIT;
-- ----------------------------
-- Table structure for vehicle_plans
-- ----------------------------
DROP TABLE IF EXISTS `vehicle_plans`;
CREATE TABLE `vehicle_plans` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plan_date` date NOT NULL COMMENT '计划日期',
`start_time` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '开始时间 (HH:MM格式)',
`end_time` varchar(10) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '结束时间 (HH:MM格式)',
`customer_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '客户名称',
`product_id` int(11) NOT NULL COMMENT '商品ID',
`quantity` float NOT NULL COMMENT '数量',
`unit` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '单位',
`loading_manufacturer_id` int(11) NOT NULL COMMENT '装货厂商ID',
`unloading_manufacturer_id` int(11) NOT NULL COMMENT '卸货厂商ID',
`vehicle_id` int(11) NOT NULL COMMENT '车辆ID',
`driver_id` int(11) NOT NULL COMMENT '司机ID',
`escort_id` int(11) NOT NULL COMMENT '押运员ID',
`loading_arrival_time` datetime DEFAULT NULL COMMENT '装货到场时间',
`loading_departure_time` datetime DEFAULT NULL COMMENT '装货离场时间',
`unloading_arrival_time` datetime DEFAULT NULL COMMENT '卸货到场时间',
`unloading_departure_time` datetime DEFAULT NULL COMMENT '卸货离场时间',
`status` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending' COMMENT '状态: pending(待开始), loading(装货中), unloading(卸货中), completed(已完成)',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_plan_date` (`plan_date`),
KEY `idx_status` (`status`),
KEY `idx_driver_id` (`driver_id`),
KEY `idx_escort_id` (`escort_id`),
KEY `product_id` (`product_id`),
KEY `loading_manufacturer_id` (`loading_manufacturer_id`),
KEY `unloading_manufacturer_id` (`unloading_manufacturer_id`),
KEY `vehicle_id` (`vehicle_id`),
KEY `idx_vehicle_plans_date_status` (`plan_date`,`status`),
KEY `idx_vehicle_plans_driver_escort` (`driver_id`,`escort_id`),
CONSTRAINT `vehicle_plans_ibfk_1` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`),
CONSTRAINT `vehicle_plans_ibfk_2` FOREIGN KEY (`loading_manufacturer_id`) REFERENCES `manufacturers` (`id`),
CONSTRAINT `vehicle_plans_ibfk_3` FOREIGN KEY (`unloading_manufacturer_id`) REFERENCES `manufacturers` (`id`),
CONSTRAINT `vehicle_plans_ibfk_4` FOREIGN KEY (`vehicle_id`) REFERENCES `vehicles` (`id`),
CONSTRAINT `vehicle_plans_ibfk_5` FOREIGN KEY (`driver_id`) REFERENCES `users` (`id`),
CONSTRAINT `vehicle_plans_ibfk_6` FOREIGN KEY (`escort_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆计划表';
-- ----------------------------
-- Records of vehicle_plans
-- ----------------------------
BEGIN;
COMMIT;
-- ----------------------------
-- Table structure for vehicle_tails
-- ----------------------------
DROP TABLE IF EXISTS `vehicle_tails`;
CREATE TABLE `vehicle_tails` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`plate_number` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
`is_active` tinyint(1) DEFAULT '1',
`is_deleted` tinyint(1) DEFAULT '0',
`created_at` datetime DEFAULT CURRENT_TIMESTAMP,
`updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`category` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT 'owned' COMMENT '车辆分类: owned(自有车辆), other(其他车辆)',
PRIMARY KEY (`id`),
UNIQUE KEY `plate_number` (`plate_number`),
KEY `idx_plate_number` (`plate_number`),
KEY `idx_is_active` (`is_active`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车尾表';
-- ----------------------------
-- Records of vehicle_tails
-- ----------------------------
BEGIN;
INSERT INTO `vehicle_tails` (`id`, `plate_number`, `is_active`, `is_deleted`, `created_at`, `updated_at`, `category`) VALUES (1, '皖A09871', 0, 0, '2026-01-15 19:18:41', '2026-01-15 21:29:50', 'owned');
INSERT INTO `vehicle_tails` (`id`, `plate_number`, `is_active`, `is_deleted`, `created_at`, `updated_at`, `category`) VALUES (2, '皖A12333', 1, 0, '2026-01-15 22:28:39', '2026-01-15 22:28:39', 'owned');
COMMIT;
-- ----------------------------
-- Table structure for vehicles
-- ----------------------------
DROP TABLE IF EXISTS `vehicles`;
CREATE TABLE `vehicles` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`category` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '分类: owned(自有车辆), other(其他车辆)',
`head_id` int(11) DEFAULT NULL,
`tail_id` int(11) DEFAULT NULL,
`default_driver_id` int(11) DEFAULT NULL COMMENT '默认司机ID',
`default_escort_id` int(11) DEFAULT NULL COMMENT '默认押运员ID',
`is_active` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否启用',
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`is_deleted` tinyint(1) DEFAULT '0' COMMENT '是否删除: 0-正常, 1-删除',
PRIMARY KEY (`id`),
KEY `idx_category` (`category`),
KEY `idx_is_active` (`is_active`),
KEY `default_driver_id` (`default_driver_id`),
KEY `default_escort_id` (`default_escort_id`),
KEY `fk_vehicle_head` (`head_id`),
KEY `fk_vehicle_tail` (`tail_id`),
CONSTRAINT `fk_vehicle_head` FOREIGN KEY (`head_id`) REFERENCES `vehicle_heads` (`id`),
CONSTRAINT `fk_vehicle_tail` FOREIGN KEY (`tail_id`) REFERENCES `vehicle_tails` (`id`) ON DELETE SET NULL,
CONSTRAINT `vehicles_ibfk_1` FOREIGN KEY (`default_driver_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
CONSTRAINT `vehicles_ibfk_2` FOREIGN KEY (`default_escort_id`) REFERENCES `users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='车辆表';
-- ----------------------------
-- Records of vehicles
-- ----------------------------
BEGIN;
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (1, 'owned', 1, 1, 10, 9, 1, '2026-01-15 19:02:06', '2026-01-15 22:35:59', 1);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (2, 'other', 1, 1, 10, 9, 1, '2026-01-15 22:28:10', '2026-01-15 22:43:35', 0);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (3, 'owned', 3, 2, 10, 9, 0, '2026-01-15 22:29:18', '2026-01-15 23:45:59', 0);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (4, 'owned', 1, 2, 10, 9, 1, '2026-01-15 22:33:46', '2026-01-15 22:33:46', 0);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (5, 'owned', 1, 2, 10, 9, 1, '2026-01-15 22:33:58', '2026-01-15 22:33:58', 0);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (6, 'owned', 1, 2, 10, 9, 1, '2026-01-15 22:35:36', '2026-01-15 22:35:36', 0);
INSERT INTO `vehicles` (`id`, `category`, `head_id`, `tail_id`, `default_driver_id`, `default_escort_id`, `is_active`, `created_at`, `updated_at`, `is_deleted`) VALUES (7, 'owned', 1, 2, 10, 9, 1, '2026-01-15 22:35:54', '2026-01-15 22:35:54', 0);
COMMIT;
-- ----------------------------
-- Triggers structure for table manufacturers
-- ----------------------------
DROP TRIGGER IF EXISTS `update_manufacturers_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_manufacturers_timestamp` BEFORE UPDATE ON `manufacturers` FOR EACH ROW BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table products
-- ----------------------------
DROP TRIGGER IF EXISTS `update_products_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_products_timestamp` BEFORE UPDATE ON `products` FOR EACH ROW BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table users
-- ----------------------------
DROP TRIGGER IF EXISTS `update_users_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_users_timestamp` BEFORE UPDATE ON `users` FOR EACH ROW BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table vehicle_heads
-- ----------------------------
DROP TRIGGER IF EXISTS `update_vehicle_heads_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_vehicle_heads_timestamp` BEFORE UPDATE ON `vehicle_heads` FOR EACH ROW SET NEW.updated_at = CURRENT_TIMESTAMP
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table vehicle_plans
-- ----------------------------
DROP TRIGGER IF EXISTS `update_vehicle_plans_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_vehicle_plans_timestamp` BEFORE UPDATE ON `vehicle_plans` FOR EACH ROW BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table vehicle_tails
-- ----------------------------
DROP TRIGGER IF EXISTS `update_vehicle_tails_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_vehicle_tails_timestamp` BEFORE UPDATE ON `vehicle_tails` FOR EACH ROW SET NEW.updated_at = CURRENT_TIMESTAMP
;;
delimiter ;
-- ----------------------------
-- Triggers structure for table vehicles
-- ----------------------------
DROP TRIGGER IF EXISTS `update_vehicles_timestamp`;
delimiter ;;
CREATE TRIGGER `vehicle_management`.`update_vehicles_timestamp` BEFORE UPDATE ON `vehicles` FOR EACH ROW BEGIN
SET NEW.updated_at = CURRENT_TIMESTAMP;
END
;;
delimiter ;
SET FOREIGN_KEY_CHECKS = 1;
@@ -0,0 +1,60 @@
# web-admin 顶栏修改密码 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 在顶栏头像下拉「退出登录」上方增加「修改密码」,用户自助改密后当前会话继续有效。
**Architecture:** 前端 `ArtUserMenu` 增加菜单项并打开 `UserPasswordDialog`;弹窗调用 `fetchChangePassword`;后端 `public.py` 新增 `POST /web/auth/change-password`,CRUD 层 `change_password()` 校验原密码并 bcrypt 更新。
**Tech Stack:** Vue 3 + Element Plus(web-admin);FastAPI + SQLAlchemy + bcrypt(backend)
**Spec:** `docs/superpowers/specs/2026-07-12-web-admin-change-password-design.md`
---
### Task 1: 后端 CRUD `change_password`
**Files:**
- Modify: `backend/app/crud/user.py`
- [x] **Step 1:** 在 `reset_password` 上方新增 `change_password(db, user_id, old_password, new_password)`
- [x] **Step 2:** 校验用户存在、原密码 bcrypt、新密码 ≥6 位、新≠旧
### Task 2: 后端路由 `POST /web/auth/change-password`
**Files:**
- Modify: `backend/app/api/public.py`
- [x] **Step 1:** 从 Bearer Token 解析当前用户
- [x] **Step 2:** 读取 `oldPassword`/`newPassword`(兼容蛇形)
- [x] **Step 3:** 调用 `change_password`,返回成功/400/401
### Task 3: 前端 API
**Files:**
- Modify: `web-admin/src/api/auth.ts`
- [x] **Step 1:** 新增 `fetchChangePassword({ oldPassword, newPassword })`
### Task 4: 前端弹窗 `UserPasswordDialog.vue`
**Files:**
- Create: `web-admin/src/components/core/layouts/art-header-bar/widget/UserPasswordDialog.vue`
- [x] **Step 1:** 三字段表单弹窗(原密码/新密码/确认)
- [x] **Step 2:** Fresh Mint 弹窗规范 + Close/Check 底栏
### Task 5: 顶栏菜单入口
**Files:**
- Modify: `web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue`
- Modify: `web-admin/src/locales/langs/zh.json`
- Modify: `web-admin/src/locales/langs/en.json`
- [x] **Step 1:** 退出登录上方增加「修改密码」菜单项
- [x] **Step 2:** 引入 `UserPasswordDialog`,点击打开
### Task 6: 验证
- [x] **Step 1:** 后端语法检查 `python -m py_compile`
- [x] **Step 2:** 前端 lint 检查改动文件
@@ -0,0 +1,233 @@
# web-admin 顶栏用户菜单 — 修改密码设计
> **日期**: 2026-07-12
> **状态**: 待实施
> **范围**: `web-admin` 顶栏头像下拉 + `backend` 当前用户改密接口
> **UI 规范**: `docs/web-admin-ui-spec-fresh-mint.md`
> **参考实现**: 并列仓库 `zkxw`(`ArtUserMenu.vue` + `UserPasswordDialog.vue` + `/web/auth/change-password`)
## 背景与目标
运营人员在 `web-admin` 顶栏点击头像后,下拉菜单目前仅有电话/区域展示与「退出登录」,无法自助修改密码,只能联系管理员在用户管理页重置为默认密码 `111111`。
**目标**:在头像下拉菜单中,于「退出登录」按钮**上方**增加「修改密码」入口,用户填写原密码与新密码后完成自助改密。
## 已确认决策
| # | 决策 | 说明 |
|---|------|------|
| D1 | **交互形态** | 方案 A:菜单项 + 独立弹窗 `UserPasswordDialog`(对齐 zkxw) |
| D2 | **改密后会话** | **不强制重新登录**;改密成功后提示并关闭弹窗,当前 Token 会话继续有效 |
| D3 | **权限** | 仅需登录态(Bearer Token),不新增菜单权限码 |
| D4 | **密码规则** | 新密码最少 6 位;校验原密码 bcrypt;确认密码前端一致性校验 |
| D5 | **传输安全** | 走 HTTPS + 现有 API 加密中间件(生产环境);**不**单独对改密请求做 RSA(与登录区分,同 zkxw) |
| D6 | **范围** | 仅「修改密码」;本期不做「个人信息」编辑 |
## 非目标(本期不做)
- 忘记密码 / 邮件找回
- 密码复杂度策略(大小写+数字+特殊字符)
- 密码历史表 / 防重复使用旧密码
- 首次登录强制改密
- 改密后吊销当前会话 / 强制退出
- 小程序端改密
---
## 一、现状与缺口
### 前端
| 项 | 状态 |
|----|------|
| `ArtUserMenu.vue` 菜单入口 | ❌ 无「修改密码」 |
| `UserPasswordDialog.vue` | ❌ 不存在 |
| `fetchChangePassword()` | ❌ `api/auth.ts` 未定义 |
入口文件:`web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue`
由 `art-header-bar/index.vue` 引用。
### 后端
| 项 | 状态 |
|----|------|
| `ChangePasswordRequest` Schema | ✅ `app/schemas/auth.py`(已有,未接线) |
| `change_password()` CRUD | ❌ 仅有 `reset_password()`(管理员重置) |
| `POST /web/auth/change-password` | ❌ 未实现 |
已有管理员重置:`POST /web/admin/users/{id}/reset-password` → 固定重置为 `111111`。
---
## 二、目标交互
### 菜单布局
```
┌─────────────────────┐
│ [头像] 张三 │
│ 运营管理员 │
├─────────────────────┤
│ 👤 138xxxx │
│ 📍 华东区(若有) │
├─────────────────────┤
│ 🔒 修改密码 ← 新增 │
├─────────────────────┤
│ [ 退出登录 ] │
└─────────────────────┘
```
### 流程
1. 用户悬停头像 → 点击「修改密码」
2. `ArtUserMenu` 关闭 Popover(沿用 `closeUserMenu()` + `setTimeout` 模式)
3. 打开 `UserPasswordDialog`(`v-model:visible`)
4. 用户填写:原密码、新密码、确认新密码
5. 前端校验通过后 `POST /web/auth/change-password`
6. 成功 → 全局成功提示、关闭弹窗、**不**调用 `logOut()`
7. 失败 → 展示后端错误(如「原密码不正确」)
---
## 三、前端设计
### 改动文件
| 文件 | 操作 |
|------|------|
| `web-admin/src/components/core/layouts/art-header-bar/widget/ArtUserMenu.vue` | 修改:增加菜单项 + 引入弹窗 |
| `web-admin/src/components/core/layouts/art-header-bar/widget/UserPasswordDialog.vue` | **新建**:改密弹窗 |
| `web-admin/src/api/auth.ts` | 修改:新增 `fetchChangePassword()` |
| `web-admin/src/locales/langs/zh.json` | 可选:`topBar.user.changePassword` |
| `web-admin/src/locales/langs/en.json` | 可选:同上英文 |
### `ArtUserMenu.vue` 变更要点
- 在分隔线与「退出登录」之间新增 `<li class="btn-item" @click="openPasswordDialog">`
- 图标:`ArtSvgIcon icon="ri:lock-password-line"`
- 文案:`修改密码`(或 `$t('topBar.user.changePassword')`)
- 根节点包裹 `<UserPasswordDialog v-model:visible="passwordDialogVisible" />`
- `openPasswordDialog()` 模式对齐 zkxw:`closeUserMenu()` → `setTimeout 150ms` → `passwordDialogVisible = true`
### `UserPasswordDialog.vue` 规范
对齐 Fresh Mint 弹窗约定(`web-admin-crud-dialog.mdc`):
- `el-dialog`:`class="dialog-form-layout"`、`align-center`、`append-to-body`、`modal-class="protocol-dialog-mask"`、`destroy-on-close`、`:close-on-click-modal="false"`
- `el-form`:`label-position="top"`、`scroll-to-error`
- 字段(均 `form-col-span-2`):
- 原密码:`type="password"`、`show-password`、`autocomplete="current-password"`
- 新密码:`min 6` 校验、`autocomplete="new-password"`
- 确认新密码:自定义 validator 与 `newPassword` 一致
- Footer:取消(`Close` 图标)、确定(`Check` 图标 + `:loading="submitting"`)
- 打开时 `resetForm()` 清空字段与校验态
### API
```typescript
/** 当前用户修改密码 */
export function fetchChangePassword(data: { oldPassword: string; newPassword: string }) {
return request.post({
url: '/web/auth/change-password',
data,
showSuccessMessage: true
})
}
```
---
## 四、后端设计
### 改动文件
| 文件 | 操作 |
|------|------|
| `backend/app/crud/user.py` | 新增 `change_password()` |
| `backend/app/api/public.py` | 新增 `POST /web/auth/change-password` |
### `change_password()` 逻辑
```python
def change_password(db: Session, user_id: str, old_password: str, new_password: str) -> None:
obj = get_user(db, user_id)
if not obj:
raise ValueError("用户不存在")
if not verify_password(old_password, obj.password or ""):
raise ValueError("原密码不正确")
new_pw = (new_password or "").strip()
if len(new_pw) < 6:
raise ValueError("新密码长度不能少于6位")
if old_password == new_pw:
raise ValueError("新密码不能与原密码相同")
obj.password = _hash_password(new_pw)
obj.update_time = datetime.now()
db.add(obj)
db.commit()
```
### 路由
```
POST /web/auth/change-password
Authorization: Bearer <access_token>
Content-Type: application/json
Request body(驼峰,与前端一致):
{
"oldPassword": "string",
"newPassword": "string"
}
Response 200:
{ "code": 200, "data": { "message": "密码修改成功" } }
Response 400:
- "请输入原密码"
- "新密码长度不能少于6位"
- "原密码不正确"
- "新密码不能与原密码相同"
Response 401:
- "Token无效或已过期" / "未授权"
```
鉴权:从 `Authorization` Bearer Token 解析当前用户 `user_id`(复用 `get_current_user_by_token` 或 `public.py` 现有模式)。
---
## 五、校验规则汇总
| 规则 | 前端 | 后端 |
|------|:----:|:----:|
| 原密码必填 | ✅ | ✅ |
| 新密码 ≥ 6 位 | ✅ | ✅ |
| 确认密码一致 | ✅ | — |
| 原密码 bcrypt 校验 | — | ✅ |
| 新密码 ≠ 原密码 | 建议 | ✅ |
---
## 六、验收清单
- [ ] 头像下拉在「退出登录」上方显示「修改密码」
- [ ] 点击后 Popover 关闭,弹窗居中打开
- [ ] 原密码错误 → 「原密码不正确」
- [ ] 新密码 < 6 位 → 前端拦截
- [ ] 两次新密码不一致 → 前端拦截
- [ ] 改密成功 → 成功提示,弹窗关闭,**不**退出登录
- [ ] 登出后用新密码可重新登录
- [ ] 弹窗符合 Fresh Mint(`dialog-form-layout`、无 backdrop blur、按钮带图标)
---
## 七、工作量
| 模块 | 预估 |
|------|------|
| 前端 | ~1h |
| 后端 | ~0.5h |
| 联调 | ~0.5h |
| **合计** | **~2h** |
无数据库迁移;约 6 个文件改动。
+826 -7232
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -1 +1 @@
{"/Users/zlwu/work/00code/shanxia2.0/web-admin/package.json":{"size":3957,"mtime_ns":1781960299953649209,"hash":"ca01a16c94014e791391dfd8896f93c1ba7c451db1afa2f49f8a2a68b87dcc56"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/tsconfig.json":{"size":921,"mtime_ns":1780108931391506392,"hash":"8cec43256bc87216f729ae2c9588979558b20f33831419aa58502b54f5127c98"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931156918274,"hash":"0f2b6369eaf54ccac995e091d7ef5e292fa1396eadd32b64cbddd5bba0018d14"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931156854566,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/zh.json":{"size":10130,"mtime_ns":1780108931365472245,"hash":"f9834cd440df5dbce6ee91cc778c58b604d72d9652c48e8a285ac41e2d1be44f"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/en.json":{"size":10269,"mtime_ns":1780108931365387869,"hash":"fd0abc176e117037235c47e12bd682d93a8dc50183e14b54e20e169fb5714758"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/mock/json/chinaMap.json":{"size":956443,"mtime_ns":1780108931366831877,"hash":"2ce3f532aed5b51fa9b64bf134bf1d77c7886e695fd55a3368333584cbef4113"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-flat.json":{"size":341606,"mtime_ns":1780108931184708348,"hash":"120c09f381ee3ac8fc6282e0be885a72ff256093c5aebf7a0861e38185d5f8ae"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-cascader.json":{"size":217969,"mtime_ns":1780108931184402180,"hash":"63789a66f6bd55e8adeda487f6e4f361f1a916c4fdb3e2d8961ee412de57d307"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.md":{"size":19526,"mtime_ns":1780108931156993275,"hash":"3e1cf79e220067ef1e99102d5cee89646591a03e292f7ca957e209ee264d416a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.md":{"size":4196,"mtime_ns":1780108931157199359,"hash":"114c94f9bf11e2083f1c985b2a5f58c5fbc50334dfbd25438415f21f8f577150"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.zh-CN.md":{"size":17172,"mtime_ns":1780108931157071900,"hash":"f4ec5751d75c6d3ec0767fd9c1f5787cc96c0a1ab059ed199ae4de1f1959f9fc"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.zh-CN.md":{"size":3775,"mtime_ns":1780108931157266568,"hash":"75a5522b08799b17dfe4416d20153a9cd247f5cbf280fe04ed0858a8337dc2d7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/views/crm/clue/README.md":{"size":7884,"mtime_ns":1780211534938564937,"hash":"43ee077b77166be37ebf44e0f13c8f01801f08a8274ebfa976ae21cbe8c27ca7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-quote-vue.py":{"size":4450,"mtime_ns":1780242127112333277,"hash":"97378f52743089231fbc83430106cad7701aa59b045126af45a238d7d2878bac"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-index-shell.py":{"size":11102,"mtime_ns":1780228518737746875,"hash":"0557768a404e2a0d9f2d3b233599bd741bdeb61a8e2d3cadf8d8dc4f1d6be25d"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-vue.py":{"size":4673,"mtime_ns":1780228615418009691,"hash":"790b4297df996f03b45d2efda686e219d60cd8e0f796fd860c070ed2e13939d6"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-attachments.py":{"size":1708,"mtime_ns":1780229286334758010,"hash":"eb364a061d7f7a6659311604353cd64a53edc81c1f1413b626ddf0388d709c46"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-panel.py":{"size":5523,"mtime_ns":1780229250658746500,"hash":"c873cdb8f5e8d8339aec3f47dc840106e1a176e3c9ac210ddd6d0abe547d928a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-attachments.py":{"size":14077,"mtime_ns":1780229316215427400,"hash":"470af77a8b9508291fab61aeee4c64bd495f78c77d09574e6b49962ce165eeaf"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-layout.py":{"size":5157,"mtime_ns":1780229581646441465,"hash":"d5d97158dd892bd942f61721bcae770de518de368f487c2a30129502b3125787"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-detail-fresh-mint.py":{"size":24615,"mtime_ns":1780229887010846627,"hash":"daf372506c69aa3a92a4ddf3d508252ae63b68718d00bb49fb03914cc8bcfee3"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/apply-list-toolbar-refresh.py":{"size":5777,"mtime_ns":1782834192989973152,"hash":"a2329df76d2aca29b6a7c751e43e61ec47b569718de910f3f10a2391d7b3bedb"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/add-list-index-columns.py":{"size":4644,"mtime_ns":1782865925817727372,"hash":"7e769c9dcb928cb8c4a5ce3eecebd488b94c4a2467959c99d8ec4cbed76bdb44"}}
{"/Users/zlwu/work/00code/shanxia2.0/web-admin/package.json":{"size":3957,"mtime_ns":1781960299953649209,"hash":"ca01a16c94014e791391dfd8896f93c1ba7c451db1afa2f49f8a2a68b87dcc56"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/tsconfig.json":{"size":921,"mtime_ns":1780108931391506392,"hash":"8cec43256bc87216f729ae2c9588979558b20f33831419aa58502b54f5127c98"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/settings.json":{"size":425,"mtime_ns":1780108931156918274,"hash":"0f2b6369eaf54ccac995e091d7ef5e292fa1396eadd32b64cbddd5bba0018d14"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/.vscode/extensions.json":{"size":200,"mtime_ns":1780108931156854566,"hash":"520c42e097d801a599814f12fe6a97bf5d7100e5395fd33217a365baa2cfe3c8"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/zh.json":{"size":10170,"mtime_ns":1783851637746348929,"hash":"015bc477ca647b32f2ef55c87db91ead797ec9db036de6dbf3578cd1be78de89"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/locales/langs/en.json":{"size":10312,"mtime_ns":1783851637976877140,"hash":"c46cb6e3ab9d55364fa79ce2ee42e46fb307f54350ee9abff7a71a74387c5982"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/mock/json/chinaMap.json":{"size":956443,"mtime_ns":1780108931366831877,"hash":"2ce3f532aed5b51fa9b64bf134bf1d77c7886e695fd55a3368333584cbef4113"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-flat.json":{"size":341606,"mtime_ns":1780108931184708348,"hash":"120c09f381ee3ac8fc6282e0be885a72ff256093c5aebf7a0861e38185d5f8ae"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/assets/data/china-region-cascader.json":{"size":217969,"mtime_ns":1780108931184402180,"hash":"63789a66f6bd55e8adeda487f6e4f361f1a916c4fdb3e2d8961ee412de57d307"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.md":{"size":19526,"mtime_ns":1780108931156993275,"hash":"3e1cf79e220067ef1e99102d5cee89646591a03e292f7ca957e209ee264d416a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.md":{"size":4196,"mtime_ns":1780108931157199359,"hash":"114c94f9bf11e2083f1c985b2a5f58c5fbc50334dfbd25438415f21f8f577150"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/CHANGELOG.zh-CN.md":{"size":17172,"mtime_ns":1780108931157071900,"hash":"f4ec5751d75c6d3ec0767fd9c1f5787cc96c0a1ab059ed199ae4de1f1959f9fc"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/README.zh-CN.md":{"size":3775,"mtime_ns":1780108931157266568,"hash":"75a5522b08799b17dfe4416d20153a9cd247f5cbf280fe04ed0858a8337dc2d7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/src/views/crm/clue/README.md":{"size":7884,"mtime_ns":1780211534938564937,"hash":"43ee077b77166be37ebf44e0f13c8f01801f08a8274ebfa976ae21cbe8c27ca7"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-quote-vue.py":{"size":4450,"mtime_ns":1780242127112333277,"hash":"97378f52743089231fbc83430106cad7701aa59b045126af45a238d7d2878bac"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-index-shell.py":{"size":11102,"mtime_ns":1780228518737746875,"hash":"0557768a404e2a0d9f2d3b233599bd741bdeb61a8e2d3cadf8d8dc4f1d6be25d"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-vue.py":{"size":4673,"mtime_ns":1780228615418009691,"hash":"790b4297df996f03b45d2efda686e219d60cd8e0f796fd860c070ed2e13939d6"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-attachments.py":{"size":1708,"mtime_ns":1780229286334758010,"hash":"eb364a061d7f7a6659311604353cd64a53edc81c1f1413b626ddf0388d709c46"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-panel.py":{"size":5523,"mtime_ns":1780229250658746500,"hash":"c873cdb8f5e8d8339aec3f47dc840106e1a176e3c9ac210ddd6d0abe547d928a"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-attachments.py":{"size":14077,"mtime_ns":1780229316215427400,"hash":"470af77a8b9508291fab61aeee4c64bd495f78c77d09574e6b49962ce165eeaf"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-form-layout.py":{"size":5157,"mtime_ns":1780229581646441465,"hash":"d5d97158dd892bd942f61721bcae770de518de368f487c2a30129502b3125787"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/migrate-contract-detail-fresh-mint.py":{"size":24615,"mtime_ns":1780229887010846627,"hash":"daf372506c69aa3a92a4ddf3d508252ae63b68718d00bb49fb03914cc8bcfee3"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/apply-list-toolbar-refresh.py":{"size":5777,"mtime_ns":1782834192989973152,"hash":"a2329df76d2aca29b6a7c751e43e61ec47b569718de910f3f10a2391d7b3bedb"},"/Users/zlwu/work/00code/shanxia2.0/web-admin/scripts/add-list-index-columns.py":{"size":4644,"mtime_ns":1782865925817727372,"hash":"7e769c9dcb928cb8c4a5ce3eecebd488b94c4a2467959c99d8ec4cbed76bdb44"}}
+9
View File
@@ -87,3 +87,12 @@ export function fetchLogout() {
url: '/web/auth/logout'
})
}
/** 当前用户修改密码 */
export function fetchChangePassword(data: { oldPassword: string; newPassword: string }) {
return request.post({
url: '/web/auth/change-password',
data,
showSuccessMessage: true
})
}
@@ -1,5 +1,6 @@
<!-- 用户菜单 -->
<template>
<div class="user-menu-root">
<ElPopover
ref="userMenuPopover"
placement="bottom-end"
@@ -43,6 +44,11 @@
<span>{{ userInfo.regionName }}</span>
</li>
<div class="w-full h-px my-2 bg-g-300/80"></div>
<li class="btn-item" @click="openPasswordDialog">
<ArtSvgIcon icon="ri:lock-password-line" />
<span>{{ $t('topBar.user.changePassword') }}</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 +56,17 @@
</div>
</template>
</ElPopover>
<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 UserPasswordDialog from './UserPasswordDialog.vue'
defineOptions({ name: 'ArtUserMenu' })
@@ -69,6 +79,7 @@
)
const userMenuPopover = ref()
const passwordDialogVisible = ref(false)
/**
* 获取角色名称
@@ -83,6 +94,13 @@
return roleMap[role] || role || '未知角色'
}
function openPasswordDialog() {
closeUserMenu()
setTimeout(() => {
passwordDialogVisible.value = true
}, 150)
}
/**
* 用户登出确认
*/
@@ -0,0 +1,151 @@
<!-- 当前用户修改密码 -->
<template>
<el-dialog
v-model="dialogVisible"
title="修改密码"
width="480px"
class="dialog-form-layout"
align-center
append-to-body
modal-class="protocol-dialog-mask"
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>
+1
View File
@@ -23,6 +23,7 @@
"docs": "Document",
"github": "Github",
"lockScreen": "Lock screen",
"changePassword": "Change password",
"logout": "Log out"
},
"guide": {
+1
View File
@@ -23,6 +23,7 @@
"docs": "使用文档",
"github": "Github",
"lockScreen": "锁定屏幕",
"changePassword": "修改密码",
"logout": "退出登录"
},
"guide": {