This commit is contained in:
zlwu committed 2026-06-14 17:20:52 +08:00
1 parent a79aee2614
commit 427bcb1551
274 files changed
+59416 -38342

No files matched your search

+1 -1
View File
@@ -1 +1 @@
86521
74483
+8
View File
@@ -739,6 +739,7 @@ class SiteCreateBody(BaseModel):
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
business_scope: Optional[str] = Field(None, alias="businessScope")
site_image: Optional[str] = Field(None, alias="siteImage")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -754,6 +755,7 @@ class SiteUpdateBody(BaseModel):
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
business_scope: Optional[str] = Field(None, alias="businessScope")
site_image: Optional[str] = Field(None, alias="siteImage")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -790,6 +792,7 @@ async def create_site(
contact_name=body.contact_name,
contact_phone=body.contact_phone,
business_scope=body.business_scope,
site_image=body.site_image,
tenant_no=tenant_no,
order_num=body.order_num,
remark=body.remark,
@@ -820,6 +823,7 @@ async def update_site(
contact_name=payload.get("contact_name"),
contact_phone=payload.get("contact_phone"),
business_scope=payload.get("business_scope"),
site_image=payload.get("site_image"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
user_id=user.get("user_id"),
@@ -1086,6 +1090,7 @@ class ExpressCompanyCreateBody(BaseModel):
express_code: str = Field(..., alias="expressCode")
express_name: str = Field(..., alias="expressName")
express_logo: Optional[str] = Field(None, alias="expressLogo")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -1095,6 +1100,7 @@ class ExpressCompanyUpdateBody(BaseModel):
express_code: Optional[str] = Field(None, alias="expressCode")
express_name: Optional[str] = Field(None, alias="expressName")
express_logo: Optional[str] = Field(None, alias="expressLogo")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -1125,6 +1131,7 @@ async def create_express_company(
db,
express_code=body.express_code,
express_name=body.express_name,
express_logo=body.express_logo,
tenant_no=tenant_no,
order_num=body.order_num,
remark=body.remark,
@@ -1149,6 +1156,7 @@ async def update_express_company(
company_id,
express_code=payload.get("express_code"),
express_name=payload.get("express_name"),
express_logo=payload.get("express_logo"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
user_id=user.get("user_id"),
+5 -1
View File
@@ -198,6 +198,7 @@ class CellSampleTypeCreateBody(BaseModel):
type_code: str = Field(..., alias="typeCode")
type_name: str = Field(..., alias="typeName")
type_logo: Optional[str] = Field(None, alias="typeLogo")
storage_years: Optional[int] = Field(None, alias="storageYears")
storage_price: Optional[float] = Field(None, alias="storagePrice")
order_num: Optional[int] = Field(0, alias="orderNum")
@@ -209,6 +210,7 @@ class CellSampleTypeUpdateBody(BaseModel):
type_code: Optional[str] = Field(None, alias="typeCode")
type_name: Optional[str] = Field(None, alias="typeName")
type_logo: Optional[str] = Field(None, alias="typeLogo")
storage_years: Optional[int] = Field(None, alias="storageYears")
storage_price: Optional[float] = Field(None, alias="storagePrice")
order_num: Optional[int] = Field(None, alias="orderNum")
@@ -240,7 +242,7 @@ async def list_cell_sample_types(
)
query = apply_data_scope(query, BizCellSampleType, user, db, tenant_no)
total = query.count()
items = query.order_by(BizCellSampleType.create_time.desc()).offset((page - 1) * pageSize).limit(pageSize).all()
items = query.order_by(BizCellSampleType.order_num.asc(), BizCellSampleType.create_time.desc()).offset((page - 1) * pageSize).limit(pageSize).all()
result_list = [cell_type_svc._row_to_dict(r) for r in items]
tp = cell_type_svc.total_pages(total, pageSize)
return success_response({"list": result_list, "total": total, "page": page, "pageSize": pageSize, "totalPages": tp})
@@ -258,6 +260,7 @@ async def create_cell_sample_type(
db,
type_code=body.type_code,
type_name=body.type_name,
type_logo=body.type_logo,
storage_years=body.storage_years,
storage_price=body.storage_price,
tenant_no=tenant_no,
@@ -285,6 +288,7 @@ async def update_cell_sample_type(
row_id,
type_code=payload.get("type_code"),
type_name=payload.get("type_name"),
type_logo=payload.get("type_logo"),
storage_years=payload.get("storage_years"),
storage_price=payload.get("storage_price"),
order_num=payload.get("order_num"),
+33 -3
View File
@@ -58,13 +58,14 @@ def _total_pages(total: int, page_size: int) -> int:
# ---------------------------------------------------------------------------
def _row_to_dict_company(row: BizInsuranceCompany) -> dict:
return {
def _row_to_dict_company(row: BizInsuranceCompany, project_prices: Optional[List[dict]] = None) -> dict:
data = {
"id": row.id,
"companyName": row.company_name,
"companyAddress": row.company_address,
"contactName": row.contact_name,
"contactPhone": row.contact_phone,
"companyLogo": row.company_logo or "",
"status": row.status,
"tenantNo": row.tenant_no,
"orderNum": row.order_num,
@@ -75,6 +76,9 @@ def _row_to_dict_company(row: BizInsuranceCompany) -> dict:
"updateBy": row.update_by,
"updateTime": _fmt_dt(row.update_time),
}
if project_prices is not None:
data["projectPrices"] = project_prices
return data
def _row_to_dict_invoice(row: BizInsuranceCompanyInvoice) -> dict:
@@ -157,7 +161,24 @@ def _list_insurance_companies(
.limit(page_size)
.all()
)
return [_row_to_dict_company(r) for r in rows], total
company_ids = [r.id for r in rows]
prices_by_company: dict[str, list] = {cid: [] for cid in company_ids}
if company_ids:
prices_q = db.query(BizInsuranceProjectPrice).filter(
BizInsuranceProjectPrice.insurance_company_id.in_(company_ids),
BizInsuranceProjectPrice.tenant_no == tenant_no,
BizInsuranceProjectPrice.del_flag == 0,
)
if user_info:
from app.core.data_scope import apply_data_scope
prices_q = apply_data_scope(prices_q, BizInsuranceProjectPrice, user_info, db, tenant_no)
for price_row in prices_q.order_by(BizInsuranceProjectPrice.create_time.desc()).all():
prices_by_company.setdefault(price_row.insurance_company_id, []).append(
_row_to_dict_project_price(price_row)
)
return [
_row_to_dict_company(r, prices_by_company.get(r.id, [])) for r in rows
], total
def _create_insurance_company(
@@ -167,6 +188,7 @@ def _create_insurance_company(
company_address: Optional[str],
contact_name: Optional[str],
contact_phone: Optional[str],
company_logo: Optional[str],
status: Optional[str],
tenant_no: str,
order_num: Optional[int],
@@ -179,6 +201,7 @@ def _create_insurance_company(
company_address=company_address,
contact_name=contact_name,
contact_phone=contact_phone,
company_logo=(company_logo or "").strip() or None,
status=status or "1",
tenant_no=tenant_no,
order_num=order_num or 0,
@@ -204,6 +227,7 @@ def _update_insurance_company(
company_address: Optional[str],
contact_name: Optional[str],
contact_phone: Optional[str],
company_logo: Optional[str],
status: Optional[str],
order_num: Optional[int],
remark: Optional[str],
@@ -229,6 +253,8 @@ def _update_insurance_company(
obj.contact_name = contact_name
if contact_phone is not None:
obj.contact_phone = contact_phone
if company_logo is not None:
obj.company_logo = (company_logo or "").strip() or None
if status is not None:
obj.status = status
if order_num is not None:
@@ -528,6 +554,7 @@ class InsuranceCompanyCreateBody(BaseModel):
company_address: Optional[str] = Field(None, alias="companyAddress")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
company_logo: Optional[str] = Field(None, alias="companyLogo")
status: Optional[str] = Field("1", alias="status")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -540,6 +567,7 @@ class InsuranceCompanyUpdateBody(BaseModel):
company_address: Optional[str] = Field(None, alias="companyAddress")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
company_logo: Optional[str] = Field(None, alias="companyLogo")
status: Optional[str] = Field(None, alias="status")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -584,6 +612,7 @@ async def create_insurance_company(
company_address=body.company_address,
contact_name=body.contact_name,
contact_phone=body.contact_phone,
company_logo=body.company_logo,
status=body.status,
tenant_no=tenant_no,
order_num=body.order_num,
@@ -612,6 +641,7 @@ async def update_insurance_company(
company_address=payload.get("company_address"),
contact_name=payload.get("contact_name"),
contact_phone=payload.get("contact_phone"),
company_logo=payload.get("company_logo"),
status=payload.get("status"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
+54
View File
@@ -149,6 +149,8 @@ class StockCheckCreateBody(BaseModel):
class StockCheckUnusedLineItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
usage_id: Optional[str] = Field(None, alias="usageId")
batch_id: Optional[str] = Field(None, alias="batchId")
material_code: Optional[str] = Field(None, alias="materialCode")
material_name: str = Field(..., alias="materialName")
spec_model: Optional[str] = Field(None, alias="specModel")
@@ -624,9 +626,61 @@ async def list_stock_logs(
return error_response(400, str(e))
@router.post("/material-usages/{usage_id}/mark-fully-used")
async def mark_material_usage_fully_used(
usage_id: str,
db: Session = Depends(get_db),
user: dict = Depends(require_menu_code("biz:material:list")),
):
"""标记领用记录已使用完(盘点登记 / 变动记录)。"""
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
mu_svc.mark_requisition_fully_used(
db,
usage_id,
tenant_no=tenant_no,
user_id=user_id,
user_info=user,
)
return success_response(None, message="已标记为使用完")
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
except Exception as e:
return error_response(400, str(e))
# ---------- 库存盘点 ----------
@router.get("/material-stock-check-requisitions")
async def list_material_stock_check_requisitions(
page: int = Query(1, ge=1),
pageSize: int = Query(50, ge=1, le=200),
keyword: Optional[str] = None,
db: Session = Depends(get_db),
user: dict = Depends(require_menu_code("biz:material:list")),
):
"""盘点登记:待处理领用记录(未标记已使用完)。"""
try:
tenant_no = _get_tenant_no(db, user)
items, total = mu_svc.list_stock_check_requisitions(
db,
tenant_no,
page=page,
page_size=pageSize,
keyword=keyword,
user_info=user,
)
return success_response(_page_payload(items, total, page, pageSize))
except PermissionError as e:
return error_response(403, str(e))
except Exception as e:
return error_response(400, str(e))
@router.get("/material-stock-checks")
async def list_material_stock_checks(
page: int = Query(1, ge=1),
+4
View File
@@ -44,6 +44,7 @@ class CleanRoomCreateBody(BaseModel):
room_grade: Optional[str] = Field(None, alias="roomGrade")
room_status: Optional[str] = Field("zc", alias="roomStatus")
area_sqm: Optional[float] = Field(None, alias="areaSqm")
room_image: Optional[str] = Field(None, alias="roomImage")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -56,6 +57,7 @@ class CleanRoomUpdateBody(BaseModel):
room_grade: Optional[str] = Field(None, alias="roomGrade")
room_status: Optional[str] = Field(None, alias="roomStatus")
area_sqm: Optional[float] = Field(None, alias="areaSqm")
room_image: Optional[str] = Field(None, alias="roomImage")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -100,6 +102,7 @@ async def create_clean_room(
room_grade=body.room_grade,
room_status=body.room_status or "zc",
area_sqm=body.area_sqm,
room_image=body.room_image,
tenant_no=tenant_no,
order_num=body.order_num,
remark=body.remark,
@@ -128,6 +131,7 @@ async def update_clean_room(
room_grade=payload.get("room_grade"),
room_status=payload.get("room_status"),
area_sqm=payload.get("area_sqm"),
room_image=payload.get("room_image"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
user_id=user.get("user_id"),
+4
View File
@@ -1219,6 +1219,7 @@ class CheckupInstitutionCreateBody(BaseModel):
institution_address: Optional[str] = Field(None, alias="institutionAddress")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
institution_logo: Optional[str] = Field(None, alias="institutionLogo")
status: Optional[str] = Field("1", alias="status")
order_num: Optional[int] = Field(0, alias="orderNum")
remark: Optional[str] = None
@@ -1231,6 +1232,7 @@ class CheckupInstitutionUpdateBody(BaseModel):
institution_address: Optional[str] = Field(None, alias="institutionAddress")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
institution_logo: Optional[str] = Field(None, alias="institutionLogo")
status: Optional[str] = Field(None, alias="status")
order_num: Optional[int] = Field(None, alias="orderNum")
remark: Optional[str] = None
@@ -1275,6 +1277,7 @@ async def create_checkup_institution(
institution_address=body.institution_address,
contact_name=body.contact_name,
contact_phone=body.contact_phone,
institution_logo=body.institution_logo,
status=body.status,
tenant_no=tenant_no,
order_num=body.order_num,
@@ -1303,6 +1306,7 @@ async def update_checkup_institution(
institution_address=payload.get("institution_address"),
contact_name=payload.get("contact_name"),
contact_phone=payload.get("contact_phone"),
institution_logo=payload.get("institution_logo"),
status=payload.get("status"),
order_num=payload.get("order_num"),
remark=payload.get("remark"),
+54
View File
@@ -633,6 +633,32 @@ async def list_production_material_usages(
return error_response(400, str(e))
@router.post("/production-material-usages/{usage_id}/mark-fully-used")
async def mark_production_material_usage_fully_used(
usage_id: str,
db: Session = Depends(get_db),
user: dict = Depends(require_menu_code("production:material:list")),
):
"""标记领用记录已使用完(盘点登记 / 变动记录)。"""
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
mu_svc.mark_requisition_fully_used(
db,
usage_id,
tenant_no=tenant_no,
user_id=user_id,
user_info=user,
)
return success_response(None, message="已标记为使用完")
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
except Exception as e:
return error_response(400, str(e))
@router.get("/my-production-material-usages")
async def list_my_production_material_usages(
page: int = Query(1, ge=1),
@@ -709,6 +735,8 @@ class StockCheckCreateBody(BaseModel):
class StockCheckUnusedLineItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
usage_id: Optional[str] = Field(None, alias="usageId")
batch_id: Optional[str] = Field(None, alias="batchId")
material_code: Optional[str] = Field(None, alias="materialCode")
material_name: str = Field(..., alias="materialName")
spec_model: Optional[str] = Field(None, alias="specModel")
@@ -730,6 +758,32 @@ class StockCheckUnusedLinesBody(BaseModel):
items: List[StockCheckUnusedLineItem] = Field(default_factory=list)
@router.get("/production-material-stock-check-requisitions")
async def list_production_material_stock_check_requisitions(
page: int = Query(1, ge=1),
pageSize: int = Query(50, ge=1, le=200),
keyword: Optional[str] = None,
db: Session = Depends(get_db),
user: dict = Depends(require_menu_code("production:material:list")),
):
"""盘点登记:待处理领用记录(未标记已使用完)。"""
try:
tenant_no = _get_tenant_no(db, user)
items, total = mu_svc.list_stock_check_requisitions(
db,
tenant_no,
page=page,
page_size=pageSize,
keyword=keyword,
user_info=user,
)
return success_response(_page_payload(items, total, page, pageSize))
except PermissionError as e:
return error_response(403, str(e))
except Exception as e:
return error_response(400, str(e))
@router.get("/production-material-stock-checks")
async def list_production_material_stock_checks(
page: int = Query(1, ge=1),
+60
View File
@@ -48,6 +48,7 @@ class ThirdPartyCompanyBody(BaseModel):
company_name: str = Field(..., alias="companyName")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
company_logo: Optional[str] = Field(None, alias="companyLogo")
address: Optional[str] = None
invoice_title: Optional[str] = Field(None, alias="invoiceTitle")
tax_id: Optional[str] = Field(None, alias="taxId")
@@ -65,6 +66,7 @@ class ThirdPartyCompanyUpdateBody(BaseModel):
company_name: Optional[str] = Field(None, alias="companyName")
contact_name: Optional[str] = Field(None, alias="contactName")
contact_phone: Optional[str] = Field(None, alias="contactPhone")
company_logo: Optional[str] = Field(None, alias="companyLogo")
address: Optional[str] = None
invoice_title: Optional[str] = Field(None, alias="invoiceTitle")
tax_id: Optional[str] = Field(None, alias="taxId")
@@ -125,6 +127,7 @@ async def create_qc_third_party_company(
company_name=body.company_name,
contact_name=body.contact_name,
contact_phone=body.contact_phone,
company_logo=body.company_logo,
address=body.address,
invoice_title=body.invoice_title,
tax_id=body.tax_id,
@@ -161,6 +164,7 @@ async def update_qc_third_party_company(
company_name=body.company_name,
contact_name=body.contact_name,
contact_phone=body.contact_phone,
company_logo=body.company_logo,
address=body.address,
invoice_title=body.invoice_title,
tax_id=body.tax_id,
@@ -1714,6 +1718,60 @@ async def list_qc_material_linked_task_usages(
return error_response(400, str(e))
@router.get("/qc-material-stock-check-requisitions")
async def list_qc_material_stock_check_requisitions(
page: int = Query(1, ge=1),
pageSize: int = Query(50, ge=1, le=200),
keyword: Optional[str] = None,
db: Session = Depends(get_db),
user: dict = Depends(require_menu_code("biz:qcMaterial:list")),
):
"""盘点登记:待处理领用记录(未标记已使用完)。"""
try:
tenant_no = _get_tenant_no(db, user)
items, total = mu_svc.list_stock_check_requisitions(
db,
tenant_no,
page=page,
page_size=pageSize,
keyword=keyword,
user_info=user,
)
return success_response(_page_payload(items, total, page, pageSize))
except PermissionError as e:
return error_response(403, str(e))
except Exception as e:
return error_response(400, str(e))
@router.post("/qc-material-usages/{usage_id}/mark-fully-used")
async def mark_qc_material_usage_fully_used(
usage_id: str,
db: Session = Depends(get_db),
user: dict = Depends(
require_any_menu_code("biz:qcMaterial:list", "biz:qcMaterialUsage:list")
),
):
"""标记领用记录已使用完(盘点登记 / 变动记录)。"""
try:
tenant_no = _get_tenant_no(db, user)
user_id = _get_current_user_id(user)
mu_svc.mark_requisition_fully_used(
db,
usage_id,
tenant_no=tenant_no,
user_id=user_id,
user_info=user,
)
return success_response(None, message="已标记为使用完")
except PermissionError as e:
return error_response(403, str(e))
except ValueError as e:
return error_response(400, str(e))
except Exception as e:
return error_response(400, str(e))
# ---------- 库存盘点 ----------
@@ -1726,6 +1784,8 @@ class StockCheckCreateBody(BaseModel):
class StockCheckUnusedLineItem(BaseModel):
model_config = ConfigDict(populate_by_name=True)
usage_id: Optional[str] = Field(None, alias="usageId")
batch_id: Optional[str] = Field(None, alias="batchId")
material_code: Optional[str] = Field(None, alias="materialCode")
material_name: str = Field(..., alias="materialName")
spec_model: Optional[str] = Field(None, alias="specModel")
+7 -1
View File
@@ -18,6 +18,7 @@ def _row_to_dict(r: BizCellSampleType) -> Dict[str, Any]:
"id": r.id,
"typeCode": r.type_code,
"typeName": r.type_name,
"typeLogo": r.type_logo or "",
"storageYears": r.storage_years,
"storagePrice": float(sp) if sp is not None else None,
"tenantNo": r.tenant_no,
@@ -63,7 +64,7 @@ def list_cell_sample_types(
page_size = min(max(1, page_size), 100)
rows = (
_filtered()
.order_by(BizCellSampleType.create_time.desc())
.order_by(BizCellSampleType.order_num.asc(), BizCellSampleType.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
@@ -83,6 +84,7 @@ def create_cell_sample_type(
*,
type_code: str,
type_name: str,
type_logo: Optional[str] = None,
storage_years: Optional[int] = None,
storage_price: Optional[float] = None,
tenant_no: str = "zkxw",
@@ -99,6 +101,7 @@ def create_cell_sample_type(
id=generate_uuid(),
type_code=tc,
type_name=(type_name or "").strip() or tc,
type_logo=(type_logo or "").strip() or None,
storage_years=storage_years,
storage_price=storage_price,
tenant_no=tenant_no,
@@ -123,6 +126,7 @@ def update_cell_sample_type(
*,
type_code: Optional[str] = None,
type_name: Optional[str] = None,
type_logo: Optional[str] = None,
storage_years: Optional[int] = None,
storage_price: Optional[float] = None,
order_num: Optional[int] = None,
@@ -142,6 +146,8 @@ def update_cell_sample_type(
obj.type_code = tc
if type_name is not None:
obj.type_name = (type_name or "").strip() or obj.type_name
if type_logo is not None:
obj.type_logo = (type_logo or "").strip() or None
if storage_years is not None:
obj.storage_years = storage_years
if storage_price is not None:
+6
View File
@@ -24,6 +24,7 @@ def _row_to_dict(c: BizCleanRoom) -> Dict[str, Any]:
"roomGrade": c.room_grade,
"roomStatus": c.room_status,
"areaSqm": float(c.area_sqm) if c.area_sqm is not None else 0.0,
"roomImage": c.room_image or "",
"tenantNo": c.tenant_no,
"orderNum": c.order_num if c.order_num is not None else 0,
"remark": c.remark or "",
@@ -87,6 +88,7 @@ def create_clean_room(
room_grade: Optional[str] = None,
room_status: Optional[str] = None,
area_sqm: Optional[Any] = None,
room_image: Optional[str] = None,
tenant_no: str = "zkxw",
order_num: Optional[int] = None,
remark: Optional[str] = None,
@@ -104,6 +106,7 @@ def create_clean_room(
room_grade=(room_grade or "").strip() or None,
room_status=(room_status or "").strip() or None,
area_sqm=area_sqm if area_sqm is not None else 0,
room_image=(room_image or "").strip() or None,
tenant_no=tenant_no,
order_num=order_num if order_num is not None else 0,
remark=(remark or "").strip() or None,
@@ -129,6 +132,7 @@ def update_clean_room(
room_grade: Optional[str] = None,
room_status: Optional[str] = None,
area_sqm: Optional[Any] = None,
room_image: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -152,6 +156,8 @@ def update_clean_room(
obj.room_status = (room_status or "").strip() or None
if area_sqm is not None:
obj.area_sqm = area_sqm
if room_image is not None:
obj.room_image = (room_image or "").strip() or None
if order_num is not None:
obj.order_num = order_num
if remark is not None:
+6
View File
@@ -17,6 +17,7 @@ def _row_to_dict(e: BizExpressCompany) -> Dict[str, Any]:
"id": e.id,
"expressCode": e.express_code,
"expressName": e.express_name,
"expressLogo": e.express_logo or "",
"tenantNo": e.tenant_no,
"orderNum": e.order_num if e.order_num is not None else 0,
"remark": e.remark or "",
@@ -80,6 +81,7 @@ def create_express_company(
*,
express_code: str,
express_name: str,
express_logo: Optional[str] = None,
tenant_no: str = "zkxw",
order_num: Optional[int] = None,
remark: Optional[str] = None,
@@ -94,6 +96,7 @@ def create_express_company(
id=generate_uuid(),
express_code=ec,
express_name=(express_name or "").strip() or ec,
express_logo=(express_logo or "").strip() or None,
tenant_no=tenant_no,
order_num=order_num if order_num is not None else 0,
remark=(remark or "").strip() or None,
@@ -116,6 +119,7 @@ def update_express_company(
*,
express_code: Optional[str] = None,
express_name: Optional[str] = None,
express_logo: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -132,6 +136,8 @@ def update_express_company(
obj.express_code = new_code
if express_name is not None:
obj.express_name = (express_name or "").strip() or obj.express_name
if express_logo is not None:
obj.express_logo = (express_logo or "").strip() or None
if order_num is not None:
obj.order_num = order_num
if remark is not None:
+95
View File
@@ -71,6 +71,8 @@ def _unused_line_to_dict(row: BizMaterialStockCheckUnusedLine) -> Dict[str, Any]
return {
"id": row.id,
"checkId": row.check_id,
"usageId": row.usage_id or "",
"batchId": row.batch_id or "",
"materialCode": row.material_code or "",
"materialName": row.material_name or "",
"specModel": row.spec_model or "",
@@ -352,6 +354,94 @@ def _parse_optional_date(v: Any) -> Optional[Any]:
return _parse_date(v, label="日期")
def _resolve_unused_item_fields(
db: Session,
it: Dict[str, Any],
tenant_no: str,
) -> Dict[str, Any]:
"""根据 usage_id / batch_id 补全登记行快照字段。"""
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip()
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip()
out = dict(it)
if usage_id:
from app.models.material import BizMaterialUsage, BizMaterialStockBatch
usage = (
db.query(BizMaterialUsage)
.filter(
BizMaterialUsage.id == usage_id,
BizMaterialUsage.tenant_no == tenant_no,
BizMaterialUsage.del_flag == 0,
BizMaterialUsage.source_type == "manual_out",
)
.first()
)
if not usage:
raise ValueError("关联领用记录不存在")
batch = None
if usage.batch_id:
batch = (
db.query(BizMaterialStockBatch)
.filter(
BizMaterialStockBatch.id == usage.batch_id,
BizMaterialStockBatch.tenant_no == tenant_no,
BizMaterialStockBatch.del_flag == 0,
)
.first()
)
out.setdefault("material_code", usage.material_code or "")
out.setdefault("material_name", usage.material_name or "")
out.setdefault("spec_model", (batch.spec_model if batch else "") or "")
out.setdefault("unit", (batch.unit if batch else "") or usage.usage_unit or "")
out.setdefault("stock_in_no", usage.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch and batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch and batch.expire_date else "")
out.setdefault("catalog_no", usage.catalog_no or "")
out.setdefault("batch_no", usage.batch_no or "")
out.setdefault("manufacturer", usage.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
up = float(usage.unit_price) if usage.unit_price is not None else None
if up is not None:
out["unit_price"] = up
rcv = (usage.receiver or "").strip()
if rcv and not (out.get("holder") or "").strip():
out["holder"] = rcv
if batch and not batch_id:
out["batch_id"] = batch.id
return out
if batch_id:
from app.models.material import BizMaterialStockBatch
batch = (
db.query(BizMaterialStockBatch)
.filter(
BizMaterialStockBatch.id == batch_id,
BizMaterialStockBatch.tenant_no == tenant_no,
BizMaterialStockBatch.del_flag == 0,
)
.first()
)
if not batch:
raise ValueError("关联入库批次不存在")
out.setdefault("material_code", batch.material_code or "")
out.setdefault("material_name", batch.material_name or "")
out.setdefault("spec_model", batch.spec_model or "")
out.setdefault("unit", batch.unit or "")
out.setdefault("stock_in_no", batch.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch.expire_date else "")
out.setdefault("catalog_no", batch.catalog_no or "")
out.setdefault("batch_no", batch.batch_no or "")
out.setdefault("manufacturer", batch.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
out["unit_price"] = float(batch.unit_price) if batch.unit_price is not None else None
return out
return out
def save_unused_lines(
db: Session,
check_id: str,
@@ -384,6 +474,7 @@ def save_unused_lines(
count = 0
for it in items or []:
it = _resolve_unused_item_fields(db, it, tenant_no)
name = _require_str(it.get("material_name") or it.get("materialName"), "物料名称")
qty = it.get("unused_qty") if it.get("unused_qty") is not None else it.get("unusedQty")
if qty is None or Decimal(str(qty)) <= 0:
@@ -391,10 +482,14 @@ def save_unused_lines(
qty_dec = Decimal(str(qty))
stock_in_date = _parse_optional_date(it.get("stock_in_date") or it.get("stockInDate"))
expire_date = _parse_optional_date(it.get("expire_date") or it.get("expireDate"))
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip() or None
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip() or None
row = BizMaterialStockCheckUnusedLine(
id=generate_uuid(),
check_id=check_id,
usage_id=usage_id,
batch_id=batch_id,
material_code=(it.get("material_code") or it.get("materialCode") or "").strip() or None,
material_name=name,
spec_model=(it.get("spec_model") or it.get("specModel") or "").strip() or None,
+141
View File
@@ -1,6 +1,7 @@
"""市场物料变动记录 CRUD"""
from __future__ import annotations
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
from sqlalchemy import func, or_
@@ -145,6 +146,7 @@ def _row_to_dict(
"receiverName": receiver_name or receiver,
"purpose": purpose,
"sourceType": r.source_type or "",
"requisitionStatus": (getattr(r, "requisition_status", None) or "open").strip() or "open",
"useTime": create_time if is_manual_out else "",
"remark": _display_remark(r),
"createBy": create_by,
@@ -277,3 +279,142 @@ def list_usages(
user_info=user_info,
)
return _paginate_usages(db, q0, page=page, page_size=page_size)
def _fmt_date_val(v) -> str:
if v is None:
return ""
if hasattr(v, "strftime"):
return v.strftime("%Y-%m-%d")
return str(v)[:10]
def list_stock_check_requisitions(
db: Session,
tenant_no: str,
*,
page: int = 1,
page_size: int = 50,
keyword: Optional[str] = None,
user_info=None,
) -> Tuple[List[Dict[str, Any]], int]:
"""盘点登记弹窗:待处理领用记录(未标记已使用完)。"""
q0 = db.query(BizMaterialUsage).filter(
BizMaterialUsage.tenant_no == tenant_no,
BizMaterialUsage.del_flag == 0,
BizMaterialUsage.change_type == "use",
BizMaterialUsage.source_type == "manual_out",
BizMaterialUsage.requisition_status == "open",
)
if user_info:
from app.core.data_scope import apply_data_scope
q0 = apply_data_scope(q0, BizMaterialUsage, user_info, db, tenant_no)
kw = (keyword or "").strip()
if kw:
like = f"%{kw}%"
q0 = q0.filter(
or_(
BizMaterialUsage.material_code.like(like),
BizMaterialUsage.material_name.like(like),
BizMaterialUsage.stock_in_no.like(like),
BizMaterialUsage.batch_no.like(like),
BizMaterialUsage.catalog_no.like(like),
BizMaterialUsage.receiver.like(like),
)
)
total = q0.order_by(None).with_entities(func.count(BizMaterialUsage.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 200)
rows = (
q0.order_by(BizMaterialUsage.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
)
bmap = _batch_map(db, [x.batch_id for x in rows if x.batch_id])
name_map = _user_nick_name_map(db, [x.create_by for x in rows if x.create_by])
receivers = []
for r in rows:
rcv, _ = _resolve_receiver_purpose(r)
if rcv:
receivers.append(rcv)
receiver_map = _receiver_display_map(db, receivers)
out: List[Dict[str, Any]] = []
for r in rows:
batch = bmap.get(r.batch_id or "")
rcv, purpose = _resolve_receiver_purpose(r)
rcv_name = receiver_map.get(rcv, rcv) if rcv else ""
qty_abs = abs(float(r.change_qty or 0))
unit = _usage_unit_label(r, batch)
use_time = r.create_time.strftime("%Y-%m-%d %H:%M:%S") if r.create_time else ""
out.append(
{
"id": r.id,
"materialId": r.material_id,
"materialCode": r.material_code or "",
"materialName": r.material_name or "",
"specModel": (batch.spec_model if batch else "") or "",
"batchId": r.batch_id or "",
"stockInNo": r.stock_in_no or "",
"stockInDate": _stock_in_date_for_row(r, batch),
"expireDate": _fmt_date_val(batch.expire_date if batch else None),
"catalogNo": r.catalog_no or "",
"batchNo": r.batch_no or "",
"manufacturer": r.manufacturer or "",
"unitPrice": _unit_price_for_row(r, batch),
"unit": unit,
"requisitionQty": qty_abs,
"taskConsumedQty": 0,
"receiver": rcv,
"receiverName": rcv_name,
"purpose": purpose,
"useTime": use_time,
"requisitionStatus": (r.requisition_status or "open").strip() or "open",
"createByName": name_map.get(r.create_by or "", r.create_by or ""),
}
)
return out, int(total)
def mark_requisition_fully_used(
db: Session,
usage_id: str,
*,
tenant_no: str,
user_id: Optional[str] = None,
user_info=None,
) -> None:
row = (
db.query(BizMaterialUsage)
.filter(
BizMaterialUsage.id == usage_id,
BizMaterialUsage.tenant_no == tenant_no,
BizMaterialUsage.del_flag == 0,
BizMaterialUsage.change_type == "use",
BizMaterialUsage.source_type == "manual_out",
)
.first()
)
if not row:
raise ValueError("领用记录不存在或不可标记")
if user_info:
from app.core.data_scope import apply_data_scope
scoped = apply_data_scope(
db.query(BizMaterialUsage).filter(BizMaterialUsage.id == usage_id),
BizMaterialUsage,
user_info,
db,
tenant_no,
)
if not scoped.first():
raise PermissionError("无权操作该领用记录")
if (row.requisition_status or "open") == "closed":
return
now = datetime.now()
row.requisition_status = "closed"
row.update_by = user_id
row.update_time = now
db.add(row)
db.commit()
+30 -3
View File
@@ -1572,13 +1572,14 @@ def soft_delete_channel_agreement_price(db, price_id, tenant_no=None):
# Entity 11: BizCheckupInstitution 体检机构
# ────────────────────────────────────────────
def _row_to_dict_checkup_institution(row) -> Dict[str, Any]:
return {
def _row_to_dict_checkup_institution(row, projects: Optional[List[Dict[str, Any]]] = None) -> Dict[str, Any]:
data = {
"id": row.id,
"institutionName": row.institution_name or "",
"institutionAddress": row.institution_address or "",
"contactName": row.contact_name or "",
"contactPhone": row.contact_phone or "",
"institutionLogo": row.institution_logo or "",
"status": row.status or "1",
"tenantNo": row.tenant_no or "",
"orderNum": row.order_num if row.order_num is not None else 0,
@@ -1586,6 +1587,9 @@ def _row_to_dict_checkup_institution(row) -> Dict[str, Any]:
"createTime": row.create_time.strftime("%Y-%m-%d %H:%M:%S") if row.create_time else "",
"updateTime": row.update_time.strftime("%Y-%m-%d %H:%M:%S") if row.update_time else "",
}
if projects is not None:
data["projects"] = projects
return data
def list_checkup_institutions(db, *, page=1, page_size=10, keyword=None, status=None, tenant_no=None, user_info=None):
@@ -1614,7 +1618,25 @@ def list_checkup_institutions(db, *, page=1, page_size=10, keyword=None, status=
page = max(1, page)
page_size = min(max(1, page_size), 100)
rows = _filtered().order_by(BizCheckupInstitution.create_time.desc()).offset((page - 1) * page_size).limit(page_size).all()
return [_row_to_dict_checkup_institution(x) for x in rows], int(total)
institution_ids = [x.id for x in rows]
projects_by_inst: Dict[str, List[Dict[str, Any]]] = {iid: [] for iid in institution_ids}
if institution_ids:
pq = db.query(BizCheckupInstitutionProject).filter(
BizCheckupInstitutionProject.checkup_institution_id.in_(institution_ids),
BizCheckupInstitutionProject.del_flag == 0,
)
if tenant_no:
pq = pq.filter(BizCheckupInstitutionProject.tenant_no == tenant_no)
if user_info:
from app.core.data_scope import apply_data_scope
pq = apply_data_scope(pq, BizCheckupInstitutionProject, user_info, db, tenant_no)
for pr in pq.order_by(BizCheckupInstitutionProject.create_time.desc()).all():
projects_by_inst.setdefault(pr.checkup_institution_id, []).append(
_row_to_dict_checkup_institution_project(pr)
)
return [
_row_to_dict_checkup_institution(x, projects_by_inst.get(x.id, [])) for x in rows
], int(total)
def get_checkup_institution(db, institution_id, tenant_no=None):
@@ -1633,6 +1655,7 @@ def create_checkup_institution(
institution_address=None,
contact_name=None,
contact_phone=None,
institution_logo=None,
status="1",
tenant_no="zkxw",
order_num=None,
@@ -1645,6 +1668,7 @@ def create_checkup_institution(
institution_address=institution_address or "",
contact_name=contact_name or "",
contact_phone=contact_phone or "",
institution_logo=(institution_logo or "").strip() or None,
status=status or "1",
tenant_no=tenant_no,
order_num=order_num or 0,
@@ -1669,6 +1693,7 @@ def update_checkup_institution(
institution_address=None,
contact_name=None,
contact_phone=None,
institution_logo=None,
status=None,
order_num=None,
remark=None,
@@ -1686,6 +1711,8 @@ def update_checkup_institution(
obj.contact_name = contact_name
if contact_phone is not None:
obj.contact_phone = contact_phone
if institution_logo is not None:
obj.institution_logo = (institution_logo or "").strip() or None
if status is not None:
obj.status = status
if order_num is not None:
@@ -73,6 +73,8 @@ def _unused_line_to_dict(row: BizProductionMaterialStockCheckUnusedLine) -> Dict
return {
"id": row.id,
"checkId": row.check_id,
"usageId": row.usage_id or "",
"batchId": row.batch_id or "",
"materialType": row.material_type or "",
"materialCode": row.material_code or "",
"materialName": row.material_name or "",
@@ -357,6 +359,96 @@ def _parse_optional_date(v: Any) -> Optional[Any]:
return _parse_date(v, label="日期")
def _resolve_unused_item_fields(
db: Session,
it: Dict[str, Any],
tenant_no: str,
) -> Dict[str, Any]:
"""根据 usage_id / batch_id 补全登记行快照字段。"""
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip()
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip()
out = dict(it)
if usage_id:
from app.models.production_material import BizProductionMaterialUsage, BizProductionMaterialStockBatch
usage = (
db.query(BizProductionMaterialUsage)
.filter(
BizProductionMaterialUsage.id == usage_id,
BizProductionMaterialUsage.tenant_no == tenant_no,
BizProductionMaterialUsage.del_flag == 0,
BizProductionMaterialUsage.source_type == "manual_out",
)
.first()
)
if not usage:
raise ValueError("关联领用记录不存在")
batch = None
if usage.batch_id:
batch = (
db.query(BizProductionMaterialStockBatch)
.filter(
BizProductionMaterialStockBatch.id == usage.batch_id,
BizProductionMaterialStockBatch.tenant_no == tenant_no,
BizProductionMaterialStockBatch.del_flag == 0,
)
.first()
)
out.setdefault("material_type", usage.material_type or "")
out.setdefault("material_code", usage.material_code or "")
out.setdefault("material_name", usage.material_name or "")
out.setdefault("spec_model", (batch.spec_model if batch else "") or "")
out.setdefault("unit", (batch.unit if batch else "") or usage.usage_unit or "")
out.setdefault("stock_in_no", usage.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch and batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch and batch.expire_date else "")
out.setdefault("catalog_no", usage.catalog_no or "")
out.setdefault("batch_no", usage.batch_no or "")
out.setdefault("manufacturer", usage.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
up = float(usage.unit_price) if usage.unit_price is not None else None
if up is not None:
out["unit_price"] = up
rcv = (usage.receiver or "").strip()
if rcv and not (out.get("holder") or "").strip():
out["holder"] = rcv
if batch and not batch_id:
out["batch_id"] = batch.id
return out
if batch_id:
from app.models.production_material import BizProductionMaterialStockBatch
batch = (
db.query(BizProductionMaterialStockBatch)
.filter(
BizProductionMaterialStockBatch.id == batch_id,
BizProductionMaterialStockBatch.tenant_no == tenant_no,
BizProductionMaterialStockBatch.del_flag == 0,
)
.first()
)
if not batch:
raise ValueError("关联入库批次不存在")
out.setdefault("material_type", batch.material_type or "")
out.setdefault("material_code", batch.material_code or "")
out.setdefault("material_name", batch.material_name or "")
out.setdefault("spec_model", batch.spec_model or "")
out.setdefault("unit", batch.unit or "")
out.setdefault("stock_in_no", batch.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch.expire_date else "")
out.setdefault("catalog_no", batch.catalog_no or "")
out.setdefault("batch_no", batch.batch_no or "")
out.setdefault("manufacturer", batch.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
out["unit_price"] = float(batch.unit_price) if batch.unit_price is not None else None
return out
return out
def save_unused_lines(
db: Session,
check_id: str,
@@ -389,6 +481,7 @@ def save_unused_lines(
count = 0
for it in items or []:
it = _resolve_unused_item_fields(db, it, tenant_no)
name = _require_str(it.get("material_name") or it.get("materialName"), "物料名称")
qty = it.get("unused_qty") if it.get("unused_qty") is not None else it.get("unusedQty")
if qty is None or Decimal(str(qty)) <= 0:
@@ -396,10 +489,14 @@ def save_unused_lines(
qty_dec = Decimal(str(qty))
stock_in_date = _parse_optional_date(it.get("stock_in_date") or it.get("stockInDate"))
expire_date = _parse_optional_date(it.get("expire_date") or it.get("expireDate"))
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip() or None
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip() or None
row = BizProductionMaterialStockCheckUnusedLine(
id=generate_uuid(),
check_id=check_id,
usage_id=usage_id,
batch_id=batch_id,
material_type=(it.get("material_type") or it.get("materialType") or "").strip() or None,
material_code=(it.get("material_code") or it.get("materialCode") or "").strip() or None,
material_name=name,
@@ -169,6 +169,7 @@ def _row_to_dict(
"requisitionReceiverName": req_receiver_name,
"purpose": purpose,
"sourceType": r.source_type or "",
"requisitionStatus": (getattr(r, "requisition_status", None) or "open").strip() or "open",
"useTime": create_time if is_manual_out else "",
"remark": _display_remark(r),
"createBy": create_by,
@@ -891,3 +892,172 @@ def register_step_usage_from_requisition(
user_id=user_id,
dept_id=dept_id,
)
def _step_consumed_qty_map(
db: Session,
tenant_no: str,
parent_usage_ids: List[str],
) -> Dict[str, float]:
ids = [x for x in parent_usage_ids if x]
if not ids:
return {}
rows = (
db.query(
BizProductionMaterialUsage.parent_usage_id,
func.coalesce(func.sum(func.abs(BizProductionMaterialUsage.change_qty)), 0),
)
.filter(
BizProductionMaterialUsage.tenant_no == tenant_no,
BizProductionMaterialUsage.del_flag == 0,
BizProductionMaterialUsage.parent_usage_id.in_(ids),
BizProductionMaterialUsage.change_type == "use",
BizProductionMaterialUsage.source_type == "step_save",
)
.group_by(BizProductionMaterialUsage.parent_usage_id)
.all()
)
return {pid: float(qty or 0) for pid, qty in rows if pid}
def _fmt_date_val(v) -> str:
if v is None:
return ""
if hasattr(v, "strftime"):
return v.strftime("%Y-%m-%d")
return str(v)[:10]
def list_stock_check_requisitions(
db: Session,
tenant_no: str,
*,
page: int = 1,
page_size: int = 50,
keyword: Optional[str] = None,
user_info=None,
) -> Tuple[List[Dict[str, Any]], int]:
"""盘点登记弹窗:待处理领用记录(未标记已使用完)。"""
q0 = db.query(BizProductionMaterialUsage).filter(
BizProductionMaterialUsage.tenant_no == tenant_no,
BizProductionMaterialUsage.del_flag == 0,
BizProductionMaterialUsage.change_type == "use",
BizProductionMaterialUsage.source_type == "manual_out",
BizProductionMaterialUsage.requisition_status == "open",
)
if user_info:
from app.core.data_scope import apply_data_scope
q0 = apply_data_scope(q0, BizProductionMaterialUsage, user_info, db, tenant_no)
kw = (keyword or "").strip()
if kw:
like = f"%{kw}%"
q0 = q0.filter(
or_(
BizProductionMaterialUsage.material_code.like(like),
BizProductionMaterialUsage.material_name.like(like),
BizProductionMaterialUsage.stock_in_no.like(like),
BizProductionMaterialUsage.batch_no.like(like),
BizProductionMaterialUsage.catalog_no.like(like),
BizProductionMaterialUsage.receiver.like(like),
)
)
total = q0.order_by(None).with_entities(func.count(BizProductionMaterialUsage.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 200)
rows = (
q0.order_by(BizProductionMaterialUsage.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
)
bmap = _batch_map(db, [x.batch_id for x in rows if x.batch_id])
name_map = _user_nick_name_map(db, [x.create_by for x in rows if x.create_by])
receivers = []
for r in rows:
rcv, _ = _resolve_receiver_purpose(r)
if rcv:
receivers.append(rcv)
receiver_map = _receiver_display_map(db, receivers)
consumed_map = _step_consumed_qty_map(db, tenant_no, [x.id for x in rows])
out: List[Dict[str, Any]] = []
for r in rows:
batch = bmap.get(r.batch_id or "")
rcv, purpose = _resolve_receiver_purpose(r)
rcv_name = receiver_map.get(rcv, rcv) if rcv else ""
qty_abs = abs(float(r.change_qty or 0))
unit = _usage_unit_label(r, batch)
use_time = r.create_time.strftime("%Y-%m-%d %H:%M:%S") if r.create_time else ""
task_consumed = consumed_map.get(r.id, 0)
out.append(
{
"id": r.id,
"materialId": r.material_id,
"materialType": r.material_type or "",
"materialCode": r.material_code or "",
"materialName": r.material_name or "",
"specModel": (batch.spec_model if batch else "") or "",
"batchId": r.batch_id or "",
"stockInNo": r.stock_in_no or "",
"stockInDate": _stock_in_date_for_row(r, batch),
"expireDate": _fmt_date_val(batch.expire_date if batch else None),
"catalogNo": r.catalog_no or "",
"batchNo": r.batch_no or "",
"manufacturer": r.manufacturer or "",
"storageLocation": (r.storage_location or "").strip() or (batch.storage_location if batch else "") or "",
"unitPrice": _unit_price_for_row(r, batch),
"unit": unit,
"requisitionQty": qty_abs,
"taskConsumedQty": task_consumed,
"receiver": rcv,
"receiverName": rcv_name,
"purpose": purpose,
"useTime": use_time,
"requisitionStatus": (r.requisition_status or "open").strip() or "open",
"createByName": name_map.get(r.create_by or "", r.create_by or ""),
}
)
return out, int(total)
def mark_requisition_fully_used(
db: Session,
usage_id: str,
*,
tenant_no: str,
user_id: Optional[str] = None,
user_info=None,
) -> None:
row = (
db.query(BizProductionMaterialUsage)
.filter(
BizProductionMaterialUsage.id == usage_id,
BizProductionMaterialUsage.tenant_no == tenant_no,
BizProductionMaterialUsage.del_flag == 0,
BizProductionMaterialUsage.change_type == "use",
BizProductionMaterialUsage.source_type == "manual_out",
)
.first()
)
if not row:
raise ValueError("领用记录不存在或不可标记")
if user_info:
from app.core.data_scope import apply_data_scope
scoped = apply_data_scope(
db.query(BizProductionMaterialUsage).filter(BizProductionMaterialUsage.id == usage_id),
BizProductionMaterialUsage,
user_info,
db,
tenant_no,
)
if not scoped.first():
raise PermissionError("无权操作该领用记录")
if (row.requisition_status or "open") == "closed":
return
now = datetime.now()
row.requisition_status = "closed"
row.update_by = user_id
row.update_time = now
db.add(row)
db.commit()
@@ -16,6 +16,7 @@ from app.models.qc_material import (
BizQcMaterialStockCheck,
BizQcMaterialStockCheckBatchLine,
BizQcMaterialStockCheckUnusedLine,
BizQcMaterialUsage,
)
@@ -71,6 +72,8 @@ def _unused_line_to_dict(row: BizQcMaterialStockCheckUnusedLine) -> Dict[str, An
return {
"id": row.id,
"checkId": row.check_id,
"usageId": row.usage_id or "",
"batchId": row.batch_id or "",
"materialCode": row.material_code or "",
"materialName": row.material_name or "",
"specModel": row.spec_model or "",
@@ -352,6 +355,90 @@ def _parse_optional_date(v: Any) -> Optional[Any]:
return _parse_date(v, label="日期")
def _resolve_unused_item_fields(
db: Session,
it: Dict[str, Any],
tenant_no: str,
) -> Dict[str, Any]:
"""根据 usage_id / batch_id 补全登记行快照字段。"""
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip()
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip()
out = dict(it)
if usage_id:
usage = (
db.query(BizQcMaterialUsage)
.filter(
BizQcMaterialUsage.id == usage_id,
BizQcMaterialUsage.tenant_no == tenant_no,
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.source_type == "manual_out",
)
.first()
)
if not usage:
raise ValueError("关联领用记录不存在")
batch = None
if usage.batch_id:
batch = (
db.query(BizQcMaterialStockBatch)
.filter(
BizQcMaterialStockBatch.id == usage.batch_id,
BizQcMaterialStockBatch.tenant_no == tenant_no,
BizQcMaterialStockBatch.del_flag == 0,
)
.first()
)
out.setdefault("material_code", usage.material_code or "")
out.setdefault("material_name", usage.material_name or "")
out.setdefault("spec_model", (batch.spec_model if batch else "") or "")
out.setdefault("unit", (batch.unit if batch else "") or usage.usage_unit or "")
out.setdefault("stock_in_no", usage.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch and batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch and batch.expire_date else "")
out.setdefault("catalog_no", usage.catalog_no or "")
out.setdefault("batch_no", usage.batch_no or "")
out.setdefault("manufacturer", usage.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
up = float(usage.unit_price) if usage.unit_price is not None else None
if up is not None:
out["unit_price"] = up
rcv = (usage.receiver or "").strip()
if rcv and not (out.get("holder") or "").strip():
out["holder"] = rcv
if batch and not batch_id:
out["batch_id"] = batch.id
return out
if batch_id:
batch = (
db.query(BizQcMaterialStockBatch)
.filter(
BizQcMaterialStockBatch.id == batch_id,
BizQcMaterialStockBatch.tenant_no == tenant_no,
BizQcMaterialStockBatch.del_flag == 0,
)
.first()
)
if not batch:
raise ValueError("关联入库批次不存在")
out.setdefault("material_code", batch.material_code or "")
out.setdefault("material_name", batch.material_name or "")
out.setdefault("spec_model", batch.spec_model or "")
out.setdefault("unit", batch.unit or "")
out.setdefault("stock_in_no", batch.stock_in_no or "")
out.setdefault("stock_in_date", _fmt_date(batch.stock_in_date) if batch.stock_in_date else "")
out.setdefault("expire_date", _fmt_date(batch.expire_date) if batch.expire_date else "")
out.setdefault("catalog_no", batch.catalog_no or "")
out.setdefault("batch_no", batch.batch_no or "")
out.setdefault("manufacturer", batch.manufacturer or "")
if out.get("unit_price") is None and out.get("unitPrice") is None:
out["unit_price"] = float(batch.unit_price) if batch.unit_price is not None else None
return out
return out
def save_unused_lines(
db: Session,
check_id: str,
@@ -384,6 +471,7 @@ def save_unused_lines(
count = 0
for it in items or []:
it = _resolve_unused_item_fields(db, it, tenant_no)
name = _require_str(it.get("material_name") or it.get("materialName"), "物料名称")
qty = it.get("unused_qty") if it.get("unused_qty") is not None else it.get("unusedQty")
if qty is None or Decimal(str(qty)) <= 0:
@@ -391,10 +479,14 @@ def save_unused_lines(
qty_dec = Decimal(str(qty))
stock_in_date = _parse_optional_date(it.get("stock_in_date") or it.get("stockInDate"))
expire_date = _parse_optional_date(it.get("expire_date") or it.get("expireDate"))
usage_id = (it.get("usage_id") or it.get("usageId") or "").strip() or None
batch_id = (it.get("batch_id") or it.get("batchId") or "").strip() or None
row = BizQcMaterialStockCheckUnusedLine(
id=generate_uuid(),
check_id=check_id,
usage_id=usage_id,
batch_id=batch_id,
material_code=(it.get("material_code") or it.get("materialCode") or "").strip() or None,
material_name=name,
spec_model=(it.get("spec_model") or it.get("specModel") or "").strip() or None,
+232 -7
View File
@@ -163,6 +163,7 @@ def _row_to_dict(
"requisitionReceiverName": req_receiver_name,
"purpose": purpose,
"sourceType": r.source_type or "",
"requisitionStatus": (getattr(r, "requisition_status", None) or "open").strip() or "open",
"useTime": create_time if is_manual_out else "",
"remark": _display_remark(r),
"createBy": create_by,
@@ -172,6 +173,39 @@ def _row_to_dict(
}
def _linked_qc_task_no_map(
db: Session,
tenant_no: str,
parent_usage_ids: List[str],
) -> Dict[str, str]:
"""领用记录(manual_out)关联的质检任务号,聚合为 parent_usage_id → 任务号列表。"""
ids = [x for x in parent_usage_ids if x]
if not ids:
return {}
rows = (
db.query(BizQcMaterialUsage.parent_usage_id, BizQcMaterialUsage.qc_task_no)
.filter(
BizQcMaterialUsage.tenant_no == tenant_no,
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.parent_usage_id.in_(ids),
BizQcMaterialUsage.change_type == "use",
BizQcMaterialUsage.source_type == "task_complete",
)
.order_by(BizQcMaterialUsage.create_time.asc())
.all()
)
grouped: Dict[str, List[str]] = {}
for pid, tno in rows:
pid = (pid or "").strip()
tno = (tno or "").strip()
if not pid or not tno:
continue
grouped.setdefault(pid, [])
if tno not in grouped[pid]:
grouped[pid].append(tno)
return {pid: "、".join(nos) for pid, nos in grouped.items()}
def _batch_map(db: Session, batch_ids: List[str]) -> Dict[str, BizQcMaterialStockBatch]:
ids = [x for x in batch_ids if x]
if not ids:
@@ -246,6 +280,15 @@ def _list_usages_query(
q0 = q0.filter(BizQcMaterialUsage.change_type == "in")
elif ct == "discard":
q0 = q0.filter(BizQcMaterialUsage.change_type == "discard")
# 任务消耗子流水(parent_usage_id 有值)仅在「任务使用」筛选下展示,避免与领用行重复
if ct != "use":
q0 = q0.filter(
or_(
BizQcMaterialUsage.source_type != "task_complete",
BizQcMaterialUsage.parent_usage_id.is_(None),
BizQcMaterialUsage.parent_usage_id == "",
)
)
sno = (stock_in_no or "").strip()
if sno:
q0 = q0.filter(BizQcMaterialUsage.stock_in_no.like(f"%{sno}%"))
@@ -272,7 +315,14 @@ def _list_usages_query(
return q0
def _paginate_usages(db: Session, q0, *, page: int, page_size: int) -> Tuple[List[Dict[str, Any]], int]:
def _paginate_usages(
db: Session,
q0,
*,
tenant_no: str,
page: int,
page_size: int,
) -> Tuple[List[Dict[str, Any]], int]:
total = q0.order_by(None).with_entities(func.count(BizQcMaterialUsage.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 100)
@@ -290,8 +340,11 @@ def _paginate_usages(db: Session, q0, *, page: int, page_size: int) -> Tuple[Lis
if rcv:
receivers.append(rcv)
receiver_map = _receiver_display_map(db, receivers)
return [
_row_to_dict(
manual_out_ids = [x.id for x in rows if (x.source_type or "") == "manual_out"]
linked_task_no_map = _linked_qc_task_no_map(db, tenant_no, manual_out_ids)
out: List[Dict[str, Any]] = []
for x in rows:
row_dict = _row_to_dict(
x,
create_by_name=name_map.get(x.create_by or "", ""),
batch=bmap.get(x.batch_id or ""),
@@ -299,8 +352,12 @@ def _paginate_usages(db: Session, q0, *, page: int, page_size: int) -> Tuple[Lis
(_resolve_receiver_purpose(x)[0] or ""), _resolve_receiver_purpose(x)[0] or ""
),
)
for x in rows
], int(total)
if (x.source_type or "") == "manual_out":
linked = linked_task_no_map.get(x.id, "")
if linked:
row_dict["qcTaskNo"] = linked
out.append(row_dict)
return out, int(total)
def list_usages(
@@ -328,7 +385,7 @@ def list_usages(
stock_in_no=stock_in_no,
user_info=user_info,
)
return _paginate_usages(db, q0, page=page, page_size=page_size)
return _paginate_usages(db, q0, tenant_no=tenant_no, page=page, page_size=page_size)
def list_my_usages(
@@ -359,7 +416,7 @@ def list_my_usages(
mine_user_id=user_id,
mine_nick_name=nick_name,
)
return _paginate_usages(db, q0, page=page, page_size=page_size)
return _paginate_usages(db, q0, tenant_no=tenant_no, page=page, page_size=page_size)
def list_usages_by_task(
@@ -551,6 +608,7 @@ def list_requisition_options(
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.change_type == "use",
BizQcMaterialUsage.source_type == "manual_out",
BizQcMaterialUsage.requisition_status == "open",
)
if user_info:
from app.core.data_scope import apply_data_scope
@@ -851,3 +909,170 @@ def deduct_for_task(
user_id=user_id,
dept_id=dept_id,
)
def _task_consumed_qty_map(
db: Session,
tenant_no: str,
parent_usage_ids: List[str],
) -> Dict[str, float]:
ids = [x for x in parent_usage_ids if x]
if not ids:
return {}
rows = (
db.query(
BizQcMaterialUsage.parent_usage_id,
func.coalesce(func.sum(func.abs(BizQcMaterialUsage.change_qty)), 0),
)
.filter(
BizQcMaterialUsage.tenant_no == tenant_no,
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.parent_usage_id.in_(ids),
BizQcMaterialUsage.change_type == "use",
BizQcMaterialUsage.source_type == "task_complete",
)
.group_by(BizQcMaterialUsage.parent_usage_id)
.all()
)
return {pid: float(qty or 0) for pid, qty in rows if pid}
def _fmt_date_val(v) -> str:
if v is None:
return ""
if hasattr(v, "strftime"):
return v.strftime("%Y-%m-%d")
return str(v)[:10]
def list_stock_check_requisitions(
db: Session,
tenant_no: str,
*,
page: int = 1,
page_size: int = 50,
keyword: Optional[str] = None,
user_info=None,
) -> Tuple[List[Dict[str, Any]], int]:
"""盘点登记弹窗:待处理领用记录(未标记已使用完)。"""
q0 = db.query(BizQcMaterialUsage).filter(
BizQcMaterialUsage.tenant_no == tenant_no,
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.change_type == "use",
BizQcMaterialUsage.source_type == "manual_out",
BizQcMaterialUsage.requisition_status == "open",
)
if user_info:
from app.core.data_scope import apply_data_scope
q0 = apply_data_scope(q0, BizQcMaterialUsage, user_info, db, tenant_no)
kw = (keyword or "").strip()
if kw:
like = f"%{kw}%"
q0 = q0.filter(
or_(
BizQcMaterialUsage.material_code.like(like),
BizQcMaterialUsage.material_name.like(like),
BizQcMaterialUsage.stock_in_no.like(like),
BizQcMaterialUsage.batch_no.like(like),
BizQcMaterialUsage.catalog_no.like(like),
BizQcMaterialUsage.receiver.like(like),
)
)
total = q0.order_by(None).with_entities(func.count(BizQcMaterialUsage.id)).scalar() or 0
page = max(1, page)
page_size = min(max(1, page_size), 200)
rows = (
q0.order_by(BizQcMaterialUsage.create_time.desc())
.offset((page - 1) * page_size)
.limit(page_size)
.all()
)
bmap = _batch_map(db, [x.batch_id for x in rows if x.batch_id])
name_map = _user_nick_name_map(db, [x.create_by for x in rows if x.create_by])
receivers = []
for r in rows:
rcv, _ = _resolve_receiver_purpose(r)
if rcv:
receivers.append(rcv)
receiver_map = _receiver_display_map(db, receivers)
consumed_map = _task_consumed_qty_map(db, tenant_no, [x.id for x in rows])
out: List[Dict[str, Any]] = []
for r in rows:
batch = bmap.get(r.batch_id or "")
rcv, purpose = _resolve_receiver_purpose(r)
rcv_name = receiver_map.get(rcv, rcv) if rcv else ""
qty_abs = abs(float(r.change_qty or 0))
unit = _usage_unit_label(r, batch)
use_time = r.create_time.strftime("%Y-%m-%d %H:%M:%S") if r.create_time else ""
task_consumed = consumed_map.get(r.id, 0)
out.append(
{
"id": r.id,
"materialId": r.material_id,
"materialCode": r.material_code or "",
"materialName": r.material_name or "",
"specModel": (batch.spec_model if batch else "") or "",
"batchId": r.batch_id or "",
"stockInNo": r.stock_in_no or "",
"stockInDate": _stock_in_date_for_row(r, batch),
"expireDate": _fmt_date_val(batch.expire_date if batch else None),
"catalogNo": r.catalog_no or "",
"batchNo": r.batch_no or "",
"manufacturer": r.manufacturer or "",
"unitPrice": _unit_price_for_row(r, batch),
"unit": unit,
"requisitionQty": qty_abs,
"taskConsumedQty": task_consumed,
"receiver": rcv,
"receiverName": rcv_name,
"purpose": purpose,
"useTime": use_time,
"requisitionStatus": (r.requisition_status or "open").strip() or "open",
"createByName": name_map.get(r.create_by or "", r.create_by or ""),
}
)
return out, int(total)
def mark_requisition_fully_used(
db: Session,
usage_id: str,
*,
tenant_no: str,
user_id: Optional[str] = None,
user_info=None,
) -> None:
row = (
db.query(BizQcMaterialUsage)
.filter(
BizQcMaterialUsage.id == usage_id,
BizQcMaterialUsage.tenant_no == tenant_no,
BizQcMaterialUsage.del_flag == 0,
BizQcMaterialUsage.change_type == "use",
BizQcMaterialUsage.source_type == "manual_out",
)
.first()
)
if not row:
raise ValueError("领用记录不存在或不可标记")
if user_info:
from app.core.data_scope import apply_data_scope
scoped = apply_data_scope(
db.query(BizQcMaterialUsage).filter(BizQcMaterialUsage.id == usage_id),
BizQcMaterialUsage,
user_info,
db,
tenant_no,
)
if not scoped.first():
raise PermissionError("无权操作该领用记录")
if (row.requisition_status or "open") == "closed":
return
now = datetime.now()
row.requisition_status = "closed"
row.update_by = user_id
row.update_time = now
db.add(row)
db.commit()
@@ -18,6 +18,7 @@ def _row_to_dict(r: BizQcThirdPartyCompany) -> Dict[str, Any]:
"companyName": r.company_name,
"contactName": r.contact_name or "",
"contactPhone": r.contact_phone or "",
"companyLogo": r.company_logo or "",
"address": r.address or "",
"invoiceTitle": r.invoice_title or "",
"taxId": r.tax_id or "",
@@ -126,6 +127,7 @@ def create_company(
company_name: str,
contact_name: Optional[str] = None,
contact_phone: Optional[str] = None,
company_logo: Optional[str] = None,
address: Optional[str] = None,
invoice_title: Optional[str] = None,
tax_id: Optional[str] = None,
@@ -155,6 +157,7 @@ def create_company(
company_name=name,
contact_name=(contact_name or "").strip() or None,
contact_phone=(contact_phone or "").strip() or None,
company_logo=(company_logo or "").strip() or None,
address=(address or "").strip() or None,
invoice_title=(invoice_title or "").strip() or None,
tax_id=(tax_id or "").strip() or None,
@@ -185,6 +188,7 @@ def update_company(
company_name: Optional[str] = None,
contact_name: Optional[str] = None,
contact_phone: Optional[str] = None,
company_logo: Optional[str] = None,
address: Optional[str] = None,
invoice_title: Optional[str] = None,
tax_id: Optional[str] = None,
@@ -215,6 +219,8 @@ def update_company(
obj.contact_name = (contact_name or "").strip() or None
if contact_phone is not None:
obj.contact_phone = (contact_phone or "").strip() or None
if company_logo is not None:
obj.company_logo = (company_logo or "").strip() or None
if address is not None:
obj.address = (address or "").strip() or None
if invoice_title is not None:
+6
View File
@@ -23,6 +23,7 @@ def _row_to_dict(s: SysSite) -> Dict[str, Any]:
"contactName": s.contact_name or "",
"contactPhone": s.contact_phone or "",
"businessScope": s.business_scope or "",
"siteImage": s.site_image or "",
"tenantNo": s.tenant_no,
"orderNum": s.order_num if s.order_num is not None else 0,
"remark": s.remark or "",
@@ -92,6 +93,7 @@ def create_site(
contact_name: Optional[str] = None,
contact_phone: Optional[str] = None,
business_scope: Optional[str] = None,
site_image: Optional[str] = None,
tenant_no: str = "zkxw",
order_num: Optional[int] = None,
remark: Optional[str] = None,
@@ -112,6 +114,7 @@ def create_site(
contact_name=(contact_name or "").strip() or None,
contact_phone=(contact_phone or "").strip() or None,
business_scope=(business_scope or "").strip() or None,
site_image=(site_image or "").strip() or None,
tenant_no=tenant_no,
order_num=order_num if order_num is not None else 0,
remark=(remark or "").strip() or None,
@@ -140,6 +143,7 @@ def update_site(
contact_name: Optional[str] = None,
contact_phone: Optional[str] = None,
business_scope: Optional[str] = None,
site_image: Optional[str] = None,
order_num: Optional[int] = None,
remark: Optional[str] = None,
user_id: Optional[str] = None,
@@ -168,6 +172,8 @@ def update_site(
obj.contact_phone = (contact_phone or "").strip() or None
if business_scope is not None:
obj.business_scope = (business_scope or "").strip() or None
if site_image is not None:
obj.site_image = (site_image or "").strip() or None
if order_num is not None:
obj.order_num = order_num
if remark is not None:
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_pilot_service_py", "label": "pilot_service.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L1"}, {"id": "crud_pilot_service_normalize_date_bound", "label": "_normalize_date_bound()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L39"}, {"id": "crud_pilot_service_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L46"}, {"id": "crud_pilot_service_row_to_dict_cell_product_type", "label": "_row_to_dict_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L58"}, {"id": "crud_pilot_service_list_cell_product_types", "label": "list_cell_product_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L71"}, {"id": "crud_pilot_service_get_cell_product_type", "label": "get_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L97"}, {"id": "crud_pilot_service_cell_product_type_code_exists", "label": "cell_product_type_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L104"}, {"id": "crud_pilot_service_create_cell_product_type", "label": "create_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L115"}, {"id": "crud_pilot_service_update_cell_product_type", "label": "update_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L137"}, {"id": "crud_pilot_service_soft_delete_cell_product_type", "label": "soft_delete_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L159"}, {"id": "crud_pilot_service_row_to_dict_cell_product_spec", "label": "_row_to_dict_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L173"}, {"id": "crud_pilot_service_list_cell_product_specs", "label": "list_cell_product_specs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L186"}, {"id": "crud_pilot_service_get_cell_product_spec", "label": "get_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L212"}, {"id": "crud_pilot_service_cell_product_spec_code_exists", "label": "cell_product_spec_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L219"}, {"id": "crud_pilot_service_create_cell_product_spec", "label": "create_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L230"}, {"id": "crud_pilot_service_update_cell_product_spec", "label": "update_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L252"}, {"id": "crud_pilot_service_soft_delete_cell_product_spec", "label": "soft_delete_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L274"}, {"id": "crud_pilot_service_row_to_dict_cell_product_price", "label": "_row_to_dict_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L288"}, {"id": "crud_pilot_service_list_cell_product_prices", "label": "list_cell_product_prices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L307"}, {"id": "crud_pilot_service_get_cell_product_price", "label": "get_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L336"}, {"id": "crud_pilot_service_cell_product_price_code_exists", "label": "cell_product_price_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py", "source_location": "L343"}, {"id": "crud_pilot_service_create_cell_product_price", "label": "create_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/baLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "label": "qc_material.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L1"}, {"id": "models_qc_material_bizqcmaterial", "label": "BizQcMaterial", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L8"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_qc_material_bizqcmaterialstockbatch", "label": "BizQcMaterialStockBatch", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L30"}, {"id": "models_qc_material_bizqcmaterialusage", "label": "BizQcMaterialUsage", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L60"}, {"id": "models_qc_material_bizqcmaterialstockcheck", "label": "BizQcMaterialStockCheck", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L105"}, {"id": "models_qc_material_bizqcmaterialstockcheckbatchline", "label": "BizQcMaterialStockCheckBatchLine", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L124"}, {"id": "models_qc_material_bizqcmaterialstockcheckunusedline", "label": "BizQcMaterialStockCheckUnusedLine", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L155"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L1", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L3", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "app_core_database", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "models_qc_material_bizqcmaterial", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L8", "weight": 1.0}, {"source": "models_qc_material_bizqcmaterial", "target": "base", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "models_qc_material_bizqcmaterialstockbatch", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L30", "weight": 1.0}, {"source": "models_qc_material_bizqcmaterialstockbatch", "target": "base", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L30", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "models_qc_material_bizqcmaterialusage", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L60", "weight": 1.0}, {"source": "models_qc_material_bizqcmaterialusage", "target": "base", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L60", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "models_qc_material_bizqcmaterialstockcheck", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L105", "weight": 1.0}, {"source": "models_qc_material_bizqcmaterialstockcheck", "target": "base", "relation": "inherits", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py", "source_location": "L105", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_models_qc_material_py", "target": "models_qc_material_bizqcmaterialstockcheckbatchline", "relation": "contains", "confidence": "EXTRACTED", "source_fiLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_basic_info_py", "label": "basic_info.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L1"}, {"id": "api_basic_info_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L31"}, {"id": "api_basic_info_customercreatebody", "label": "CustomerCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L46"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_basic_info_customerupdatebody", "label": "CustomerUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L59"}, {"id": "api_basic_info_normalize_date_bound", "label": "_normalize_date_bound()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L72"}, {"id": "api_basic_info_list_customers", "label": "list_customers()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L80"}, {"id": "api_basic_info_create_customer", "label": "create_customer()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L123"}, {"id": "api_basic_info_update_customer", "label": "update_customer()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L149"}, {"id": "api_basic_info_delete_customer", "label": "delete_customer()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L178"}, {"id": "api_basic_info_cellsampletypecreatebody", "label": "CellSampleTypeCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L196"}, {"id": "api_basic_info_cellsampletypeupdatebody", "label": "CellSampleTypeUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L208"}, {"id": "api_basic_info_list_cell_sample_types", "label": "list_cell_sample_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L221"}, {"id": "api_basic_info_create_cell_sample_type", "label": "create_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L252"}, {"id": "api_basic_info_update_cell_sample_type", "label": "update_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L277"}, {"id": "api_basic_info_delete_cell_sample_type", "label": "delete_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L305"}, {"id": "api_basic_info_collectionregioncreatebody", "label": "CollectionRegionCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L323"}, {"id": "api_basic_info_collectionregionupdatebody", "label": "CollectionRegionUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L331"}, {"id": "api_basic_info_list_collection_regions", "label": "list_collection_regions()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L340"}, {"id": "api_basic_info_create_collection_region", "label": "create_collection_region()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L367"}, {"id": "api_basic_info_update_collection_region", "label": "update_collection_region()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L388"}, {"id": "api_basic_info_delete_collection_region", "label": "delete_collection_region()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L412"}, {"id": "api_basic_info_hospitalcreatebody", "label": "HospitalCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L430"}, {"id": "api_basic_info_hospitalupdatebody", "label": "HospitalUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py", "source_location": "L438"}, {"id": "api_bLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L298"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L321"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L342"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L360"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L379"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L401"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L421"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L449"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L468"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L299"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L322"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L343"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L361"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L380"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L402"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L422"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L450"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L469"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "label": "cell_sample_type.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L1"}, {"id": "crud_cell_sample_type_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L15"}, {"id": "crud_cell_sample_type_type_code_exists", "label": "type_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L32"}, {"id": "crud_cell_sample_type_list_cell_sample_types", "label": "list_cell_sample_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L44"}, {"id": "crud_cell_sample_type_get_cell_sample_type", "label": "get_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L75"}, {"id": "crud_cell_sample_type_create_cell_sample_type", "label": "create_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L82"}, {"id": "crud_cell_sample_type_update_cell_sample_type", "label": "update_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L123"}, {"id": "crud_cell_sample_type_soft_delete_cell_sample_type", "label": "soft_delete_cell_sample_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L167"}, {"id": "crud_cell_sample_type_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L177"}, {"id": "crud_cell_sample_type_rationale_1", "label": "\u7ec6\u80de\u6837\u672c\u7c7b\u578b CRUD\uff08biz_cell_sample_type\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "crud_cell_sample_type_row_to_dict", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_cell_sample_type_py", "target": "crud_cell_sample_type_type_code_exists", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py", "source_location": "L32", "weight": 1.0}, {"source": "uLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_operations_py", "label": "operations.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L1"}, {"id": "api_operations_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L24"}, {"id": "api_operations_cleanroomcreatebody", "label": "CleanRoomCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L39"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_operations_cleanroomupdatebody", "label": "CleanRoomUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L52"}, {"id": "api_operations_list_clean_rooms", "label": "list_clean_rooms()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L66"}, {"id": "api_operations_create_clean_room", "label": "create_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L91"}, {"id": "api_operations_update_clean_room", "label": "update_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L117"}, {"id": "api_operations_delete_clean_room", "label": "delete_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L146"}, {"id": "api_operations_accesslogcreatebody", "label": "AccessLogCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L164"}, {"id": "api_operations_accesslogupdatebody", "label": "AccessLogUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L178"}, {"id": "api_operations_parse_optional_dt", "label": "_parse_optional_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L191"}, {"id": "api_operations_list_access_logs", "label": "list_access_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L198"}, {"id": "api_operations_create_access_log", "label": "create_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L227"}, {"id": "api_operations_update_access_log", "label": "update_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L254"}, {"id": "api_operations_delete_access_log", "label": "delete_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L283"}, {"id": "api_operations_uvdisinfectlogcreatebody", "label": "UvDisinfectLogCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L301"}, {"id": "api_operations_uvdisinfectlogupdatebody", "label": "UvDisinfectLogUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L313"}, {"id": "api_operations_list_uv_disinfect_logs", "label": "list_uv_disinfect_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L325"}, {"id": "api_operations_create_uv_disinfect_log", "label": "create_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L356"}, {"id": "api_operations_update_uv_disinfect_log", "label": "update_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L381"}, {"id": "api_operations_delete_uv_disinfect_log", "label": "delete_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L409"}, {"id": "api_operations_storagefacilitycreatebody", "label": "StorageFacilityCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L427"}, {"id": "api_operations_storagefacilityupdatebody", "label": "StorageFacilityUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py", "source_location": "L439"}, {"id": "api_operations_list_storage_facilities", "labelLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "label": "express_company.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L1"}, {"id": "crud_express_company_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L15"}, {"id": "crud_express_company_list_express_companies", "label": "list_express_companies()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L29"}, {"id": "crud_express_company_get_express_company", "label": "get_express_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L64"}, {"id": "crud_express_company_express_code_exists", "label": "express_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L72"}, {"id": "crud_express_company_create_express_company", "label": "create_express_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L79"}, {"id": "crud_express_company_update_express_company", "label": "update_express_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L116"}, {"id": "crud_express_company_soft_delete_express_company", "label": "soft_delete_express_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L153"}, {"id": "crud_express_company_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L163"}, {"id": "crud_express_company_rationale_1", "label": "\u5feb\u9012\u516c\u53f8 CRUD\uff08biz_express_company\uff09", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L1"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "crud_express_company_row_to_dict", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_express_company_py", "target": "crud_express_company_list_express_companies", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py", "source_location": "L29", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_exLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_admin_py", "label": "admin.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L1"}, {"id": "api_admin_list_roles_for_select", "label": "list_roles_for_select()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L41"}, {"id": "api_admin_list_users_for_select", "label": "list_users_for_select()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L73"}, {"id": "api_admin_list_roles_for_designer", "label": "list_roles_for_designer()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L88"}, {"id": "api_admin_tenantcreatebody", "label": "TenantCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L108"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_admin_tenantupdatebody", "label": "TenantUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L119"}, {"id": "api_admin_list_tenants", "label": "list_tenants()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L131"}, {"id": "api_admin_create_tenant", "label": "create_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L152"}, {"id": "api_admin_update_tenant", "label": "update_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L174"}, {"id": "api_admin_delete_tenant", "label": "delete_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L199"}, {"id": "api_admin_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L216"}, {"id": "api_admin_usercreatebody", "label": "UserCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L229"}, {"id": "api_admin_userupdatebody", "label": "UserUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L246"}, {"id": "api_admin_list_users", "label": "list_users()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L262"}, {"id": "api_admin_get_user_by_id", "label": "get_user_by_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L306"}, {"id": "api_admin_create_user", "label": "create_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L322"}, {"id": "api_admin_update_user", "label": "update_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L355"}, {"id": "api_admin_delete_user", "label": "delete_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L385"}, {"id": "api_admin_reset_user_password", "label": "reset_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L398"}, {"id": "api_admin_dicttypecreatebody", "label": "DictTypeCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L415"}, {"id": "api_admin_dicttypeupdatebody", "label": "DictTypeUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L424"}, {"id": "api_admin_list_dict_types", "label": "list_dict_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L434"}, {"id": "api_admin_create_dict_type", "label": "create_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L450"}, {"id": "api_admin_update_dict_type", "label": "update_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L472"}, {"id": "api_admin_delete_dict_type", "label": "delete_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L497"}, {"id": "api_admin_dictdatacreatebody", "label": "DictDataCreateBody", "file_type": "code", "sLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_material_usage_py", "label": "qc_material_usage.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L1"}, {"id": "crud_qc_material_usage_parse_receiver_purpose_from_remark", "label": "_parse_receiver_purpose_from_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L18"}, {"id": "crud_qc_material_usage_resolve_receiver_purpose", "label": "_resolve_receiver_purpose()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L30"}, {"id": "crud_qc_material_usage_display_remark", "label": "_display_remark()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L40"}, {"id": "crud_qc_material_usage_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L56"}, {"id": "crud_qc_material_usage_receiver_display_map", "label": "_receiver_display_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L64"}, {"id": "crud_qc_material_usage_usage_unit_label", "label": "_usage_unit_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L76"}, {"id": "crud_qc_material_usage_stock_in_date_for_row", "label": "_stock_in_date_for_row()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L85"}, {"id": "crud_qc_material_usage_unit_price_for_row", "label": "_unit_price_for_row()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L91"}, {"id": "crud_qc_material_usage_amount_for_row", "label": "_amount_for_row()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L99"}, {"id": "crud_qc_material_usage_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L115"}, {"id": "crud_qc_material_usage_linked_qc_task_no_map", "label": "_linked_qc_task_no_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L176"}, {"id": "crud_qc_material_usage_batch_map", "label": "_batch_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L209"}, {"id": "crud_qc_material_usage_mine_usage_filter", "label": "_mine_usage_filter()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L221"}, {"id": "crud_qc_material_usage_list_usages_query", "label": "_list_usages_query()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L246"}, {"id": "crud_qc_material_usage_paginate_usages", "label": "_paginate_usages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L318"}, {"id": "crud_qc_material_usage_list_usages", "label": "list_usages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L363"}, {"id": "crud_qc_material_usage_list_my_usages", "label": "list_my_usages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L391"}, {"id": "crud_qc_material_usage_list_usages_by_task", "label": "list_usages_by_task()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L422"}, {"id": "crud_qc_material_usage_list_linked_task_usages", "label": "list_linked_task_usages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L479"}, {"id": "crud_qc_material_usage_revert_task_material_usages", "label": "revert_task_material_usages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L529"}, {"id": "crud_qc_material_usage_list_requisition_options", "label": "list_requisition_options()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py", "source_location": "L597"}, {"id": "crud_qc_material_usage_rLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_pilot_service_py", "label": "pilot_service.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L1"}, {"id": "api_pilot_service_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L17"}, {"id": "api_pilot_service_cellproducttypecreatebody", "label": "CellProductTypeCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L32"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_pilot_service_cellproducttypeupdatebody", "label": "CellProductTypeUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L41"}, {"id": "api_pilot_service_list_cell_product_types", "label": "list_cell_product_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L51"}, {"id": "api_pilot_service_create_cell_product_type", "label": "create_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L69"}, {"id": "api_pilot_service_update_cell_product_type", "label": "update_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L91"}, {"id": "api_pilot_service_delete_cell_product_type", "label": "delete_cell_product_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L116"}, {"id": "api_pilot_service_cellproductspeccreatebody", "label": "CellProductSpecCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L134"}, {"id": "api_pilot_service_cellproductspecupdatebody", "label": "CellProductSpecUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L143"}, {"id": "api_pilot_service_list_cell_product_specs", "label": "list_cell_product_specs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L153"}, {"id": "api_pilot_service_create_cell_product_spec", "label": "create_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L171"}, {"id": "api_pilot_service_update_cell_product_spec", "label": "update_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L193"}, {"id": "api_pilot_service_delete_cell_product_spec", "label": "delete_cell_product_spec()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L218"}, {"id": "api_pilot_service_cellproductpricecreatebody", "label": "CellProductPriceCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L236"}, {"id": "api_pilot_service_cellproductpriceupdatebody", "label": "CellProductPriceUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L251"}, {"id": "api_pilot_service_list_cell_product_prices", "label": "list_cell_product_prices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L267"}, {"id": "api_pilot_service_create_cell_product_price", "label": "create_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L292"}, {"id": "api_pilot_service_update_cell_product_price", "label": "update_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L320"}, {"id": "api_pilot_service_delete_cell_product_price", "label": "delete_cell_product_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L351"}, {"id": "api_pilot_service_projectsystemcreatebody", "label": "ProjectSystemCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py", "source_location": "L369"}, {"id": "api_pilot_service_projectsystemupdatebody", "label": "ProjectSystemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/apLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L299"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L322"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L344"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L362"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L381"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L403"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L423"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L451"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L470"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L299"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L322"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L343"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L361"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L380"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L402"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L422"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L450"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L469"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_qc_py", "label": "qc.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L1"}, {"id": "api_qc_thirdpartycompanybody", "label": "ThirdPartyCompanyBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L44"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_qc_thirdpartycompanyupdatebody", "label": "ThirdPartyCompanyUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L62"}, {"id": "api_qc_list_qc_third_party_companies", "label": "list_qc_third_party_companies()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L81"}, {"id": "api_qc_list_qc_third_party_company_options", "label": "list_qc_third_party_company_options()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L103"}, {"id": "api_qc_create_qc_third_party_company", "label": "create_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L117"}, {"id": "api_qc_update_qc_third_party_company", "label": "update_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L152"}, {"id": "api_qc_delete_qc_third_party_company", "label": "delete_qc_third_party_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L189"}, {"id": "api_qc_thirdpartyitembody", "label": "ThirdPartyItemBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L209"}, {"id": "api_qc_thirdpartyitemupdatebody", "label": "ThirdPartyItemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L221"}, {"id": "api_qc_list_qc_third_party_items", "label": "list_qc_third_party_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L234"}, {"id": "api_qc_list_qc_third_party_items_active", "label": "list_qc_third_party_items_active()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L263"}, {"id": "api_qc_create_qc_third_party_item", "label": "create_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L278"}, {"id": "api_qc_update_qc_third_party_item", "label": "update_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L307"}, {"id": "api_qc_delete_qc_third_party_item", "label": "delete_qc_third_party_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L338"}, {"id": "api_qc_labtestitembody", "label": "LabTestItemBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L358"}, {"id": "api_qc_labtestitemupdatebody", "label": "LabTestItemUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L369"}, {"id": "api_qc_itemparambody", "label": "ItemParamBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L383"}, {"id": "api_qc_taskresultbody", "label": "TaskResultBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L388"}, {"id": "api_qc_taskcompletewithresultbody", "label": "TaskCompleteWithResultBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L393"}, {"id": "api_qc_list_qc_lab_test_items", "label": "list_qc_lab_test_items()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L403"}, {"id": "api_qc_list_qc_lab_test_items_active", "label": "list_qc_lab_test_items_active()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L425"}, {"id": "api_qc_create_qc_lab_test_item", "label": "create_qc_lab_test_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L439"}, {"id": "api_qc_update_qc_lab_test_item", "label": "update_qc_lab_test_item()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py", "source_location": "L467"}, {"id": "api_Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "label": "qc_third_party_company.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L1"}, {"id": "crud_qc_third_party_company_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L14"}, {"id": "crud_qc_third_party_company_company_code_exists", "label": "company_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L35"}, {"id": "crud_qc_third_party_company_list_companies", "label": "list_companies()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L51"}, {"id": "crud_qc_third_party_company_list_company_options", "label": "list_company_options()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L95"}, {"id": "crud_qc_third_party_company_get_company", "label": "get_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L112"}, {"id": "crud_qc_third_party_company_create_company", "label": "create_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L123"}, {"id": "crud_qc_third_party_company_update_company", "label": "update_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L183"}, {"id": "crud_qc_third_party_company_soft_delete_company", "label": "soft_delete_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L251"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L7", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L10", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "crud_qc_third_party_company_row_to_dict", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L14", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "crud_qc_third_party_company_company_code_exists", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_third_party_company_py", "target": "crud_qc_third_party_company_list_companies", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py", "source_location": "L51", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_thirdLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_admin_py", "label": "admin.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L1"}, {"id": "api_admin_list_roles_for_select", "label": "list_roles_for_select()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L41"}, {"id": "api_admin_list_users_for_select", "label": "list_users_for_select()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L73"}, {"id": "api_admin_list_roles_for_designer", "label": "list_roles_for_designer()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L88"}, {"id": "api_admin_tenantcreatebody", "label": "TenantCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L108"}, {"id": "basemodel", "label": "BaseModel", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "api_admin_tenantupdatebody", "label": "TenantUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L119"}, {"id": "api_admin_list_tenants", "label": "list_tenants()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L131"}, {"id": "api_admin_create_tenant", "label": "create_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L152"}, {"id": "api_admin_update_tenant", "label": "update_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L174"}, {"id": "api_admin_delete_tenant", "label": "delete_tenant()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L199"}, {"id": "api_admin_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L216"}, {"id": "api_admin_usercreatebody", "label": "UserCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L229"}, {"id": "api_admin_userupdatebody", "label": "UserUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L246"}, {"id": "api_admin_list_users", "label": "list_users()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L262"}, {"id": "api_admin_get_user_by_id", "label": "get_user_by_id()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L306"}, {"id": "api_admin_create_user", "label": "create_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L322"}, {"id": "api_admin_update_user", "label": "update_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L355"}, {"id": "api_admin_delete_user", "label": "delete_user()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L385"}, {"id": "api_admin_reset_user_password", "label": "reset_user_password()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L398"}, {"id": "api_admin_dicttypecreatebody", "label": "DictTypeCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L415"}, {"id": "api_admin_dicttypeupdatebody", "label": "DictTypeUpdateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L424"}, {"id": "api_admin_list_dict_types", "label": "list_dict_types()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L434"}, {"id": "api_admin_create_dict_type", "label": "create_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L450"}, {"id": "api_admin_update_dict_type", "label": "update_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L472"}, {"id": "api_admin_delete_dict_type", "label": "delete_dict_type()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py", "source_location": "L497"}, {"id": "api_admin_dictdatacreatebody", "label": "DictDataCreateBody", "file_type": "code", "sLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L299"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L322"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L344"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L362"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L381"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L403"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L423"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L451"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L470"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_material_stock_check_py", "label": "qc_material_stock_check.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L1"}, {"id": "crud_qc_material_stock_check_user_nick_name_map", "label": "_user_nick_name_map()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L23"}, {"id": "crud_qc_material_stock_check_status_label", "label": "_status_label()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L31"}, {"id": "crud_qc_material_stock_check_batch_line_to_dict", "label": "_batch_line_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L39"}, {"id": "crud_qc_material_stock_check_unused_amount", "label": "_unused_amount()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L63"}, {"id": "crud_qc_material_stock_check_unused_line_to_dict", "label": "_unused_line_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L69"}, {"id": "crud_qc_material_stock_check_check_header_to_dict", "label": "_check_header_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L95"}, {"id": "crud_qc_material_stock_check_get_check", "label": "_get_check()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L119"}, {"id": "crud_qc_material_stock_check_line_counts", "label": "_line_counts()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L131"}, {"id": "crud_qc_material_stock_check_list_checks", "label": "list_checks()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L166"}, {"id": "crud_qc_material_stock_check_get_check_detail", "label": "get_check_detail()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L226"}, {"id": "crud_qc_material_stock_check_parse_check_time", "label": "_parse_check_time()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L261"}, {"id": "crud_qc_material_stock_check_create_check", "label": "create_check()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L275"}, {"id": "crud_qc_material_stock_check_parse_optional_date", "label": "_parse_optional_date()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L352"}, {"id": "crud_qc_material_stock_check_resolve_unused_item_fields", "label": "_resolve_unused_item_fields()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L358"}, {"id": "crud_qc_material_stock_check_save_unused_lines", "label": "save_unused_lines()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L442"}, {"id": "crud_qc_material_stock_check_complete_check", "label": "complete_check()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L526"}, {"id": "crud_qc_material_stock_check_cancel_check", "label": "cancel_check()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L547"}, {"id": "crud_qc_material_stock_check_rationale_363", "label": "\u6839\u636e usage_id / batch_id \u8865\u5168\u767b\u8bb0\u884c\u5feb\u7167\u5b57\u6bb5\u3002", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L363"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_material_stock_check_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_qc_material_stock_check_py", "target": "decimal", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/UsLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_models_models_py", "label": "models.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L1"}, {"id": "models_models_userrole", "label": "UserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L10"}, {"id": "str", "label": "str", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysuser", "label": "SysUser", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L22"}, {"id": "base", "label": "Base", "file_type": "code", "source_file": "", "source_location": ""}, {"id": "models_models_sysrole", "label": "SysRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L48"}, {"id": "models_models_sysuserrole", "label": "SysUserRole", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L68"}, {"id": "models_models_sysrolemenu", "label": "SysRoleMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L87"}, {"id": "models_models_sysroledatascopedetail", "label": "SysRoleDataScopeDetail", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L106"}, {"id": "models_models_sysmenu", "label": "SysMenu", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L126"}, {"id": "models_models_sysdept", "label": "SysDept", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L152"}, {"id": "models_models_systenant", "label": "SysTenant", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L175"}, {"id": "models_models_syssite", "label": "SysSite", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L195"}, {"id": "models_models_syspost", "label": "SysPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L221"}, {"id": "models_models_sysuserpost", "label": "SysUserPost", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L241"}, {"id": "models_models_bizitemunit", "label": "BizItemUnit", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L260"}, {"id": "models_models_bizexpresscompany", "label": "BizExpressCompany", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L279"}, {"id": "models_models_bizcustomer", "label": "BizCustomer", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L299"}, {"id": "models_models_bizcellsampletype", "label": "BizCellSampleType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L322"}, {"id": "models_models_bizcollectionregion", "label": "BizCollectionRegion", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L344"}, {"id": "models_models_bizcollectionhospital", "label": "BizCollectionHospital", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L362"}, {"id": "models_models_bizcollectionprotocolno", "label": "BizCollectionProtocolNo", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L381"}, {"id": "models_models_bizbiznosequence", "label": "BizBizNoSequence", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L403"}, {"id": "models_models_bizsamplecode", "label": "BizSampleCode", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L423"}, {"id": "models_models_sysdicttype", "label": "SysDictType", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L451"}, {"id": "models_models_sysethnic", "label": "SysEthnic", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location": "L470"}, {"id": "models_models_sysdictdata", "label": "SysDictData", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py", "source_location"Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_api_insurance_company_py", "label": "insurance_company.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L1"}, {"id": "api_insurance_company_get_tenant_no", "label": "_get_tenant_no()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L30"}, {"id": "api_insurance_company_generate_uuid", "label": "_generate_uuid()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L40"}, {"id": "api_insurance_company_fmt_dt", "label": "_fmt_dt()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L44"}, {"id": "api_insurance_company_total_pages", "label": "_total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L52"}, {"id": "api_insurance_company_row_to_dict_company", "label": "_row_to_dict_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L61"}, {"id": "api_insurance_company_row_to_dict_invoice", "label": "_row_to_dict_invoice()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L84"}, {"id": "api_insurance_company_row_to_dict_project_price", "label": "_row_to_dict_project_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L105"}, {"id": "api_insurance_company_list_insurance_companies", "label": "_list_insurance_companies()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L128"}, {"id": "api_insurance_company_create_insurance_company", "label": "_create_insurance_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L184"}, {"id": "api_insurance_company_update_insurance_company", "label": "_update_insurance_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L222"}, {"id": "api_insurance_company_soft_delete_insurance_company", "label": "_soft_delete_insurance_company()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L271"}, {"id": "api_insurance_company_list_insurance_company_invoices", "label": "_list_insurance_company_invoices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L292"}, {"id": "api_insurance_company_create_insurance_company_invoice", "label": "_create_insurance_company_invoice()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L319"}, {"id": "api_insurance_company_update_insurance_company_invoice", "label": "_update_insurance_company_invoice()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L359"}, {"id": "api_insurance_company_soft_delete_insurance_company_invoice", "label": "_soft_delete_insurance_company_invoice()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L408"}, {"id": "api_insurance_company_list_insurance_project_prices", "label": "_list_insurance_project_prices()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L429"}, {"id": "api_insurance_company_create_insurance_project_price", "label": "_create_insurance_project_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L455"}, {"id": "api_insurance_company_update_insurance_project_price", "label": "_update_insurance_project_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L489"}, {"id": "api_insurance_company_soft_delete_insurance_project_price", "label": "_soft_delete_insurance_project_price()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L529"}, {"id": "api_insurance_company_insurancecompanycreatebody", "label": "InsuranceCompanyCreateBody", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py", "source_location": "L550"}, {"id": "basemodel", "label": "BaseModel", "file_typeLine truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_clean_room_py", "label": "clean_room.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L1"}, {"id": "crud_clean_room_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L19"}, {"id": "crud_clean_room_list_clean_rooms", "label": "list_clean_rooms()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L36"}, {"id": "crud_clean_room_get_clean_room", "label": "get_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L67"}, {"id": "crud_clean_room_room_code_exists", "label": "room_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L74"}, {"id": "crud_clean_room_create_clean_room", "label": "create_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L83"}, {"id": "crud_clean_room_update_clean_room", "label": "update_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L126"}, {"id": "crud_clean_room_soft_delete_clean_room", "label": "soft_delete_clean_room()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L173"}, {"id": "crud_clean_room_access_log_to_dict", "label": "_access_log_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L187"}, {"id": "crud_clean_room_list_access_logs", "label": "list_access_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L206"}, {"id": "crud_clean_room_get_access_log", "label": "get_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L243"}, {"id": "crud_clean_room_create_access_log", "label": "create_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L250"}, {"id": "crud_clean_room_update_access_log", "label": "update_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L295"}, {"id": "crud_clean_room_soft_delete_access_log", "label": "soft_delete_access_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L337"}, {"id": "crud_clean_room_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L347"}, {"id": "crud_clean_room_calc_duration_minutes", "label": "_calc_duration_minutes()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L357"}, {"id": "crud_clean_room_uv_disinfect_log_to_dict", "label": "_uv_disinfect_log_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L365"}, {"id": "crud_clean_room_list_uv_disinfect_logs", "label": "list_uv_disinfect_logs()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L385"}, {"id": "crud_clean_room_get_uv_disinfect_log", "label": "get_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L419"}, {"id": "crud_clean_room_create_uv_disinfect_log", "label": "create_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L430"}, {"id": "crud_clean_room_update_uv_disinfect_log", "label": "update_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L480"}, {"id": "crud_clean_room_soft_delete_uv_disinfect_log", "label": "soft_delete_uv_disinfect_log()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L531"}, {"id": "crud_clean_room_rationale_1", "label": "\u6d01\u51c0\u5ba4\u53ca\u8fdb\u51fa\u8bb0\u5f55\u3001\u7d2b\u5916\u7ebf\u6d88\u6bd2\u8bb0\u5f55 CRUD\uff08biz_clean_room + biz_clean_room_access_log + biz_clean_roo", "file_type": "rationale", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py", "source_location": "L1"}],Line truncated
@@ -0,0 +1 @@
{"nodes": [{"id": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "label": "site.py", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L1"}, {"id": "crud_site_row_to_dict", "label": "_row_to_dict()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L15"}, {"id": "crud_site_list_sites", "label": "list_sites()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L35"}, {"id": "crud_site_get_site", "label": "get_site()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L70"}, {"id": "crud_site_site_code_exists", "label": "site_code_exists()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L78"}, {"id": "crud_site_create_site", "label": "create_site()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L85"}, {"id": "crud_site_update_site", "label": "update_site()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L134"}, {"id": "crud_site_soft_delete_site", "label": "soft_delete_site()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L189"}, {"id": "crud_site_total_pages", "label": "total_pages()", "file_type": "code", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L199"}], "edges": [{"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "math", "relation": "imports", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L4", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "datetime", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L5", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "typing", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L6", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "sqlalchemy", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L8", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "sqlalchemy_orm", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L9", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "app_core_utils", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L11", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "app_models_models", "relation": "imports_from", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L12", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "crud_site_row_to_dict", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L15", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "crud_site_list_sites", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L35", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "crud_site_get_site", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L70", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "crud_site_site_code_exists", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L78", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backend_app_crud_site_py", "target": "crud_site_create_site", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py", "source_location": "L85", "weight": 1.0}, {"source": "users_wuzilong_work_00code_zkxw_backenLine truncated
+8
View File
@@ -80,6 +80,12 @@ class BizMaterialUsage(Base):
stock_after = Column(Numeric(18, 4), nullable=False, comment="变动后库存量")
receiver = Column(String(64), nullable=True, comment="领用人(手动出库)")
purpose = Column(String(512), nullable=True, comment="用途/事由(手动出库或废弃原因)")
requisition_status = Column(
String(16),
nullable=False,
default="open",
comment="领用状态:open-待登记/有剩余 closed-已使用完",
)
source_type = Column(
String(32),
nullable=False,
@@ -150,6 +156,8 @@ class BizMaterialStockCheckUnusedLine(Base):
id = Column(String(64), primary_key=True, comment="主键ID")
check_id = Column(String(64), nullable=False, comment="盘点单ID")
usage_id = Column(String(64), nullable=True, comment="关联领用记录ID")
batch_id = Column(String(64), nullable=True, comment="关联入库批次ID")
material_code = Column(String(64), nullable=True, comment="物料编码")
material_name = Column(String(200), nullable=False, comment="物料名称")
spec_model = Column(String(200), nullable=True, comment="规格型号")
+7
View File
@@ -206,6 +206,7 @@ class SysSite(Base):
contact_name = Column(String(100), nullable=True, comment="联系人")
contact_phone = Column(String(32), nullable=True, comment="联系电话")
business_scope = Column(String(256), nullable=True, comment="业务范围")
site_image = Column(String(512), nullable=True, comment="站点图片URL")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
@@ -283,6 +284,7 @@ class BizExpressCompany(Base):
id = Column(String(64), primary_key=True, comment="主键ID")
express_code = Column(String(64), nullable=False, comment="快递公司编码")
express_name = Column(String(200), nullable=False, comment="快递公司名称")
express_logo = Column(String(512), nullable=True, comment="快递公司Logo URL")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
@@ -325,6 +327,7 @@ class BizCellSampleType(Base):
id = Column(String(64), primary_key=True, comment="主键ID")
type_code = Column(String(64), nullable=False, comment="样本类型编码")
type_name = Column(String(200), nullable=False, comment="样本类型名称")
type_logo = Column(String(512), nullable=True, comment="样本类型Logo URL")
storage_years = Column(Integer, nullable=True, comment="样本存储年份")
storage_price = Column(Numeric(18, 2), nullable=True, comment="样本存储价格(元)")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
@@ -1207,6 +1210,7 @@ class BizQcThirdPartyCompany(Base):
company_name = Column(String(200), nullable=False, comment="公司名称")
contact_name = Column(String(100), nullable=True, comment="联系人")
contact_phone = Column(String(32), nullable=True, comment="联系电话")
company_logo = Column(String(512), nullable=True, comment="公司Logo URL")
address = Column(String(500), nullable=True, comment="地址")
invoice_title = Column(String(200), nullable=True, comment="发票抬头")
tax_id = Column(String(64), nullable=True, comment="纳税人识别号")
@@ -1430,6 +1434,7 @@ class BizCleanRoom(Base):
room_grade = Column(String(8), nullable=True, comment="等级 A/B/C/D")
room_status = Column(String(16), nullable=False, default="zc", comment="zc正常 yc异常")
area_sqm = Column(Numeric(12, 2), nullable=True, comment="面积m²")
room_image = Column(String(512), nullable=True, comment="洁净室图片URL")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
remark = Column(String(512), nullable=True, comment="备注")
@@ -1982,6 +1987,7 @@ class BizCheckupInstitution(Base):
institution_address = Column(String(512), nullable=True, comment="体检机构地址")
contact_name = Column(String(100), nullable=True, comment="联系人")
contact_phone = Column(String(32), nullable=True, comment="联系人电话")
institution_logo = Column(String(512), nullable=True, comment="体检机构Logo URL")
status = Column(CHAR(1), nullable=False, default="1", comment="1正常 0停用")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
@@ -2874,6 +2880,7 @@ class BizInsuranceCompany(Base):
company_address = Column(String(512), nullable=True, comment="公司地址")
contact_name = Column(String(100), nullable=True, comment="联系人")
contact_phone = Column(String(32), nullable=True, comment="联系电话")
company_logo = Column(String(512), nullable=True, comment="保险公司Logo URL")
status = Column(CHAR(1), nullable=False, default="1", comment="1正常 0停用")
tenant_no = Column(String(64), nullable=False, default="zkxw", comment="租户编号")
order_num = Column(Integer, nullable=True, comment="排序号")
@@ -89,6 +89,12 @@ class BizProductionMaterialUsage(Base):
prep_id = Column(String(64), nullable=True, comment="关联配制单ID")
receiver = Column(String(64), nullable=True, comment="领用人(手动出库)")
purpose = Column(String(512), nullable=True, comment="用途/事由(手动出库)")
requisition_status = Column(
String(16),
nullable=False,
default="open",
comment="领用状态:open-待登记/有剩余 closed-已使用完",
)
source_type = Column(
String(32),
nullable=False,
@@ -234,6 +240,8 @@ class BizProductionMaterialStockCheckUnusedLine(Base):
id = Column(String(64), primary_key=True, comment="主键ID")
check_id = Column(String(64), nullable=False, comment="盘点单ID")
usage_id = Column(String(64), nullable=True, comment="关联领用记录ID")
batch_id = Column(String(64), nullable=True, comment="关联入库批次ID")
material_type = Column(String(32), nullable=True, comment="物料类型")
material_code = Column(String(64), nullable=True, comment="物料编码")
material_name = Column(String(200), nullable=False, comment="物料名称")
+8
View File
@@ -81,6 +81,12 @@ class BizQcMaterialUsage(Base):
parent_usage_id = Column(String(64), nullable=True, comment="关联领用记录ID")
receiver = Column(String(64), nullable=True, comment="领用人(手动出库)")
purpose = Column(String(512), nullable=True, comment="用途/事由(手动出库)")
requisition_status = Column(
String(16),
nullable=False,
default="open",
comment="领用状态:open-待登记 closed-已使用完",
)
source_type = Column(
String(32),
nullable=False,
@@ -151,6 +157,8 @@ class BizQcMaterialStockCheckUnusedLine(Base):
id = Column(String(64), primary_key=True, comment="主键ID")
check_id = Column(String(64), nullable=False, comment="盘点单ID")
usage_id = Column(String(64), nullable=True, comment="关联领用记录ID")
batch_id = Column(String(64), nullable=True, comment="关联入库批次ID")
material_code = Column(String(64), nullable=True, comment="物料编码")
material_name = Column(String(200), nullable=False, comment="物料名称")
spec_model = Column(String(200), nullable=True, comment="规格型号")
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+112 -132
View File
@@ -1,11 +1,11 @@
# Graph Report - app (2026-06-13)
# Graph Report - app (2026-06-14)
## Corpus Check
- Large corpus: 205 files · ~231,501 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
- Large corpus: 205 files · ~233,064 words. Semantic extraction will be expensive (many Claude tokens). Consider running on a subfolder, or use --no-semantic to run AST-only.
## Summary
- 4027 nodes · 20969 edges · 55 communities detected
- Extraction: 33% EXTRACTED · 67% INFERRED · 0% AMBIGUOUS · INFERRED: 14087 edges (avg confidence: 0.6)
- 4040 nodes · 21037 edges · 51 communities detected
- Extraction: 33% EXTRACTED · 67% INFERRED · 0% AMBIGUOUS · INFERRED: 14129 edges (avg confidence: 0.6)
- Token cost: 0 input · 0 output
## Community Hubs (Navigation)
@@ -54,28 +54,24 @@
- [[_COMMUNITY_Community 42|Community 42]]
- [[_COMMUNITY_Community 43|Community 43]]
- [[_COMMUNITY_Community 44|Community 44]]
- [[_COMMUNITY_Community 45|Community 45]]
- [[_COMMUNITY_Community 46|Community 46]]
- [[_COMMUNITY_Community 47|Community 47]]
- [[_COMMUNITY_Community 48|Community 48]]
- [[_COMMUNITY_Community 49|Community 49]]
- [[_COMMUNITY_Community 50|Community 50]]
- [[_COMMUNITY_Community 51|Community 51]]
- [[_COMMUNITY_Community 52|Community 52]]
- [[_COMMUNITY_Community 53|Community 53]]
- [[_COMMUNITY_Community 54|Community 54]]
- [[_COMMUNITY_Community 55|Community 55]]
- [[_COMMUNITY_Community 56|Community 56]]
## God Nodes (most connected - your core abstractions)
1. `success_response()` - 623 edges
2. `error_response()` - 517 edges
3. `SysUser` - 424 edges
4. `BizQcTaskResult` - 287 edges
5. `BizQcMaterialUsage` - 286 edges
1. `success_response()` - 625 edges
2. `error_response()` - 519 edges
3. `SysUser` - 427 edges
4. `BizQcMaterialUsage` - 289 edges
5. `BizQcTaskResult` - 287 edges
6. `BizProductionMaterial` - 284 edges
7. `BizProductionMaterialUsage` - 284 edges
8. `BizQcMaterial` - 280 edges
9. `BizProductionMaterialStockBatch` - 272 edges
10. `BizQcMaterialStockBatch` - 272 edges
8. `BizQcMaterial` - 282 edges
9. `BizQcMaterialStockBatch` - 275 edges
10. `BizProductionMaterialStockBatch` - 272 edges
## Surprising Connections (you probably didn't know these)
- `统一记录 API 请求/响应出入参的中间件` --uses--> `SysApiRequestLog` [INFERRED]
@@ -93,264 +89,248 @@
### Community 0 - "Community 0"
Cohesion: 0.01
Nodes (796): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+788 more)
Nodes (806): attachment_download_url(), create_dept(), create_dict_data(), create_dict_type(), create_express_company(), create_item_unit(), create_menu(), create_post() (+798 more)
### Community 1 - "Community 1"
Cohesion: 0.01
Nodes (570): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+562 more)
Nodes (594): AttachmentDownloadUrlBody, DeptCreateBody, DeptUpdateBody, DictDataCreateBody, DictDataUpdateBody, DictTypeCreateBody, DictTypeUpdateBody, ExpressCompanyCreateBody (+586 more)
### Community 2 - "Community 2"
Cohesion: 0.08
Nodes (370): 环境检测 — 检测项维护 + 登记管理 API, 保险公司及险种价格管理 API(保险公司 + 开票信息 + 险种价格), AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody (+362 more)
Cohesion: 0.07
Nodes (465): AuditCreateBody, BatchDetailIdsBody, BatchRefundFinanceSubmitBody, FinanceConfirmBody, FullmoonTodoInsuranceBody, ProtocolCreateBody, ProtocolUpdateBody, 细胞存储 — 采集协议单 / 审核 / 财务确认 / 分期预警 API (+457 more)
### Community 3 - "Community 3"
Cohesion: 0.01
Nodes (231): _ensure_customer_for_mother(), _persist_protocol_sub_resources(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), _resolve_user_role_scopes(), format_date() (+223 more)
Nodes (255): list_collection_regions(), _persist_protocol_sub_resources(), list_ethnics_for_select(), apply_data_scope(), _get_child_dept_ids(), get_user_dept_id(), _resolve_user_role_scopes(), format_date() (+247 more)
### Community 4 - "Community 4"
Cohesion: 0.01
Nodes (238): generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status() (+230 more)
### Community 5 - "Community 5"
Cohesion: 0.02
Nodes (226): eq_unicode(), like_unicode(), MySQL 字符串比较/模糊匹配时统一排序规则,避免 Illegal mix of collations。, 跨表字符串等值比较(JOIN / WHERE)时统一为 utf8mb4_unicode_ci。, 将列显式设为 utf8mb4_unicode_ci。, unicode_ci(), _format_attachment_file_size(), urls_to_attachment_list() (+218 more)
### Community 5 - "Community 5"
Cohesion: 0.04
Nodes (216): generate_uuid(), batch_stock_in(), batch_stock_out(), consumable_code_exists(), create_consumable(), _dec(), get_consumable(), _is_enabled_status() (+208 more)
### Community 6 - "Community 6"
Cohesion: 0.05
Nodes (196): CellSampleTypeCreateBody, CellSampleTypeUpdateBody, CollectionRegionCreateBody, CollectionRegionUpdateBody, CustomerCreateBody, CustomerUpdateBody, HospitalCreateBody, HospitalUpdateBody (+188 more)
Cohesion: 0.02
Nodes (156): get_protocol_nos_used_in_protocols(), create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), 字典类型 CRUD(sys_dict_type), _row_to_dict(), soft_delete_dict_type() (+148 more)
### Community 7 - "Community 7"
Cohesion: 0.02
Nodes (113): get_designer_data(), _error_json(), lifespan(), 数据库异常:返回 JSON 并保留 CORS 头,避免浏览器只报跨域错误, 未捕获异常:统一 JSON 500,确保跨域场景下仍有 Access-Control-Allow-Origin, sqlalchemy_exception_handler(), unhandled_exception_handler(), BaseHTTPMiddleware (+105 more)
Nodes (106): _business_type_label(), get_business_all_tasks(), _get_business_form_fields(), get_designer_data(), get_instance_detail(), ProcessDefCreateBody, ProcessDefUpdateBody, PublishVersionBody (+98 more)
### Community 8 - "Community 8"
Cohesion: 0.02
Nodes (165): api_save_application(), get_protocol_nos_used_in_protocols(), create_dict_type(), dict_type_code_exists(), get_dict_type(), list_dict_types(), 字典类型 CRUD(sys_dict_type), _row_to_dict() (+157 more)
Cohesion: 0.03
Nodes (140): batch_discard(), batch_options(), _batch_row_to_dict(), batch_stock_in(), batch_stock_out(), _create_batch_and_usage(), delete_batch(), _discard_batch() (+132 more)
### Community 9 - "Community 9"
Cohesion: 0.03
Nodes (143): batch_discard(), batch_options(), _batch_row_to_dict(), batch_stock_in(), batch_stock_out(), _create_batch_and_usage(), delete_batch(), _discard_batch() (+135 more)
Nodes (97): _avatar_url_field(), _build_current_user_payload(), _build_user_info_payload(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线) (+89 more)
### Community 10 - "Community 10"
Cohesion: 0.03
Nodes (98): _avatar_url_field(), _build_current_user_payload(), _build_user_info_payload(), get_current_user_profile(), get_web_auth_menu_codes(), _jwt_user_payload(), logout(), 公共接口(Web 登录、刷新 Token、登出;用户模型对齐 docs/sql/zkxw.sql 基线) (+90 more)
Cohesion: 0.04
Nodes (103): get_next_cell_product_code(), _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes() (+95 more)
### Community 11 - "Community 11"
Cohesion: 0.04
Nodes (99): get_next_cell_product_code(), _ancestor_link_from_cell_product_input(), _ancestor_sample_chain_link(), _apply_cell_product_status_change(), _build_ancestor_chain(), _build_descendant_chain(), _build_facility_path_label(), build_split_product_codes() (+91 more)
Cohesion: 0.06
Nodes (89): AccessLogCreateBody, AccessLogUpdateBody, CleanRoomCreateBody, CleanRoomUpdateBody, ExhibitionAppointmentCreateBody, ExhibitionAppointmentUpdateBody, OccupancyCreateBody, 运营支撑 API(洁净室、进出记录、仓储设施、储位、展厅预约) (+81 more)
### Community 12 - "Community 12"
Cohesion: 0.09
Nodes (45): batch_stock_in(), batch_stock_out(), code_exists(), create_material(), _dec(), _filter_material_type(), _fmt_dt(), get_material() (+37 more)
Cohesion: 0.07
Nodes (55): batch_stock_in(), batch_stock_out(), code_exists(), create_material(), _dec(), _filter_material_type(), _fmt_dt(), get_material() (+47 more)
### Community 13 - "Community 13"
Cohesion: 0.09
Nodes (51): allocate_next_biz_no(), _format_biz_no(), _prefix_for(), 业务协议号自动生成:XBCC / JZCC + YYYYMMDD + 6 位序号, 原子分配下一个业务协议号。 须在 create 事务内调用;使用 MySQL LAST_INSERT_ID 保证并发安全。, create_collection_protocol(), _active_link_query(), assert_biz_no_available() (+43 more)
### Community 14 - "Community 14"
Cohesion: 0.11
Nodes (35): batch_create_sterilize_logs(), batch_create_wash_logs(), batch_discard_garments(), batch_soft_delete_garments(), _count_map(), create_garment(), create_sterilize_log(), create_wash_log() (+27 more)
### Community 14 - "Community 14"
Cohesion: 0.12
Nodes (11): get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.ht, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total, 申请退款 Args: out_trade_no: 商户订单号 total_amount, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 tot, 生成签名 V3 (SHA256 with RSA) (+3 more)
### Community 15 - "Community 15"
Cohesion: 0.16
Nodes (27): set_current_process_route(), add_step(), copy_step(), create_route(), _create_step_consumable(), _create_step_data_collection(), _create_step_output(), _create_step_reagent() (+19 more)
Cohesion: 0.12
Nodes (10): get_wechat_pay_client(), get_wechat_pay_v2(), 微信支付工具模块 支持微信支付 V3 API 文档参考: https://pay.weixin.qq.com/docs/v3/apis/index.ht, 统一下单接口 (V3) Args: out_trade_no: 商户订单号 total, 小程序调起支付的二次签名参数(与公众号 JSAPI 规则一致), 统一下单 (V2 API) Args: out_trade_no: 商户订单号 tot, 生成签名 V3 (SHA256 with RSA), wechat_pay() (+2 more)
### Community 16 - "Community 16"
Cohesion: 0.21
Nodes (23): _amount_for_row(), _batch_map(), deduct_for_task(), _deduct_task_usage_legacy_batch(), _display_remark(), list_linked_task_usages(), list_my_usages(), list_requisition_options() (+15 more)
Cohesion: 0.17
Nodes (12): BusinessException, InvalidStatusTransitionException, log_delivery_operation(), log_operation(), log_order_operation(), log_settlement_operation(), log_user_operation(), OrderLockedException (+4 more)
### Community 17 - "Community 17"
Cohesion: 0.15
Nodes (20): _access_log_to_dict(), _calc_duration_minutes(), create_access_log(), create_clean_room(), create_uv_disinfect_log(), get_access_log(), get_clean_room(), get_uv_disinfect_log() (+12 more)
### Community 18 - "Community 18"
Cohesion: 0.21
Nodes (19): _consumable_row_to_dict(), create_process(), _create_sub_consumable(), _create_sub_data_collection(), _create_sub_output(), _create_sub_reagent(), _data_collection_row_to_dict(), get_process() (+11 more)
### Community 19 - "Community 19"
Cohesion: 0.18
Nodes (18): company_code_exists(), create_company(), get_company(), list_companies(), list_company_options(), _row_to_dict(), soft_delete_company(), update_company() (+10 more)
### Community 20 - "Community 20"
Cohesion: 0.29
Nodes (14): _amount_for_row(), _batch_map(), _display_remark(), list_usages(), _list_usages_query(), _paginate_usages(), _parse_receiver_purpose_from_remark(), _receiver_display_map() (+6 more)
### Community 21 - "Community 21"
### Community 18 - "Community 18"
Cohesion: 0.28
Nodes (14): _code_exists(), create_material(), _dec(), _fmt_dt(), get_material(), get_material_entity(), _is_enabled_status(), list_materials() (+6 more)
### Community 22 - "Community 22"
### Community 19 - "Community 19"
Cohesion: 0.25
Nodes (13): batch_issue_protocol_nos(), batch_revoke_protocol_nos(), create_protocol_no(), get_protocol_no(), list_protocol_nos(), _parse_issued_time(), protocol_no_exists(), 采集协议号池 CRUD(biz_collection_protocol_no) (+5 more)
### Community 20 - "Community 20"
Cohesion: 0.24
Nodes (9): 微信消息通知服务 支持微信小程序模板消息推送 使用方式: from app.core.wechat_message import Wech, 发送模板消息 Args: openid: 用户openid templ, send_delivery_notice(), send_delivery_warning(), send_order_status(), send_payment_success(), send_refund_result(), send_urge_notification() (+1 more)
### Community 23 - "Community 23"
### Community 21 - "Community 21"
Cohesion: 0.23
Nodes (12): Config, ProductBase, ProductCategoryBase, ProductCategoryCreate, ProductCategoryResponse, ProductCreate, ProductResponse, ProductUnitBase (+4 more)
### Community 24 - "Community 24"
### Community 22 - "Community 22"
Cohesion: 0.29
Nodes (11): create_equipment(), _dec(), equipment_code_exists(), get_equipment(), list_equipments(), _norm_status(), _parse_date(), 设备 CRUD(biz_equipment) (+3 more)
### Community 25 - "Community 25"
Cohesion: 0.27
Nodes (11): create_consumable_pack(), get_consumable_pack(), get_pack_detail(), _item_row_to_dict(), list_all_packs(), list_consumable_packs(), pack_code_exists(), 耗材包 CRUD(biz_consumable_pack + biz_consumable_pack_item) (+3 more)
### Community 26 - "Community 26"
### Community 23 - "Community 23"
Cohesion: 0.24
Nodes (12): appointment_no_exists(), create_exhibition_appointment(), _format_visit_date(), _generate_appointment_no(), get_exhibition_appointment(), list_exhibition_appointments(), 展览预约 CRUD(biz_exhibition_appointment), 生成预约编号:YYYYMMDD + 6位序号(如 20260515000001) (+4 more)
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 试剂变动记录 CRUD(biz_reagent_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减试剂库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
### Community 27 - "Community 27"
### Community 24 - "Community 24"
Cohesion: 0.32
Nodes (11): create_env_detect_record(), _generate_record_no(), get_env_detect_record(), _join_csv(), list_env_detect_records(), _resolve_inspector_snapshots(), _resolve_item_snapshot(), _row_to_dict() (+3 more)
### Community 28 - "Community 28"
### Community 25 - "Community 25"
Cohesion: 0.24
Nodes (11): deduct_for_step(), _display_remark(), list_stock_logs(), _parse_receiver_purpose_from_remark(), 耗材变动记录 CRUD(biz_consumable_stock_log), 撤销步骤此前 step_save 扣减,便于重新填报。, 扣减耗材库存并生成变动记录。调用方控制事务,本函数不 commit。, _resolve_receiver_purpose() (+3 more)
### Community 29 - "Community 29"
### Community 26 - "Community 26"
Cohesion: 0.27
Nodes (11): _build_tree(), _cascade_soft_delete(), _collect_with_ancestors(), create_dept(), get_dept(), list_depts(), list_depts_tree(), 保留匹配节点及其全部上级,供关键词检索后仍能正确组树。 (+3 more)
### Community 30 - "Community 30"
### Community 27 - "Community 27"
Cohesion: 0.29
Nodes (9): _build_tree(), _cascade_soft_delete(), create_menu(), get_menu(), list_menus(), list_menus_tree(), _row_to_dict(), soft_delete_menu() (+1 more)
### Community 31 - "Community 31"
Cohesion: 0.31
Nodes (8): create_sop_document(), get_sop_document(), list_sop_documents(), SOP文档 CRUD(biz_sop_document), _row_to_dict(), soft_delete_sop_document(), sop_code_exists(), update_sop_document()
### Community 28 - "Community 28"
Cohesion: 0.27
Nodes (8): create_customer(), get_customer(), id_card_taken(), list_customers(), 客户 CRUD(biz_customer), _row_to_dict(), soft_delete_customer(), update_customer()
### Community 32 - "Community 32"
### Community 29 - "Community 29"
Cohesion: 0.31
Nodes (8): create_express_company(), express_code_exists(), get_express_company(), list_express_companies(), 快递公司 CRUD(biz_express_company), _row_to_dict(), soft_delete_express_company(), update_express_company()
### Community 33 - "Community 33"
### Community 30 - "Community 30"
Cohesion: 0.38
Nodes (9): create_check_item(), get_check_item(), item_code_exists(), list_active_check_items(), list_check_items(), _order_query(), _row_to_dict(), soft_delete_check_item() (+1 more)
### Community 34 - "Community 34"
Cohesion: 0.27
Nodes (8): create_dict_data(), get_dict_data(), list_dict_data(), list_dict_data_options(), 字典数据 CRUD(sys_dict_data), _row_to_dict(), soft_delete_dict_data(), update_dict_data()
### Community 35 - "Community 35"
### Community 31 - "Community 31"
Cohesion: 0.38
Nodes (9): create_env_detect_item(), get_env_detect_item(), item_code_exists(), list_active_env_detect_items(), list_env_detect_items(), _order_query(), _row_to_dict(), soft_delete_env_detect_item() (+1 more)
### Community 36 - "Community 36"
Cohesion: 0.31
Nodes (8): category_code_exists(), create_process_category(), get_process_category(), list_process_categories(), 工艺工序分类 CRUD(biz_process_category), _row_to_dict(), soft_delete_process_category(), update_process_category()
### Community 37 - "Community 37"
### Community 32 - "Community 32"
Cohesion: 0.31
Nodes (8): create_item_unit(), get_item_unit(), list_item_units(), 物品单位 CRUD(biz_item_unit), _row_to_dict(), soft_delete_item_unit(), unit_code_exists(), update_item_unit()
### Community 38 - "Community 38"
### Community 33 - "Community 33"
Cohesion: 0.31
Nodes (8): create_sop_document(), get_sop_document(), list_sop_documents(), SOP文档 CRUD(biz_sop_document), _row_to_dict(), soft_delete_sop_document(), sop_code_exists(), update_sop_document()
### Community 34 - "Community 34"
Cohesion: 0.31
Nodes (8): create_cell_sample_type(), get_cell_sample_type(), list_cell_sample_types(), 细胞样本类型 CRUD(biz_cell_sample_type), _row_to_dict(), soft_delete_cell_sample_type(), type_code_exists(), update_cell_sample_type()
### Community 39 - "Community 39"
Cohesion: 0.31
Nodes (8): create_output_type(), get_output_type(), list_output_types(), 工艺产出物类型 CRUD(biz_output_type), _row_to_dict(), soft_delete_output_type(), type_code_exists(), update_output_type()
### Community 35 - "Community 35"
Cohesion: 0.36
Nodes (7): create_post(), get_post(), list_posts(), post_code_exists(), _row_to_dict(), soft_delete_post(), update_post()
### Community 40 - "Community 40"
### Community 36 - "Community 36"
Cohesion: 0.36
Nodes (7): create_tenant(), get_tenant(), list_tenants(), _row_to_dict(), soft_delete_tenant(), tenant_no_exists(), update_tenant()
### Community 41 - "Community 41"
### Community 37 - "Community 37"
Cohesion: 0.25
Nodes (7): 菜单 code 权限守卫(V0.3:通过 sys_user_role → sys_role_menu → sys_menu.perms), 运营端角色守卫:admin / super_admin 可访问。, 接口菜单权限守卫。super_admin 直接放行。, 接口菜单权限守卫:拥有任一 menuCode 即可访问。super_admin 直接放行。, require_admin_or_super_admin(), require_any_menu_code(), require_menu_code()
### Community 42 - "Community 42"
### Community 38 - "Community 38"
Cohesion: 0.29
Nodes (2): BaseModel, SoftDeleteModel
### Community 43 - "Community 43"
### Community 39 - "Community 39"
Cohesion: 0.38
Nodes (6): derive_legacy_status_from_three(), derive_three_status_from_legacy(), 阶段A兼容:从旧 status 推导三字段。 约束:旧 status 本身混合了支付/配送/订单生命周期,因此只能尽力推断; 若业务侧已有更精确, 阶段A兼容:从三字段反推旧 status(用于旧前端/旧筛选参数兼容)。, ThreeStatus, _to_decimal()
### Community 44 - "Community 44"
### Community 40 - "Community 40"
Cohesion: 0.5
Nodes (3): BaseSettings, Config, Settings
### Community 45 - "Community 45"
### Community 41 - "Community 41"
Cohesion: 0.5
Nodes (2): _auto_fill_create_dept_id(), ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID
### Community 46 - "Community 46"
### Community 42 - "Community 42"
Cohesion: 0.67
Nodes (2): get_menu_list(), 运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)
### Community 47 - "Community 47"
### Community 43 - "Community 43"
Cohesion: 1.0
Nodes (1): 请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传
### Community 48 - "Community 48"
### Community 44 - "Community 44"
Cohesion: 1.0
Nodes (1): API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)
### Community 51 - "Community 51"
### Community 47 - "Community 47"
Cohesion: 1.0
Nodes (1): 发送订单状态通知 Args: openid: 用户openid ord
### Community 52 - "Community 52"
### Community 48 - "Community 48"
Cohesion: 1.0
Nodes (1): 发送支付成功通知 Args: openid: 用户openid ord
### Community 53 - "Community 53"
### Community 49 - "Community 49"
Cohesion: 1.0
Nodes (1): 发送配送通知 Args: openid: 配送员openid task
### Community 54 - "Community 54"
### Community 50 - "Community 50"
Cohesion: 1.0
Nodes (1): 发送配送时效预警 Args: openid: 配送员openid ta
### Community 55 - "Community 55"
### Community 51 - "Community 51"
Cohesion: 1.0
Nodes (1): 发送退款结果通知 Args: openid: 用户openid ord
### Community 56 - "Community 56"
### Community 52 - "Community 52"
Cohesion: 1.0
Nodes (1): 发送催单通知给配送员 Args: deliver_openid: 配送员openid
## Knowledge Gaps
- **117 isolated node(s):** `刷新会话 TTL(refreshToken 续期;已登录用户每次 API 校验通过后滑动续期)`, `写入 refreshToken(用于 one-time 使用/吊销)`, `根据 token 获取当前用户(包含 Redis 会话校验;会话滑动续期)`, `登录凭据 RSA 解密(与前端 JSEncrypt PKCS#1 v1.5 兼容)。`, `Base64 密文 -> JSON 对象(须含 username、password、ts 毫秒时间戳)。` (+112 more)
These have ≤1 connection - possible missing edges or undocumented components.
- **Thin community `Community 42`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
- **Thin community `Community 38`** (8 nodes): `BaseModel`, `.to_dict()`, `get_active()`, `base.py`, `SoftDeleteModel`, `.restore()`, `.soft_delete()`, `__tablename__()`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 45`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
- **Thin community `Community 41`** (4 nodes): `_auto_fill_create_dept_id()`, `get_db()`, `database.py`, `ORM before_insert 钩子:当 create_dept_id 为空时,自动从请求上下文填充当前用户部门 ID`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 46`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)`
- **Thin community `Community 42`** (3 nodes): `get_menu_list()`, `menu.py`, `运营端菜单接口(与 web-admin 前端静态路由 sqxp.ts 对齐,5 个一级菜单分组)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 47`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
- **Thin community `Community 43`** (2 nodes): `context.py`, `请求级别的用户上下文变量 通过 contextvars 在请求处理链路中传递当前用户信息, 供 SQLAlchemy 事件监听器等底层机制使用,避免逐层手动传`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 48`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
- **Thin community `Community 44`** (2 nodes): `__init__.py`, `API 路由包(骨架:公共鉴权 + 静态菜单 + 运营端占位)`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 51`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
- **Thin community `Community 47`** (1 nodes): `发送订单状态通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 52`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
- **Thin community `Community 48`** (1 nodes): `发送支付成功通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 53`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
- **Thin community `Community 49`** (1 nodes): `发送配送通知 Args: openid: 配送员openid task`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 54`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
- **Thin community `Community 50`** (1 nodes): `发送配送时效预警 Args: openid: 配送员openid ta`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 55`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
- **Thin community `Community 51`** (1 nodes): `发送退款结果通知 Args: openid: 用户openid ord`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
- **Thin community `Community 56`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
- **Thin community `Community 52`** (1 nodes): `发送催单通知给配送员 Args: deliver_openid: 配送员openid`
Too small to be a meaningful cluster - may be noise or needs more connections extracted.
## Suggested Questions
_Questions this graph is uniquely positioned to answer:_
- **Why does `SysUser` connect `Community 1` to `Community 2`, `Community 3`, `Community 4`, `Community 5`, `Community 6`, `Community 8`, `Community 10`, `Community 28`?**
_High betweenness centrality (0.105) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 3`, `Community 7`, `Community 8`, `Community 10`, `Community 11`, `Community 46`, `Community 15`?**
_High betweenness centrality (0.063) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `Community 5` to `Community 0`, `Community 3`, `Community 4`, `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 21`, `Community 24`, `Community 25`, `Community 26`, `Community 27`, `Community 28`, `Community 29`, `Community 30`, `Community 31`, `Community 32`, `Community 33`, `Community 34`, `Community 35`, `Community 36`, `Community 37`, `Community 38`, `Community 39`, `Community 40`?**
_High betweenness centrality (0.055) - this node is a cross-community bridge._
- **Are the 665 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `get_current_user_by_token()`) actually correct?**
_`str` has 665 INFERRED edges - model-reasoned connections that need verification._
- **Are the 622 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 622 INFERRED edges - model-reasoned connections that need verification._
- **Are the 516 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 516 INFERRED edges - model-reasoned connections that need verification._
- **Are the 422 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 422 INFERRED edges - model-reasoned connections that need verification._
- **Why does `SysUser` connect `Community 1` to `Community 2`, `Community 3`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 11`, `Community 12`, `Community 19`, `Community 23`, `Community 25`?**
_High betweenness centrality (0.120) - this node is a cross-community bridge._
- **Why does `generate_uuid()` connect `Community 4` to `Community 0`, `Community 1`, `Community 3`, `Community 5`, `Community 6`, `Community 7`, `Community 8`, `Community 9`, `Community 10`, `Community 11`, `Community 12`, `Community 13`, `Community 14`, `Community 17`, `Community 18`, `Community 19`, `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 34`, `Community 35`, `Community 36`?**
_High betweenness centrality (0.081) - this node is a cross-community bridge._
- **Why does `success_response()` connect `Community 0` to `Community 1`, `Community 3`, `Community 7`, `Community 9`, `Community 42`, `Community 10`?**
_High betweenness centrality (0.049) - this node is a cross-community bridge._
- **Are the 668 inferred relationships involving `str` (e.g. with `unhandled_exception_handler()` and `get_current_user_by_token()`) actually correct?**
_`str` has 668 INFERRED edges - model-reasoned connections that need verification._
- **Are the 624 inferred relationships involving `success_response()` (e.g. with `list_storage_release_reviews()` and `get_storage_release_review_detail()`) actually correct?**
_`success_response()` has 624 INFERRED edges - model-reasoned connections that need verification._
- **Are the 518 inferred relationships involving `error_response()` (e.g. with `_json_error_response()` and `list_storage_release_reviews()`) actually correct?**
_`error_response()` has 518 INFERRED edges - model-reasoned connections that need verification._
- **Are the 425 inferred relationships involving `SysUser` (e.g. with `数据权限过滤(V0.3:基于角色 data_scope 的查询级行级过滤) data_scope 值: 1 = 全部数据 2 = 本部门数据 3` and `从 SysUser 读取用户的 dept_id。`) actually correct?**
_`SysUser` has 425 INFERRED edges - model-reasoned connections that need verification._
+4 -4
View File
@@ -57,12 +57,12 @@
</div>
<div id="legend"></div>
</div>
<div id="stats">4027 nodes &middot; 20969 edges &middot; 61 communities</div>
<div id="stats">4040 nodes &middot; 21037 edges &middot; 57 communities</div>
</div>
<script>
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 49, "community_name": "Community 49", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 7}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_error_json", "label": "_error_json()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_error_json()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 3}, {"id": "app_main_sqlalchemy_exception_handler", "label": "sqlalchemy_exception_handler()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "sqlalchemy_exception_handler()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_unhandled_exception_handler", "label": "unhandled_exception_handler()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "unhandled_exception_handler()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 5}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_rationale_81", "label": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "app_main_rationale_92", "label": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 7, "community_name": "Community 7", "source_file": "tasks/__init__.py", "file_type": "code", "degLine truncated
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_error_json", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_sqlalchemy_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_unhandled_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_error_json", "to": "app_main_sqlalchemy_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_error_json", "to": "app_main_unhandled_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "app_main_rationale_81", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "app_main_rationale_92", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_unhandled_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "str", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "labeLine truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 828}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 611}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 375}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 275}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 242}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 232}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 203}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 181}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 178}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 154}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 118}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 106}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 48}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 38}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 31}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 29}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 24}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 22}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 21}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 20}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 15}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 15}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 13}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 13}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 13}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 13}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 12}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 12}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 12}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 11}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 10}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 10}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 10}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 10}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 10}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 9}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 8}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 8}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 7}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 4}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 4}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 3}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 2}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 2}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 1}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 1}];
const RAW_NODES = [{"id": "init_py", "label": "__init__.py", "color": {"background": "#EDC948", "border": "#EDC948", "highlight": {"background": "#ffffff", "border": "#EDC948"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 45, "community_name": "Community 45", "source_file": "__init__.py", "file_type": "code", "degree": 0}, {"id": "main_py", "label": "main.py", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.3, "font": {"size": 0, "color": "#ffffff"}, "title": "main.py", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 7}, {"id": "app_main_lifespan", "label": "lifespan()", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "lifespan()", "community": 9, "community_name": "Community 9", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_error_json", "label": "_error_json()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "_error_json()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 3}, {"id": "app_main_sqlalchemy_exception_handler", "label": "sqlalchemy_exception_handler()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "sqlalchemy_exception_handler()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 4}, {"id": "app_main_unhandled_exception_handler", "label": "unhandled_exception_handler()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.2, "font": {"size": 0, "color": "#ffffff"}, "title": "unhandled_exception_handler()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 5}, {"id": "app_main_mask_secret", "label": "_mask_secret()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "_mask_secret()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_root", "label": "root()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "root()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_health_check", "label": "health_check()", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.0, "font": {"size": 0, "color": "#ffffff"}, "title": "health_check()", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "code", "degree": 1}, {"id": "app_main_rationale_81", "label": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "\u6570\u636e\u5e93\u5f02\u5e38\uff1a\u8fd4\u56de JSON \u5e76\u4fdd\u7559 CORS \u5934\uff0c\u907f\u514d\u6d4f\u89c8\u5668\u53ea\u62a5\u8de8\u57df\u9519\u8bef", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "app_main_rationale_92", "label": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "color": {"background": "#FF9DA7", "border": "#FF9DA7", "highlight": {"background": "#ffffff", "border": "#FF9DA7"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "\u672a\u6355\u83b7\u5f02\u5e38\uff1a\u7edf\u4e00 JSON 500\uff0c\u786e\u4fdd\u8de8\u57df\u573a\u666f\u4e0b\u4ecd\u6709 Access-Control-Allow-Origin", "community": 7, "community_name": "Community 7", "source_file": "main.py", "file_type": "rationale", "degree": 3}, {"id": "tasks_init_py", "label": "__init__.py", "color": {"background": "#BAB0AC", "border": "#BAB0AC", "highlight": {"background": "#ffffff", "border": "#BAB0AC"}}, "size": 10.1, "font": {"size": 0, "color": "#ffffff"}, "title": "__init__.py", "community": 9, "community_name": "Community 9", "source_file": "tasks/__init__.py", "file_type": "code", "degLine truncated
const RAW_EDGES = [{"from": "main_py", "to": "app_main_lifespan", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_error_json", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_sqlalchemy_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_unhandled_exception_handler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_mask_secret", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_root", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "main_py", "to": "app_main_health_check", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_lifespan", "to": "core_login_crypto_ensure_initialized", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_init_scheduled_tasks", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_lifespan", "to": "tasks_init_shutdown_scheduler", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_error_json", "to": "app_main_sqlalchemy_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_error_json", "to": "app_main_unhandled_exception_handler", "label": "calls", "title": "calls [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "app_main_rationale_81", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_sqlalchemy_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "app_main_rationale_92", "label": "rationale_for", "title": "rationale_for [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "app_main_unhandled_exception_handler", "to": "exception", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_unhandled_exception_handler", "to": "str", "label": "calls", "title": "calls [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_81", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_request_log_middleware_apirequestlogmiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "app_main_rationale_92", "to": "core_api_crypto_middleware_apicryptomiddleware", "label": "uses", "title": "uses [INFERRED]", "dashes": true, "width": 1, "color": {"opacity": 0.35}, "confidence": "INFERRED"}, {"from": "tasks_init_py", "to": "tasks_init_init_scheduled_tasks", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "tasks_init_py", "to": "tasks_init_shutdown_scheduler", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_redis_session_enabled", "label": "contains", "title": "contains [EXTRACTED]", "dashes": false, "width": 2, "color": {"opacity": 0.7}, "confidence": "EXTRACTED"}, {"from": "core_auth_py", "to": "core_auth_get_redis_client", "labeLine truncated
const LEGEND = [{"cid": 0, "color": "#4E79A7", "label": "Community 0", "count": 837}, {"cid": 1, "color": "#F28E2B", "label": "Community 1", "count": 635}, {"cid": 2, "color": "#E15759", "label": "Community 2", "count": 471}, {"cid": 3, "color": "#76B7B2", "label": "Community 3", "count": 293}, {"cid": 4, "color": "#59A14F", "label": "Community 4", "count": 266}, {"cid": 5, "color": "#EDC948", "label": "Community 5", "count": 242}, {"cid": 6, "color": "#B07AA1", "label": "Community 6", "count": 173}, {"cid": 7, "color": "#FF9DA7", "label": "Community 7", "count": 165}, {"cid": 8, "color": "#9C755F", "label": "Community 8", "count": 151}, {"cid": 9, "color": "#BAB0AC", "label": "Community 9", "count": 115}, {"cid": 10, "color": "#4E79A7", "label": "Community 10", "count": 110}, {"cid": 11, "color": "#F28E2B", "label": "Community 11", "count": 94}, {"cid": 12, "color": "#E15759", "label": "Community 12", "count": 58}, {"cid": 13, "color": "#76B7B2", "label": "Community 13", "count": 55}, {"cid": 14, "color": "#59A14F", "label": "Community 14", "count": 38}, {"cid": 15, "color": "#EDC948", "label": "Community 15", "count": 29}, {"cid": 16, "color": "#B07AA1", "label": "Community 16", "count": 21}, {"cid": 17, "color": "#FF9DA7", "label": "Community 17", "count": 20}, {"cid": 18, "color": "#9C755F", "label": "Community 18", "count": 15}, {"cid": 19, "color": "#BAB0AC", "label": "Community 19", "count": 15}, {"cid": 20, "color": "#4E79A7", "label": "Community 20", "count": 13}, {"cid": 21, "color": "#F28E2B", "label": "Community 21", "count": 13}, {"cid": 22, "color": "#E15759", "label": "Community 22", "count": 13}, {"cid": 23, "color": "#76B7B2", "label": "Community 23", "count": 12}, {"cid": 24, "color": "#59A14F", "label": "Community 24", "count": 12}, {"cid": 25, "color": "#EDC948", "label": "Community 25", "count": 12}, {"cid": 26, "color": "#B07AA1", "label": "Community 26", "count": 12}, {"cid": 27, "color": "#FF9DA7", "label": "Community 27", "count": 11}, {"cid": 28, "color": "#9C755F", "label": "Community 28", "count": 11}, {"cid": 29, "color": "#BAB0AC", "label": "Community 29", "count": 10}, {"cid": 30, "color": "#4E79A7", "label": "Community 30", "count": 10}, {"cid": 31, "color": "#F28E2B", "label": "Community 31", "count": 10}, {"cid": 32, "color": "#E15759", "label": "Community 32", "count": 10}, {"cid": 33, "color": "#76B7B2", "label": "Community 33", "count": 10}, {"cid": 34, "color": "#59A14F", "label": "Community 34", "count": 10}, {"cid": 35, "color": "#EDC948", "label": "Community 35", "count": 9}, {"cid": 36, "color": "#B07AA1", "label": "Community 36", "count": 9}, {"cid": 37, "color": "#FF9DA7", "label": "Community 37", "count": 8}, {"cid": 38, "color": "#9C755F", "label": "Community 38", "count": 8}, {"cid": 39, "color": "#BAB0AC", "label": "Community 39", "count": 7}, {"cid": 40, "color": "#4E79A7", "label": "Community 40", "count": 4}, {"cid": 41, "color": "#F28E2B", "label": "Community 41", "count": 4}, {"cid": 42, "color": "#E15759", "label": "Community 42", "count": 3}, {"cid": 43, "color": "#76B7B2", "label": "Community 43", "count": 2}, {"cid": 44, "color": "#59A14F", "label": "Community 44", "count": 2}, {"cid": 45, "color": "#EDC948", "label": "Community 45", "count": 1}, {"cid": 46, "color": "#B07AA1", "label": "Community 46", "count": 1}, {"cid": 47, "color": "#FF9DA7", "label": "Community 47", "count": 1}, {"cid": 48, "color": "#9C755F", "label": "Community 48", "count": 1}, {"cid": 49, "color": "#BAB0AC", "label": "Community 49", "count": 1}, {"cid": 50, "color": "#4E79A7", "label": "Community 50", "count": 1}, {"cid": 51, "color": "#F28E2B", "label": "Community 51", "count": 1}, {"cid": 52, "color": "#E15759", "label": "Community 52", "count": 1}, {"cid": 53, "color": "#76B7B2", "label": "Community 53", "count": 1}, {"cid": 54, "color": "#59A14F", "label": "Community 54", "count": 1}, {"cid": 55, "color": "#EDC948", "label": "Community 55", "count": 1}, {"cid": 56, "color": "#B07AA1", "label": "Community 56", "count": 1}, {"cid": 57, "color": "#FF9DA7", "label": "Community 57", "count": 0}, {"cid": 58, "color": "#9C755F", "label": "Community 58", "count": 0}];
// HTML-escape helper — prevents XSS when injecting graph data into innerHTML
function esc(s) {
+16680 -15747
View File
File diff suppressed because it is too large. Load diff
+16 -16
View File
@@ -28,11 +28,11 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/models/material.py": 1781346064.0763414,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/production_material.py": 1781345696.0319448,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_param.py": 1779022399.0175831,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1781348044.8917,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/models.py": 1781415372.256244,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/cleanroom_garment.py": 1781347080.6165943,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/__init__.py": 1781344070.5899634,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/research_donation.py": 1780458012.8329656,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py": 1781345695.4941015,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/qc_material.py": 1781423950.8521655,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/base.py": 1778578258.0821667,
"/Users/wuzilong/work/00code/zkxw/backend/app/models/clinical_payment.py": 1779834956.9588954,
"/Users/wuzilong/work/00code/zkxw/backend/app/schemas/storage_release_review.py": 1779491680.5729434,
@@ -78,7 +78,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_code.py": 1780479191.5382729,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_task_result.py": 1779331731.6720955,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_release_review.py": 1781079917.390382,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py": 1781160504.782417,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_stock_check.py": 1781423988.9720724,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material_stock_batch.py": 1781346093.956913,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/post.py": 1779265648.38155,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_check_result.py": 1779255909.8554008,
@@ -88,7 +88,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material.py": 1781346079.2469015,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dict_type.py": 1779265621.5212462,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_occupancy.py": 1781335540.360182,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py": 1779265648.2051165,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_third_party_company.py": 1781415374.1019006,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_material.py": 1781344099.4832826,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/material_stock_log.py": 1779281903.0942652,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/tenant.py": 1779265611.0532296,
@@ -101,16 +101,16 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent.py": 1779512669.9847593,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_protocol.py": 1781076854.635026,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/cleanroom_garment.py": 1781347124.799281,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py": 1781345612.6013956,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_material_usage.py": 1781423974.5969574,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/biz_no_generator.py": 1779882385.4674172,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_infusion_confirm.py": 1779828818.7646794,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/reagent_stock_log.py": 1779515479.6599197,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_infusion_schedule_mgmt.py": 1781079923.2487886,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py": 1781345294.491891,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/clean_room.py": 1781403189.1288755,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/__init__.py": 1778605691.3816392,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/production_material_stock_check.py": 1781345075.2707977,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_entry_sms_notification.py": 1781063498.05542,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py": 1779265659.3453207,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/express_company.py": 1781402091.5987046,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_application.py": 1781079895.8304482,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/qc_lab_test_item.py": 1779265673.3888667,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/role.py": 1779265616.3701816,
@@ -124,7 +124,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/collection_region.py": 1779277867.6408322,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_delivery.py": 1779935673.6808827,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_check_item.py": 1779007909.2933013,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py": 1779265643.0128026,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/site.py": 1781401290.6845422,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/api_request_log.py": 1778578258.0614743,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dict_data.py": 1779265627.276101,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/research_donation.py": 1781063441.4821293,
@@ -139,7 +139,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/env_detect_record.py": 1781145773.959546,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_release_material.py": 1779928413.9677577,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/process.py": 1779309113.0447981,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py": 1779923362.485726,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_service.py": 1781411605.207482,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/customer.py": 1779686149.7508218,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/workflow.py": 1779265993.677624,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_sms_notification.py": 1781063495.0317714,
@@ -151,7 +151,7 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/outbound_handover.py": 1780455574.0993364,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/storage_facility.py": 1781348192.5178332,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/sample_reception_lab_code.py": 1780462849.099601,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py": 1778733001.8375483,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/cell_sample_type.py": 1781406022.0539382,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/pilot_outbound_status_sync.py": 1781079916.545948,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/consumable_stock_log.py": 1779515477.284446,
"/Users/wuzilong/work/00code/zkxw/backend/app/crud/dept.py": 1779265637.7914758,
@@ -168,10 +168,10 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/api/public.py": 1781364255.0874767,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/material.py": 1781346125.224969,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/production_material.py": 1781345627.6603975,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py": 1781345617.9076924,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc.py": 1781424003.0850434,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/collection_protocol.py": 1781063459.1075609,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/cleanroom_garment.py": 1781347256.2326367,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py": 1779882001.7519956,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/basic_info.py": 1781406022.6140583,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_infusion_confirm.py": 1779657043.1389203,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_infusion_schedule_mgmt.py": 1779940938.18027,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/__init__.py": 1781347167.8573015,
@@ -179,19 +179,19 @@
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_application.py": 1781079904.0516074,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/qc_sms_notification.py": 1780326875.7886882,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/research_donation_sample_collection.py": 1780457788.2998126,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py": 1781348094.1896408,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/operations.py": 1781403189.729859,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/menu.py": 1781347656.1330166,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_delivery.py": 1779655584.820777,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py": 1779882001.7516146,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/admin.py": 1781402092.9624665,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/env_detect.py": 1781145712.2433698,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/research_donation.py": 1779883570.5354397,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/ethnic.py": 1779266243.9511197,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_checkup.py": 1779935751.2658868,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py": 1779712984.6961803,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/pilot_service.py": 1781411609.3643663,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/workflow.py": 1779266232.4568832,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_sms_notification.py": 1780325524.907156,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/sample_reception.py": 1781190032.4213104,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py": 1779281097.279193,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/insurance_company.py": 1781410837.9443986,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/production.py": 1781344255.1594076,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/protocol_sample_collection.py": 1780457788.2093296,
"/Users/wuzilong/work/00code/zkxw/backend/app/api/leave.py": 1779266168.8693042,
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
"""执行质检物料盘点登记相关 DB 迁移(requisition_status + usage_id/batch_id)。
用法(在 backend 目录):
source venv/bin/activate
python scripts/migrate_qc_material_stock_check_requisition.py
"""
from __future__ import annotations
from sqlalchemy import text
from app.core.database import engine
MIGRATIONS = [
(
"biz_qc_material_usage.requisition_status",
"""ALTER TABLE `biz_qc_material_usage`
ADD COLUMN `requisition_status` varchar(16) NOT NULL DEFAULT 'open'
COMMENT '领用状态:open-待登记/有剩余 closed-已使用完'
AFTER `purpose`""",
"""UPDATE `biz_qc_material_usage`
SET `requisition_status` = 'open'
WHERE `source_type` = 'manual_out'
AND `change_type` = 'use'
AND (`requisition_status` IS NULL OR `requisition_status` = '')""",
),
(
"biz_qc_material_stock_check_unused_line.usage_id",
"""ALTER TABLE `biz_qc_material_stock_check_unused_line`
ADD COLUMN `usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_qc_material_usage.id)' AFTER `check_id`""",
None,
),
(
"biz_qc_material_stock_check_unused_line.batch_id",
"""ALTER TABLE `biz_qc_material_stock_check_unused_line`
ADD COLUMN `batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)' AFTER `usage_id`""",
None,
),
(
"idx_qc_check_unused_line_usage",
"""ALTER TABLE `biz_qc_material_stock_check_unused_line`
ADD KEY `idx_qc_check_unused_line_usage` (`usage_id`, `del_flag`)""",
None,
),
]
def _run(conn, sql: str, label: str) -> None:
try:
conn.execute(text(sql))
print(f"OK {label}")
except Exception as e:
msg = str(e)
if "Duplicate column name" in msg or "1060" in msg:
print(f"SKIP {label} (column exists)")
elif "Duplicate key name" in msg or "1061" in msg:
print(f"SKIP {label} (index exists)")
else:
raise
def main() -> None:
with engine.begin() as conn:
for label, ddl, follow_up in MIGRATIONS:
_run(conn, ddl, label)
if follow_up:
_run(conn, follow_up, f"{label} data backfill")
print("Migration completed.")
if __name__ == "__main__":
main()
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""批量初始化细胞产品规格(biz_cell_product_spec),已存在编码则跳过。"""
from __future__ import annotations
import sys
from datetime import datetime
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from app.core.database import SessionLocal
from app.crud import pilot_service as ps_svc
from app.models.models import BizCellProductSpec
# 旧版仅细胞数规格,执行时软删除
LEGACY_SPEC_CODES = [
"CPS-100W",
"CPS-200W",
"CPS-500W",
"CPS-1000W",
"CPS-2000W",
"CPS-5000W",
]
# (spec_code, spec_name, order_num, remark) — 规格名称:细胞数/体积
CELL_PRODUCT_SPECS = [
("CPS-1.1E6-5ML", "1.1×10⁶/5ml", 1, "低剂量规格"),
("CPS-2.2E6-10ML", "2.2×10⁶/10ml", 2, "低剂量规格"),
("CPS-5.5E6-20ML", "5.5×10⁶/20ml", 3, "标准规格"),
("CPS-1.0E7-50ML", "1.0×10⁷/50ml", 4, "标准规格"),
("CPS-2.5E7-50ML", "2.5×10⁷/50ml", 5, "高剂量规格"),
("CPS-5.5E7-100ML", "5.5×10⁷/100ml", 6, "高剂量规格"),
]
def cleanup_legacy_specs(db, tenant_no: str = "zkxw") -> int:
rows = (
db.query(BizCellProductSpec)
.filter(
BizCellProductSpec.spec_code.in_(LEGACY_SPEC_CODES),
BizCellProductSpec.tenant_no == tenant_no,
BizCellProductSpec.del_flag == 0,
)
.all()
)
for row in rows:
row.del_flag = 1
row.update_time = datetime.now()
if rows:
db.commit()
return len(rows)
def seed(tenant_no: str = "zkxw", user_id: str = "d3000000000000000000000000000001") -> None:
db = SessionLocal()
created = 0
skipped = 0
try:
removed = cleanup_legacy_specs(db, tenant_no)
if removed:
print(f"已软删除旧版规格 {removed} 条。")
for code, name, order_num, remark in CELL_PRODUCT_SPECS:
if ps_svc.cell_product_spec_code_exists(db, code, tenant_no):
skipped += 1
continue
ps_svc.create_cell_product_spec(
db,
spec_code=code,
spec_name=name,
tenant_no=tenant_no,
order_num=order_num,
remark=remark,
user_id=user_id,
)
created += 1
print(f"细胞产品规格初始化完成:新增 {created} 条,跳过 {skipped} 条(编码已存在)。")
finally:
db.close()
if __name__ == "__main__":
seed()
+202
View File
@@ -0,0 +1,202 @@
#!/usr/bin/env python3
"""质检物料库测试数据(biz_qc_material + 入库批次 + 变动记录),已存在编码/入库编号则跳过。"""
from __future__ import annotations
import sys
from decimal import Decimal
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from app.core.database import SessionLocal
from app.crud import qc_material as material_svc
from app.crud import qc_material_stock_batch as batch_svc
# (material_code, material_name, spec_model, unit, warning_qty, order_num, remark,
# stock_in_no, stock_in_date, expire_date, catalog_no, batch_no, manufacturer,
# unit_price, qty)
QC_MATERIAL_SEEDS = [
(
"QC-MAT-001",
"DMEM培养基",
"500ml/瓶",
"瓶",
Decimal("5"),
1,
"细胞培养基础培养基",
"RK-20260601-001",
"2026-06-01",
"2027-06-01",
"CAT-DMEM-500",
"BN20260501",
"Gibco",
Decimal("128.00"),
Decimal("20"),
),
(
"QC-MAT-002",
"胎牛血清",
"500ml/瓶",
"瓶",
Decimal("3"),
2,
"细胞培养添加物",
"RK-20260601-002",
"2026-06-01",
"2027-03-01",
"CAT-FBS-500",
"BN20260415",
"Gibco",
Decimal("2680.00"),
Decimal("6"),
),
(
"QC-MAT-003",
"青霉素-链霉素双抗",
"100ml/瓶",
"瓶",
Decimal("5"),
3,
"细胞培养抗生素",
"RK-20260601-003",
"2026-06-02",
"2026-12-02",
"CAT-PS-100",
"BN20260520",
"HyClone",
Decimal("186.00"),
Decimal("10"),
),
(
"QC-MAT-004",
"胰酶消化液",
"100ml/瓶",
"瓶",
Decimal("4"),
4,
"贴壁细胞消化",
"RK-20260601-004",
"2026-06-02",
"2026-11-02",
"CAT-TRY-100",
"BN20260518",
"Sigma",
Decimal("95.00"),
Decimal("8"),
),
(
"QC-MAT-005",
"台盼蓝染色液",
"50ml/瓶",
"瓶",
Decimal("2"),
5,
"细胞活力检测",
"RK-20260601-005",
"2026-06-03",
"2027-06-03",
"CAT-TB-50",
"BN20260525",
"Bio-Rad",
Decimal("72.00"),
Decimal("5"),
),
]
def seed(tenant_no: str = "zkxw", user_id: str = "d3000000000000000000000000000001") -> None:
db = SessionLocal()
created_material = 0
skipped_material = 0
created_batch = 0
skipped_batch = 0
try:
for row in QC_MATERIAL_SEEDS:
(
code,
name,
spec,
unit,
warning_qty,
order_num,
remark,
stock_in_no,
stock_in_date,
expire_date,
catalog_no,
batch_no,
manufacturer,
unit_price,
qty,
) = row
amount = (unit_price * qty).quantize(Decimal("0.01"))
material = None
if material_svc.code_exists(db, code, tenant_no):
skipped_material += 1
from app.models.models import BizQcMaterial
material = (
db.query(BizQcMaterial)
.filter(
BizQcMaterial.material_code == code,
BizQcMaterial.tenant_no == tenant_no,
BizQcMaterial.del_flag == 0,
)
.first()
)
else:
material = material_svc.create_material(
db,
material_code=code,
material_name=name,
spec_model=spec,
unit=unit,
stock_qty=Decimal("0"),
warning_qty=warning_qty,
status="1",
tenant_no=tenant_no,
order_num=order_num,
remark=remark,
user_id=user_id,
)
created_material += 1
if not material:
print(f"跳过批次 {stock_in_no}:物料 {code} 不存在")
continue
if batch_svc.stock_in_no_exists(db, stock_in_no, tenant_no):
skipped_batch += 1
continue
batch_svc.stock_in_one(
db,
material.id,
stock_in_no=stock_in_no,
stock_in_date=stock_in_date,
expire_date=expire_date,
catalog_no=catalog_no,
batch_no=batch_no,
manufacturer=manufacturer,
unit_price=unit_price,
amount=amount,
qty=qty,
remark="测试数据初始化",
tenant_no=tenant_no,
user_id=user_id,
)
created_batch += 1
print(
f"质检物料库测试数据:物料新增 {created_material} 条、跳过 {skipped_material} 条;"
f"入库批次新增 {created_batch} 条、跳过 {skipped_batch} 条。"
)
finally:
db.close()
if __name__ == "__main__":
seed()
@@ -0,0 +1,44 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01 下划线默认 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">01 下划线默认</span> 质检物料库 · Tab 样式 Demo</h1>
<p>接近 Element Plus 默认 Tab,底边绿线 · 改动最小</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
<a href="02-pill-segmented.html">02 胶囊</a>
<a href="05-bar-accent.html">05 竖条</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<nav class="tabs-01" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">物料列表</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">变动记录</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">库存盘点</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>适用场景:</strong>与全站其他 <code>panel-tabs</code> 保持一致;若只想微调间距/字重,选此方案。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
@@ -0,0 +1,44 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>02 胶囊分段 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">02 胶囊分段</span> 质检物料库 · Tab 样式 Demo</h1>
<p>灰底轨道 + 白底激活块 · B 端常用 Segmented 风格</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
<a href="01-underline-default.html">01 下划线</a>
<a href="06-full-track.html">06 滑轨</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<nav class="tabs-02" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">物料列表</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">变动记录</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">库存盘点</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>推荐:</strong>三 Tab 等宽感好、点击区域明确;实现时可放在 <code>panel-top</code> 与内容区之间,用自定义 class 覆盖 <code>el-tabs</code> 或改用 div + v-show。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+42
View File
@@ -0,0 +1,42 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>03 卡片 Tab · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">03 卡片 Tab</span> 质检物料库 · Tab 样式 Demo</h1>
<p>Tab 如卡片,激活项与内容区顶边无缝衔接</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone tabs-03-wrap">
<nav class="tabs-03" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">物料列表</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">变动记录</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">库存盘点</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>注意:</strong>卡片 Tab 与下方 filter-block 共用顶边框,分区感强;Tab 较多时横向可能拥挤。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+57
View File
@@ -0,0 +1,57 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>04 图标信息块 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">04 图标信息块</span> 质检物料库 · Tab 样式 Demo</h1>
<p>图标 + 文案块,模块识别度更高</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<nav class="tabs-04" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">
<span class="tab-icon" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.7l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.7l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"/></svg>
</span>
<span>物料列表</span>
</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">
<span class="tab-icon" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/><path d="M16 13H8"/><path d="M16 17H8"/><path d="M10 9H8"/></svg>
</span>
<span>变动记录</span>
</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">
<span class="tab-icon" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
</span>
<span>库存盘点</span>
</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>落地提示:</strong>图标可用 Element Plus Icons,与侧栏/按钮图标体系一致;占用略多横向空间。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+43
View File
@@ -0,0 +1,43 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>05 竖条强调 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">05 竖条强调</span> 质检物料库 · Tab 样式 Demo</h1>
<p>激活 Tab 左侧主色竖条 + 浅绿底,与 panel 标题竖条统一</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
<a href="02-pill-segmented.html">02 胶囊</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<nav class="tabs-05" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">物料列表</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">变动记录</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">库存盘点</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>推荐:</strong>与 Fresh Mint「标题前竖条」同一视觉语言,品牌感连贯;适合作为全站 panel-tabs 升级方向。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+52
View File
@@ -0,0 +1,52 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>06 全宽滑轨 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
<style>
.tabs-06-inner {
position: relative;
}
</style>
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">06 全宽滑轨</span> 质检物料库 · Tab 样式 Demo</h1>
<p>三等分全宽轨道,白色滑块随 Tab 平滑移动</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<div class="tabs-06" data-active="0">
<div class="tabs-06-inner">
<div class="tabs-06-slider"></div>
<div class="tabs-06-track" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">物料列表</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">变动记录</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">库存盘点</button>
</div>
</div>
</div>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>实现:</strong>可用 CSS <code>transform: translateX</code> 或 Vue 计算激活 index;三 Tab 等分最协调,Tab 数量变化需重算宽度。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+51
View File
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>07 极简圆点 · Tab Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="_shared.css" />
</head>
<body>
<header class="demo-banner">
<div>
<h1><span class="demo-badge">07 极简圆点</span> 质检物料库 · Tab 样式 Demo</h1>
<p>纯文字 + 底部绿点,最轻量、纵向占用少</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
</div>
</header>
<div class="page-wrap">
<section class="panel" id="panel-root">
<div class="panel-top"><h2>质检物料库</h2></div>
<div class="panel-tab-zone">
<nav class="tabs-07" role="tablist">
<button type="button" class="tab-btn is-active" data-tab="list" role="tab">
<span>物料列表</span>
<span class="tab-dot"></span>
</button>
<button type="button" class="tab-btn" data-tab="usage" role="tab">
<span>变动记录</span>
<span class="tab-dot"></span>
</button>
<button type="button" class="tab-btn" data-tab="stockCheck" role="tab">
<span>库存盘点</span>
<span class="tab-dot"></span>
</button>
</nav>
</div>
<div class="tab-panel is-active" data-panel="list" id="content"></div>
</section>
<p class="style-note"><strong>适用:</strong>列表字段多、需要压缩 Tab 区高度时;识别度略低于胶囊/图标方案。</p>
</div>
<script src="_demo-shell.js"></script>
<script>
document.getElementById('content').innerHTML = mockContent('list')
initPanelTabs('panel-root')
</script>
</body>
</html>
+109
View File
@@ -0,0 +1,109 @@
/** 面板 Tab Demo 通用交互 */
function initPanelTabs(rootId) {
const root = document.getElementById(rootId)
if (!root) return
const tabBtns = root.querySelectorAll('[data-tab]')
const panels = root.querySelectorAll('[data-panel]')
const track = root.querySelector('.tabs-06')
const singleContent = root.querySelector('#content')
function activate(name, index) {
tabBtns.forEach((btn) => {
btn.classList.toggle('is-active', btn.dataset.tab === name)
})
panels.forEach((panel) => {
panel.classList.toggle('is-active', panel.dataset.panel === name)
})
if (track) {
track.dataset.active = String(index)
}
if (singleContent && typeof mockContent === 'function') {
singleContent.innerHTML = mockContent(name)
}
}
tabBtns.forEach((btn, index) => {
btn.addEventListener('click', () => activate(btn.dataset.tab, index))
})
}
function buildBanner(currentFile, styleName, styleDesc) {
const files = [
{ id: '01', file: '01-underline-default.html', label: '01 下划线' },
{ id: '02', file: '02-pill-segmented.html', label: '02 胶囊分段' },
{ id: '03', file: '03-card-tabs.html', label: '03 卡片 Tab' },
{ id: '04', file: '04-icon-blocks.html', label: '04 图标块' },
{ id: '05', file: '05-bar-accent.html', label: '05 竖条强调' },
{ id: '06', file: '06-full-track.html', label: '06 全宽滑轨' },
{ id: '07', file: '07-minimal-dot.html', label: '07 极简圆点' }
]
const links = files
.map((f) => {
const current = f.file === currentFile ? ' is-current' : ''
return `<a href="${f.file}" class="${current.trim()}">${f.label}</a>`
})
.join('')
return `
<header class="demo-banner">
<div>
<h1><span class="demo-badge">${styleName}</span> 质检物料库 · Tab 样式 Demo</h1>
<p>${styleDesc} · 点击下方 Tab 可切换模拟内容</p>
</div>
<div class="demo-banner__actions">
<a href="index.html">← 选型索引</a>
${links}
</div>
</header>
`
}
function mockContent(tabName) {
const labels = {
list: '物料列表',
usage: '变动记录',
stockCheck: '库存盘点'
}
return `
<div class="mock-content">
<div class="filter-block">
<div class="filter-grid">
<div class="filter-item">
<label>关键词</label>
<div class="fake-input">物料编码/名称</div>
</div>
<div class="filter-item">
<label>状态</label>
<div class="fake-input">全部</div>
</div>
<div class="filter-item">
<label>时间范围</label>
<div class="fake-input">开始日期 — 结束日期</div>
</div>
</div>
</div>
<div class="list-toolbar">
<span class="sel-hint">已选 <strong>0</strong> 项</span>
<button class="btn btn-primary">入库</button>
<button class="btn">批量入库</button>
<button class="btn">导出</button>
</div>
<div class="list-body">
<div class="fake-table">
<div class="fake-table-head">
<span>序号</span><span>入库编号</span><span>物料名称</span><span>批号</span><span>剩余数量</span>
</div>
<div class="fake-table-row">
<span>1</span><span>RK-20260601-001</span><span>DMEM培养基</span><span>BN20260501</span><span>20 瓶</span>
</div>
<div class="fake-table-row">
<span>2</span><span>RK-20260601-002</span><span>胎牛血清</span><span>BN20260415</span><span>6 瓶</span>
</div>
</div>
<p style="margin:12px 0 0;font-size:12px;color:var(--text-muted)">当前 Tab:<strong>${labels[tabName] || tabName}</strong>(示意内容相同,仅 Tab 样式不同)</p>
</div>
</div>
`
}
+577
View File
@@ -0,0 +1,577 @@
/* 质检物料库 · 面板 Tab 样式 Demo 共享样式(Fresh Mint Token) */
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--bg-page: #f8fafc;
--surface: #fff;
--radius: 10px;
--radius-sm: 8px;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: Inter, -apple-system, BlinkMacSystemFont, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--bg-page);
}
/* ── 顶栏说明 ── */
.demo-banner {
position: sticky;
top: 0;
z-index: 200;
padding: 12px 24px;
background: var(--surface);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
flex-wrap: wrap;
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.04);
}
.demo-banner h1 {
margin: 0;
font-size: 15px;
font-weight: 600;
}
.demo-banner p {
margin: 4px 0 0;
font-size: 12px;
color: var(--text-muted);
}
.demo-banner__actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
align-items: center;
}
.demo-banner a {
padding: 6px 12px;
border-radius: 6px;
font-size: 12px;
font-weight: 500;
text-decoration: none;
color: var(--text-muted);
border: 1px solid var(--border);
background: var(--surface);
}
.demo-banner a:hover {
border-color: var(--primary);
color: var(--primary-dark);
}
.demo-banner a.is-current {
background: var(--primary-bg);
border-color: var(--primary);
color: var(--primary-dark);
}
.demo-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
background: var(--primary-bg);
color: var(--primary-dark);
}
/* ── 页面骨架(模拟 web-admin page-container) ── */
.page-wrap {
padding: 24px;
max-width: 1280px;
margin: 0 auto;
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
overflow: hidden;
}
.panel-top {
padding: 16px 24px 0;
}
.panel-top h2 {
margin: 0;
font-size: 16px;
font-weight: 600;
display: flex;
align-items: center;
gap: 10px;
}
.panel-top h2::before {
content: '';
width: 4px;
height: 16px;
border-radius: 2px;
background: var(--primary);
flex-shrink: 0;
}
/* Tab 区域容器 */
.panel-tab-zone {
padding: 0 24px;
}
/* 模拟内容区 */
.mock-content {
border-top: 1px solid var(--border);
}
.filter-block {
padding: 16px 24px;
}
.filter-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 12px 16px;
}
.filter-item label {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--text-muted);
margin-bottom: 6px;
}
.filter-item .fake-input {
height: 36px;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 0 12px;
background: var(--surface);
color: var(--text-muted);
font-size: 13px;
display: flex;
align-items: center;
}
.list-toolbar {
padding: 12px 24px;
border-top: 1px solid var(--border);
display: flex;
gap: 8px;
align-items: center;
flex-wrap: wrap;
}
.btn {
height: 36px;
padding: 0 14px;
border-radius: var(--radius-sm);
font-size: 13px;
font-weight: 500;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
cursor: default;
}
.btn-primary {
background: var(--primary);
border-color: var(--primary);
color: #fff;
}
.sel-hint {
font-size: 13px;
color: var(--text-muted);
}
.sel-hint strong {
color: var(--primary-dark);
}
.list-body {
padding: 0 24px 24px;
}
.fake-table {
border: 1px solid var(--border);
border-radius: var(--radius-sm);
overflow: hidden;
}
.fake-table-head,
.fake-table-row {
display: grid;
grid-template-columns: 48px 1.2fr 1fr 1fr 1fr;
gap: 8px;
padding: 10px 16px;
font-size: 13px;
align-items: center;
}
.fake-table-head {
background: #f1f5f9;
font-weight: 600;
color: var(--text-muted);
font-size: 12px;
}
.fake-table-row {
border-top: 1px solid var(--border);
color: var(--text);
}
.fake-table-row:nth-child(even) {
background: #fafafa;
}
/* ── Tab 基础:隐藏非激活面板 ── */
.tab-panel {
display: none;
}
.tab-panel.is-active {
display: block;
}
/* ── 样式 01:默认下划线(Element Plus 风格) ── */
.tabs-01 {
display: flex;
gap: 0;
border-bottom: 1px solid var(--border);
margin-top: 12px;
}
.tabs-01 .tab-btn {
padding: 12px 20px;
margin-bottom: -1px;
border: none;
background: transparent;
font-size: 14px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s, border-color 0.15s;
}
.tabs-01 .tab-btn:hover {
color: var(--primary-dark);
}
.tabs-01 .tab-btn.is-active {
color: var(--primary-dark);
border-bottom-color: var(--primary);
}
/* ── 样式 02:胶囊分段(Segmented Pill) ── */
.tabs-02 {
display: inline-flex;
gap: 4px;
margin-top: 16px;
padding: 4px;
background: #f1f5f9;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
}
.tabs-02 .tab-btn {
padding: 8px 20px;
border: none;
border-radius: 6px;
background: transparent;
font-size: 13px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.tabs-02 .tab-btn:hover:not(.is-active) {
color: var(--text);
background: rgba(255, 255, 255, 0.6);
}
.tabs-02 .tab-btn.is-active {
background: var(--surface);
color: var(--primary-dark);
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08);
font-weight: 600;
}
/* ── 样式 03:卡片 Tab(独立卡片 + 底边融合) ── */
.tabs-03 {
display: flex;
gap: 8px;
margin-top: 16px;
align-items: flex-end;
}
.tabs-03 .tab-btn {
padding: 10px 20px;
border: 1px solid var(--border);
border-bottom: none;
border-radius: var(--radius-sm) var(--radius-sm) 0 0;
background: #f8fafc;
font-size: 13px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
position: relative;
top: 1px;
transition: background 0.15s, color 0.15s;
}
.tabs-03 .tab-btn:hover:not(.is-active) {
background: var(--primary-bg);
color: var(--primary-dark);
}
.tabs-03 .tab-btn.is-active {
background: var(--surface);
color: var(--primary-dark);
font-weight: 600;
border-color: var(--border);
z-index: 1;
}
.tabs-03-wrap {
border-bottom: 1px solid var(--border);
margin-bottom: -1px;
}
/* ── 样式 04:图标 + 文字(横向信息块) ── */
.tabs-04 {
display: flex;
gap: 12px;
margin-top: 16px;
flex-wrap: wrap;
}
.tabs-04 .tab-btn {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 16px;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
background: var(--surface);
font-size: 13px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
transition: border-color 0.15s, background 0.15s, color 0.15s;
min-width: 140px;
}
.tabs-04 .tab-icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: #f1f5f9;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
color: var(--text-muted);
}
.tabs-04 .tab-btn:hover:not(.is-active) {
border-color: #a7f3d0;
background: var(--primary-bg);
}
.tabs-04 .tab-btn.is-active {
border-color: var(--primary);
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
.tabs-04 .tab-btn.is-active .tab-icon {
background: var(--primary);
color: #fff;
}
/* ── 样式 05:左侧竖条强调(文字 Tab + 激活竖条) ── */
.tabs-05 {
display: flex;
gap: 0;
margin-top: 12px;
border-bottom: 1px solid var(--border);
}
.tabs-05 .tab-btn {
padding: 12px 24px;
border: none;
background: transparent;
font-size: 14px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
position: relative;
transition: color 0.15s, background 0.15s;
}
.tabs-05 .tab-btn::before {
content: '';
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
width: 3px;
height: 0;
border-radius: 2px;
background: var(--primary);
transition: height 0.15s;
}
.tabs-05 .tab-btn.is-active::before {
height: 16px;
}
.tabs-05 .tab-btn:hover:not(.is-active) {
color: var(--text);
background: #f8fafc;
}
.tabs-05 .tab-btn.is-active {
color: var(--primary-dark);
font-weight: 600;
background: linear-gradient(180deg, var(--primary-bg) 0%, transparent 100%);
}
/* ── 样式 06:全宽底轨滑动高亮(Modern Track) ── */
.tabs-06 {
margin-top: 16px;
}
.tabs-06-inner {
position: relative;
}
.tabs-06-track {
display: grid;
grid-template-columns: repeat(3, 1fr);
background: #f1f5f9;
border-radius: var(--radius-sm);
padding: 4px;
border: 1px solid var(--border);
}
.tabs-06 .tab-btn {
padding: 10px 12px;
border: none;
border-radius: 6px;
background: transparent;
font-size: 13px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
text-align: center;
transition: color 0.2s;
z-index: 1;
}
.tabs-06 .tab-btn.is-active {
color: var(--primary-dark);
font-weight: 600;
}
.tabs-06-slider {
position: absolute;
top: 4px;
left: 4px;
width: calc((100% - 8px) / 3);
height: calc(100% - 8px);
background: var(--surface);
border-radius: 6px;
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.1);
transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
}
.tabs-06[data-active='1'] .tabs-06-slider {
transform: translateX(100%);
}
.tabs-06[data-active='2'] .tabs-06-slider {
transform: translateX(200%);
}
/* ── 样式 07:极简文字 + 点状指示 ── */
.tabs-07 {
display: flex;
gap: 32px;
margin-top: 16px;
padding-bottom: 12px;
border-bottom: 1px solid var(--border);
}
.tabs-07 .tab-btn {
padding: 4px 0;
border: none;
background: transparent;
font-size: 14px;
font-weight: 500;
color: var(--text-muted);
cursor: pointer;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
transition: color 0.15s;
}
.tabs-07 .tab-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: transparent;
transition: background 0.15s, transform 0.15s;
}
.tabs-07 .tab-btn:hover:not(.is-active) {
color: var(--text);
}
.tabs-07 .tab-btn.is-active {
color: var(--primary-dark);
font-weight: 600;
}
.tabs-07 .tab-btn.is-active .tab-dot {
background: var(--primary);
transform: scale(1.2);
}
/* 样式说明卡片 */
.style-note {
margin: 24px 0 0;
padding: 14px 18px;
background: #fffbeb;
border: 1px solid #fde68a;
border-radius: var(--radius-sm);
font-size: 13px;
color: #92400e;
}
.style-note strong {
color: #78350f;
}
+156
View File
@@ -0,0 +1,156 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>质检物料库 · 面板 Tab 样式选型</title>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<link rel="stylesheet" href="_shared.css" />
<style>
.index-hero {
max-width: 960px;
margin: 0 auto;
padding: 32px 24px 16px;
}
.index-hero h1 {
margin: 0 0 8px;
font-size: 22px;
}
.index-hero p {
margin: 0;
color: var(--text-muted);
max-width: 640px;
}
.index-grid {
max-width: 960px;
margin: 0 auto;
padding: 16px 24px 48px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
gap: 16px;
}
.index-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 18px;
text-decoration: none;
color: inherit;
transition: border-color 0.2s, box-shadow 0.2s;
}
.index-card:hover {
border-color: #a7f3d0;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.08);
}
.index-card h2 {
margin: 0 0 6px;
font-size: 15px;
font-weight: 600;
color: var(--primary-dark);
}
.index-card p {
margin: 0;
font-size: 13px;
color: var(--text-muted);
line-height: 1.5;
}
.index-card .tag {
display: inline-block;
margin-top: 12px;
padding: 2px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
background: #f1f5f9;
color: var(--text-muted);
}
.index-card .tag--rec {
background: var(--primary-bg);
color: var(--primary-dark);
}
.preview-strip {
margin-top: 14px;
padding: 10px;
background: #f8fafc;
border-radius: 8px;
border: 1px solid var(--border);
font-size: 12px;
color: var(--text-muted);
}
</style>
</head>
<body>
<div class="index-hero">
<h1>质检物料库 · 三 Tab 样式 Demo</h1>
<p>
针对【物料列表】【变动记录】【库存盘点】三个 Tab,提供 7 套可选样式。色值与间距对齐
Fresh Mint(<code>#10b981</code>)。选定样式后可落地到
<code>qc-material/index.vue</code> 的 <code>panel-tabs</code>。
</p>
</div>
<div class="index-grid">
<a class="index-card" href="01-underline-default.html">
<h2>01 · 下划线默认</h2>
<p>与当前 Element Plus 默认 Tab 接近,底边绿线指示激活项。改动最小。</p>
<span class="tag">现状基线</span>
<div class="preview-strip">物料列表 变动记录 库存盘点 ———</div>
</a>
<a class="index-card" href="02-pill-segmented.html">
<h2>02 · 胶囊分段</h2>
<p>灰底轨道 + 白底激活块,类似 Segmented Control,层次清晰、适合 3~5 个 Tab。</p>
<span class="tag tag--rec">推荐</span>
<div class="preview-strip">[ 物料列表 | 变动记录 | 库存盘点 ]</div>
</a>
<a class="index-card" href="03-card-tabs.html">
<h2>03 · 卡片 Tab</h2>
<p>每个 Tab 像小卡片,激活项与内容区顶边融合,适合强调「分区」感。</p>
<span class="tag">分区感强</span>
<div class="preview-strip">┌物料列表┐ 变动记录 库存盘点</div>
</a>
<a class="index-card" href="04-icon-blocks.html">
<h2>04 · 图标信息块</h2>
<p>图标 + 文案横向块,信息量大,适合 Tab 需要快速识别的业务模块。</p>
<span class="tag">信息丰富</span>
<div class="preview-strip">[📦 物料] [📋 变动] [✓ 盘点]</div>
</a>
<a class="index-card" href="05-bar-accent.html">
<h2>05 · 竖条 + 浅绿底</h2>
<p>激活 Tab 左侧主色竖条 + 浅绿渐变底,与列表标题竖条视觉统一。</p>
<span class="tag tag--rec">推荐</span>
<div class="preview-strip">|物料列表 变动记录 库存盘点</div>
</a>
<a class="index-card" href="06-full-track.html">
<h2>06 · 全宽滑轨</h2>
<p>三等分全宽轨道,白色滑块平滑移动,现代感强,移动端也友好。</p>
<span class="tag">现代感</span>
<div class="preview-strip">████░░░░░░░░ (滑块随 Tab 移动)</div>
</a>
<a class="index-card" href="07-minimal-dot.html">
<h2>07 · 极简圆点</h2>
<p>纯文字 Tab,激活项下方绿点指示,最轻量,适合内容区需要更多纵向空间。</p>
<span class="tag">极简</span>
<div class="preview-strip">物料列表· 变动记录 库存盘点·</div>
</a>
</div>
</body>
</html>
@@ -0,0 +1,3 @@
-- 细胞样本类型表增加 Logo 字段
ALTER TABLE `biz_cell_sample_type`
ADD COLUMN `type_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '样本类型Logo URL' AFTER `type_name`;
@@ -0,0 +1,3 @@
-- 体检机构表增加 Logo 字段
ALTER TABLE `biz_checkup_institution`
ADD COLUMN `institution_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '体检机构Logo URL' AFTER `contact_phone`;
@@ -0,0 +1,3 @@
-- 洁净室表增加图片字段
ALTER TABLE `biz_clean_room`
ADD COLUMN `room_image` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '洁净室图片URL' AFTER `area_sqm`;
@@ -0,0 +1,3 @@
-- 快递公司表增加 logo 字段
ALTER TABLE `biz_express_company`
ADD COLUMN `express_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '快递公司Logo URL' AFTER `express_name`;
@@ -0,0 +1,3 @@
-- 保险公司表增加 Logo 字段
ALTER TABLE `biz_insurance_company`
ADD COLUMN `company_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '保险公司Logo URL' AFTER `contact_phone`;
@@ -0,0 +1,7 @@
-- 市场物料盘点未用完登记行 · 关联领用记录 / 入库批次
ALTER TABLE `biz_material_stock_check_unused_line`
ADD COLUMN `usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_material_usage.id)' AFTER `check_id`,
ADD COLUMN `batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)' AFTER `usage_id`;
ALTER TABLE `biz_material_stock_check_unused_line`
ADD KEY `idx_material_check_unused_line_usage` (`usage_id`, `del_flag`);
@@ -0,0 +1,11 @@
-- 市场物料领用记录 · 是否已使用完(盘点登记用)
ALTER TABLE `biz_material_usage`
ADD COLUMN `requisition_status` varchar(16) NOT NULL DEFAULT 'open'
COMMENT '领用状态:open-待登记/有剩余 closed-已使用完'
AFTER `purpose`;
UPDATE `biz_material_usage`
SET `requisition_status` = 'open'
WHERE `source_type` = 'manual_out'
AND `change_type` = 'use'
AND (`requisition_status` IS NULL OR `requisition_status` = '');
@@ -0,0 +1,7 @@
-- 生产物料盘点未用完登记行 · 关联领用记录 / 入库批次
ALTER TABLE `biz_production_material_stock_check_unused_line`
ADD COLUMN `usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_production_material_usage.id)' AFTER `check_id`,
ADD COLUMN `batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)' AFTER `usage_id`;
ALTER TABLE `biz_production_material_stock_check_unused_line`
ADD KEY `idx_pm_check_unused_line_usage` (`usage_id`, `del_flag`);
@@ -0,0 +1,11 @@
-- 生产物料领用记录 · 是否已使用完(盘点登记用)
ALTER TABLE `biz_production_material_usage`
ADD COLUMN `requisition_status` varchar(16) NOT NULL DEFAULT 'open'
COMMENT '领用状态:open-待登记/有剩余 closed-已使用完'
AFTER `purpose`;
UPDATE `biz_production_material_usage`
SET `requisition_status` = 'open'
WHERE `source_type` = 'manual_out'
AND `change_type` = 'use'
AND (`requisition_status` IS NULL OR `requisition_status` = '');
@@ -0,0 +1,7 @@
-- 盘点未用完登记行 · 关联领用记录 / 入库批次
ALTER TABLE `biz_qc_material_stock_check_unused_line`
ADD COLUMN `usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_qc_material_usage.id)' AFTER `check_id`,
ADD COLUMN `batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)' AFTER `usage_id`;
ALTER TABLE `biz_qc_material_stock_check_unused_line`
ADD KEY `idx_qc_check_unused_line_usage` (`usage_id`, `del_flag`);
@@ -0,0 +1,11 @@
-- 质检物料领用记录 · 是否已使用完(盘点登记用)
ALTER TABLE `biz_qc_material_usage`
ADD COLUMN `requisition_status` varchar(16) NOT NULL DEFAULT 'open'
COMMENT '领用状态:open-待登记/有剩余 closed-已使用完'
AFTER `purpose`;
UPDATE `biz_qc_material_usage`
SET `requisition_status` = 'open'
WHERE `source_type` = 'manual_out'
AND `change_type` = 'use'
AND (`requisition_status` IS NULL OR `requisition_status` = '');
@@ -0,0 +1,3 @@
-- 第三方检测公司表增加 Logo 字段
ALTER TABLE `biz_qc_third_party_company`
ADD COLUMN `company_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '公司Logo URL' AFTER `contact_phone`;
@@ -0,0 +1,3 @@
-- 站点表增加站点图片字段
ALTER TABLE `sys_site`
ADD COLUMN `site_image` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '站点图片URL' AFTER `business_scope`;
+33
View File
@@ -0,0 +1,33 @@
-- 细胞产品规格初始化数据(幂等:按 spec_code / 固定 id 跳过已存在记录)
-- 规格名称格式:细胞数/体积,如 5.5×10⁷/100ml
-- 执行:mysql -u root -p zkxw < docs/sql/seed_cell_product_specs.sql
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 清理旧版仅细胞数规格(若存在)
UPDATE `biz_cell_product_spec` SET `del_flag` = 1, `update_time` = NOW()
WHERE `tenant_no` = 'zkxw' AND `del_flag` = 0
AND `spec_code` IN ('CPS-100W', 'CPS-200W', 'CPS-500W', 'CPS-1000W', 'CPS-2000W', 'CPS-5000W');
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000001', 'CPS-1.1E6-5ML', '1.1×10⁶/5ml', 'zkxw', 1, '低剂量规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-1.1E6-5ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000002', 'CPS-2.2E6-10ML', '2.2×10⁶/10ml', 'zkxw', 2, '低剂量规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-2.2E6-10ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000003', 'CPS-5.5E6-20ML', '5.5×10⁶/20ml', 'zkxw', 3, '标准规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-5.5E6-20ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000004', 'CPS-1.0E7-50ML', '1.0×10⁷/50ml', 'zkxw', 4, '标准规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-1.0E7-50ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000005', 'CPS-2.5E7-50ML', '2.5×10⁷/50ml', 'zkxw', 5, '高剂量规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-2.5E7-50ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cps000000000000000000000000000006', 'CPS-5.5E7-100ML', '5.5×10⁷/100ml', 'zkxw', 6, '高剂量规格', 'd3000000000000000000000000000001', '', NOW(), 'd3000000000000000000000000000001', NOW(), 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_cell_product_spec` WHERE `spec_code`='CPS-5.5E7-100ML' AND `tenant_no`='zkxw' AND `del_flag`=0);
+104
View File
@@ -0,0 +1,104 @@
-- 体检机构及项目价格测试数据(幂等:按 id 跳过已存在记录)
-- 2 家体检机构,每家 10 个体检项目
-- 执行:mysql -u root -p zkxw < docs/sql/seed_checkup_institutions.sql
SET NAMES utf8mb4;
-- 体检机构主表(2 条)
INSERT INTO `biz_checkup_institution` (`id`, `institution_name`, `institution_address`, `contact_name`, `contact_phone`, `institution_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cki000000000000000000000000000001', '安徽省立医院健康管理中心', '合肥市庐阳区六安路9号', '王主任', '0551-6228340', NULL, '1', 'zkxw', 1, '测试数据-省立医院体检中心', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution` WHERE `id` = 'cki000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution` (`id`, `institution_name`, `institution_address`, `contact_name`, `contact_phone`, `institution_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'cki000000000000000000000000000002', '合肥美年大健康体检中心', '合肥市蜀山区潜山路188号', '刘经理', '0551-65588000', NULL, '1', 'zkxw', 2, '测试数据-美年大健康', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution` WHERE `id` = 'cki000000000000000000000000000002' AND `del_flag` = 0);
-- 开票信息子表(2 条)
INSERT INTO `biz_checkup_institution_invoice` (`id`, `checkup_institution_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckinv000000000000000000000000000001', 'cki000000000000000000000000000001', '安徽省立医院', '12340000000000001X', '合肥市庐阳区六安路9号', '0551-6228340', '中国建设银行合肥庐阳支行', '34000000000000000001', 'zkxw', 1, '测试开票信息-省立医院', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_invoice` WHERE `id` = 'ckinv000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_invoice` (`id`, `checkup_institution_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckinv000000000000000000000000000002', 'cki000000000000000000000000000002', '合肥美年大健康产业控股集团有限公司', '91340100000000002Y', '合肥市蜀山区潜山路188号', '0551-65588000', '招商银行合肥分行营业部', '55100000000000000002', 'zkxw', 1, '测试开票信息-美年大健康', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_invoice` WHERE `id` = 'ckinv000000000000000000000000000002' AND `del_flag` = 0);
-- 体检项目:省立医院 10 条
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000001', 'cki000000000000000000000000000001', '一般健康体检', 580.00, '1', 'zkxw', 1, '含内科、外科、眼科、耳鼻喉科', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000002', 'cki000000000000000000000000000001', '血常规', 45.00, '1', 'zkxw', 2, '全血细胞分析', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000002' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000003', 'cki000000000000000000000000000001', '肝功能全套', 120.00, '1', 'zkxw', 3, 'ALT/AST/总胆红素等', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000003' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000004', 'cki000000000000000000000000000001', '肾功能全套', 98.00, '1', 'zkxw', 4, '尿素氮/肌酐/尿酸', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000004' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000005', 'cki000000000000000000000000000001', '空腹血糖', 25.00, '1', 'zkxw', 5, '需空腹8小时以上', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000005' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000006', 'cki000000000000000000000000000001', '血脂四项', 68.00, '1', 'zkxw', 6, '总胆固醇/甘油三酯/HDL/LDL', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000006' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000007', 'cki000000000000000000000000000001', '心电图', 35.00, '1', 'zkxw', 7, '十二导联常规心电图', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000007' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000008', 'cki000000000000000000000000000001', '胸部DR', 80.00, '1', 'zkxw', 8, '数字化X线摄影', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000008' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000009', 'cki000000000000000000000000000001', '腹部B超', 120.00, '1', 'zkxw', 9, '肝、胆、脾、胰、双肾', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000009' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000010', 'cki000000000000000000000000000001', '肿瘤标志物筛查', 380.00, '1', 'zkxw', 10, 'CEA/AFP/CA199等组合', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000010' AND `del_flag` = 0);
-- 体检项目:美年大健康 10 条
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000011', 'cki000000000000000000000000000002', '入职体检套餐A', 298.00, '1', 'zkxw', 1, '适用于一般岗位入职', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000011' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000012', 'cki000000000000000000000000000002', '高管健康体检', 1680.00, '1', 'zkxw', 2, '深度体检含专项评估', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000012' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000013', 'cki000000000000000000000000000002', '幽门螺旋杆菌检测', 85.00, '1', 'zkxw', 3, 'C13呼气试验', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000013' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000014', 'cki000000000000000000000000000002', '甲状腺彩超', 90.00, '1', 'zkxw', 4, '甲状腺形态及血流', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000014' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000015', 'cki000000000000000000000000000002', '颈动脉彩超', 160.00, '1', 'zkxw', 5, '评估动脉粥样硬化风险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000015' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000016', 'cki000000000000000000000000000002', '骨密度检测', 120.00, '1', 'zkxw', 6, '双能X线骨密度', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000016' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000017', 'cki000000000000000000000000000002', '动态血压监测', 200.00, '1', 'zkxw', 7, '24小时动态血压', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000017' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000018', 'cki000000000000000000000000000002', '眼底照相', 75.00, '1', 'zkxw', 8, '免散瞳眼底检查', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000018' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000019', 'cki000000000000000000000000000002', '肺功能检测', 150.00, '1', 'zkxw', 9, '肺通气功能检查', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000019' AND `del_flag` = 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ckp000000000000000000000000000020', 'cki000000000000000000000000000002', '细胞储存前专项体检', 880.00, '1', 'zkxw', 10, '细胞存储业务前置体检组合', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_checkup_institution_project` WHERE `id` = 'ckp000000000000000000000000000020' AND `del_flag` = 0);
+104
View File
@@ -0,0 +1,104 @@
-- 保险公司及险种价格测试数据(幂等:按 id 跳过已存在记录)
-- 2 家保险公司,每家 10 个险种
-- 执行:mysql -u root -p zkxw < docs/sql/seed_insurance_companies.sql
SET NAMES utf8mb4;
-- 保险公司主表(2 条)
INSERT INTO `biz_insurance_company` (`id`, `company_name`, `company_address`, `contact_name`, `contact_phone`, `company_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'inc000000000000000000000000000001', '中国人民财产保险股份有限公司', '北京市西城区西长安街88号', '张经理', '010-95518', NULL, '1', 'zkxw', 1, '测试数据-人保财险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_company` WHERE `id` = 'inc000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_insurance_company` (`id`, `company_name`, `company_address`, `contact_name`, `contact_phone`, `company_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'inc000000000000000000000000000002', '中国平安财产保险股份有限公司', '深圳市福田区益田路5033号平安金融中心', '李经理', '95511', NULL, '1', 'zkxw', 2, '测试数据-平安财险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_company` WHERE `id` = 'inc000000000000000000000000000002' AND `del_flag` = 0);
-- 开票信息子表(2 条,各对应一家保险公司)
INSERT INTO `biz_insurance_company_invoice` (`id`, `insurance_company_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'inv000000000000000000000000000001', 'inc000000000000000000000000000001', '中国人民财产保险股份有限公司', '91110000100000000X', '北京市西城区西长安街88号', '010-95518', '中国工商银行北京分行营业部', '02000000000000000001', 'zkxw', 1, '测试开票信息-人保', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_company_invoice` WHERE `id` = 'inv000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_insurance_company_invoice` (`id`, `insurance_company_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'inv000000000000000000000000000002', 'inc000000000000000000000000000002', '中国平安财产保险股份有限公司', '91440300100000000Y', '深圳市福田区益田路5033号平安金融中心', '95511', '招商银行深圳分行营业部', '75500000000000000002', 'zkxw', 1, '测试开票信息-平安', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_company_invoice` WHERE `id` = 'inv000000000000000000000000000002' AND `del_flag` = 0);
-- 险种价格子表:人保财险 10 条
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000001', 'inc000000000000000000000000000001', '细胞存储责任险', 1280.00, '1', 'zkxw', 1, '年度保费,覆盖样本存储期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000001' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000002', 'inc000000000000000000000000000001', '样本运输险', 680.00, '1', 'zkxw', 2, '覆盖样本冷链运输过程', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000002' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000003', 'inc000000000000000000000000000001', '实验室财产险', 3500.00, '1', 'zkxw', 3, '覆盖实验室设备与设施', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000003' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000004', 'inc000000000000000000000000000001', '公众责任险', 980.00, '1', 'zkxw', 4, '覆盖第三方人身及财产损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000004' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000005', 'inc000000000000000000000000000001', '产品责任险', 1680.00, '1', 'zkxw', 5, '覆盖细胞产品相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000005' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000006', 'inc000000000000000000000000000001', '雇主责任险', 2200.00, '1', 'zkxw', 6, '覆盖员工工伤及职业病', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000006' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000007', 'inc000000000000000000000000000001', '安全生产责任险', 1560.00, '1', 'zkxw', 7, '覆盖生产作业安全事故', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000007' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000008', 'inc000000000000000000000000000001', '医疗责任险', 3200.00, '1', 'zkxw', 8, '覆盖医疗服务相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000008' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000009', 'inc000000000000000000000000000001', '生物材料污染险', 890.00, '1', 'zkxw', 9, '覆盖生物样本污染损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000009' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000010', 'inc000000000000000000000000000001', '冷链中断险', 720.00, '1', 'zkxw', 10, '覆盖冷链设备故障导致损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000010' AND `del_flag` = 0);
-- 险种价格子表:平安财险 10 条
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000011', 'inc000000000000000000000000000002', '临床试验责任险', 2560.00, '1', 'zkxw', 1, '年度保费,覆盖临床试验期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000011' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000012', 'inc000000000000000000000000000002', '细胞治疗责任险', 3800.00, '1', 'zkxw', 2, '覆盖细胞治疗相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000012' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000013', 'inc000000000000000000000000000002', '研究者保险', 1200.00, '1', 'zkxw', 3, '覆盖主要研究者及团队', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000013' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000014', 'inc000000000000000000000000000002', '受试者保险', 980.00, '1', 'zkxw', 4, '覆盖临床试验受试者', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000014' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000015', 'inc000000000000000000000000000002', '试验器械险', 1450.00, '1', 'zkxw', 5, '覆盖试验用器械损坏', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000015' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000016', 'inc000000000000000000000000000002', '伦理审查责任险', 760.00, '1', 'zkxw', 6, '覆盖伦理审查相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000016' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000017', 'inc000000000000000000000000000002', '数据泄露责任险', 1100.00, '1', 'zkxw', 7, '覆盖试验数据泄露风险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000017' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000018', 'inc000000000000000000000000000002', '跨境转运险', 1890.00, '1', 'zkxw', 8, '覆盖跨境样本转运', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000018' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000019', 'inc000000000000000000000000000002', '制剂稳定性险', 1350.00, '1', 'zkxw', 9, '覆盖制剂稳定性试验期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000019' AND `del_flag` = 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'ipp000000000000000000000000000020', 'inc000000000000000000000000000002', '不良事件保障险', 2100.00, '1', 'zkxw', 10, '覆盖试验不良事件处理', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0
FROM DUAL WHERE NOT EXISTS (SELECT 1 FROM `biz_insurance_project_price` WHERE `id` = 'ipp000000000000000000000000000020' AND `del_flag` = 0);
+66
View File
@@ -0,0 +1,66 @@
-- 质检物料库测试数据(幂等:按 material_code / stock_in_no 跳过已存在记录)
-- 执行:mysql -u root -p zkxw < docs/sql/seed_qc_materials.sql
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- ── 物料主表 ──────────────────────────────────────
INSERT INTO `biz_qc_material` (`id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_qty`, `warning_qty`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcm00000000000000000000000000001', 'QC-MAT-001', 'DMEM培养基', '500ml/瓶', '瓶', 20.0000, 5.0000, '1', 'zkxw', 1, '细胞培养基础培养基', 'd3000000000000000000000000000001', '', '2026-06-01 08:00:00', 'd3000000000000000000000000000001', '2026-06-01 08:00:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material` WHERE `material_code`='QC-MAT-001' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material` (`id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_qty`, `warning_qty`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcm00000000000000000000000000002', 'QC-MAT-002', '胎牛血清', '500ml/瓶', '瓶', 6.0000, 3.0000, '1', 'zkxw', 2, '细胞培养添加物', 'd3000000000000000000000000000001', '', '2026-06-01 08:10:00', 'd3000000000000000000000000000001', '2026-06-01 08:10:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material` WHERE `material_code`='QC-MAT-002' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material` (`id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_qty`, `warning_qty`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcm00000000000000000000000000003', 'QC-MAT-003', '青霉素-链霉素双抗', '100ml/瓶', '瓶', 10.0000, 5.0000, '1', 'zkxw', 3, '细胞培养抗生素', 'd3000000000000000000000000000001', '', '2026-06-01 08:20:00', 'd3000000000000000000000000000001', '2026-06-01 08:20:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material` WHERE `material_code`='QC-MAT-003' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material` (`id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_qty`, `warning_qty`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcm00000000000000000000000000004', 'QC-MAT-004', '胰酶消化液', '100ml/瓶', '瓶', 8.0000, 4.0000, '1', 'zkxw', 4, '贴壁细胞消化', 'd3000000000000000000000000000001', '', '2026-06-01 08:30:00', 'd3000000000000000000000000000001', '2026-06-01 08:30:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material` WHERE `material_code`='QC-MAT-004' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material` (`id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_qty`, `warning_qty`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcm00000000000000000000000000005', 'QC-MAT-005', '台盼蓝染色液', '50ml/瓶', '瓶', 5.0000, 2.0000, '1', 'zkxw', 5, '细胞活力检测', 'd3000000000000000000000000000001', '', '2026-06-01 08:40:00', 'd3000000000000000000000000000001', '2026-06-01 08:40:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material` WHERE `material_code`='QC-MAT-005' AND `tenant_no`='zkxw' AND `del_flag`=0);
-- ── 入库批次(material_id 按 material_code 关联)──
INSERT INTO `biz_qc_material_stock_batch` (`id`, `material_id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_in_no`, `stock_in_date`, `expire_date`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `in_qty`, `remaining_qty`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcb00000000000000000000000000001', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-001' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-001', 'DMEM培养基', '500ml/瓶', '瓶', 'RK-20260601-001', '2026-06-01', '2027-06-01', 'CAT-DMEM-500', 'BN20260501', 'Gibco', 128.00, 2560.00, 20.0000, 20.0000, 'zkxw', 1, '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-01 08:00:00', 'd3000000000000000000000000000001', '2026-06-01 08:00:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_stock_batch` WHERE `stock_in_no`='RK-20260601-001' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material_stock_batch` (`id`, `material_id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_in_no`, `stock_in_date`, `expire_date`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `in_qty`, `remaining_qty`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcb00000000000000000000000000002', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-002' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-002', '胎牛血清', '500ml/瓶', '瓶', 'RK-20260601-002', '2026-06-01', '2027-03-01', 'CAT-FBS-500', 'BN20260415', 'Gibco', 2680.00, 16080.00, 6.0000, 6.0000, 'zkxw', 2, '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-01 08:10:00', 'd3000000000000000000000000000001', '2026-06-01 08:10:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_stock_batch` WHERE `stock_in_no`='RK-20260601-002' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material_stock_batch` (`id`, `material_id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_in_no`, `stock_in_date`, `expire_date`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `in_qty`, `remaining_qty`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcb00000000000000000000000000003', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-003' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-003', '青霉素-链霉素双抗', '100ml/瓶', '瓶', 'RK-20260601-003', '2026-06-02', '2026-12-02', 'CAT-PS-100', 'BN20260520', 'HyClone', 186.00, 1860.00, 10.0000, 10.0000, 'zkxw', 3, '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-02 08:20:00', 'd3000000000000000000000000000001', '2026-06-02 08:20:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_stock_batch` WHERE `stock_in_no`='RK-20260601-003' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material_stock_batch` (`id`, `material_id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_in_no`, `stock_in_date`, `expire_date`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `in_qty`, `remaining_qty`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcb00000000000000000000000000004', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-004' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-004', '胰酶消化液', '100ml/瓶', '瓶', 'RK-20260601-004', '2026-06-02', '2026-11-02', 'CAT-TRY-100', 'BN20260518', 'Sigma', 95.00, 760.00, 8.0000, 8.0000, 'zkxw', 4, '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-02 08:30:00', 'd3000000000000000000000000000001', '2026-06-02 08:30:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_stock_batch` WHERE `stock_in_no`='RK-20260601-004' AND `tenant_no`='zkxw' AND `del_flag`=0);
INSERT INTO `biz_qc_material_stock_batch` (`id`, `material_id`, `material_code`, `material_name`, `spec_model`, `unit`, `stock_in_no`, `stock_in_date`, `expire_date`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `in_qty`, `remaining_qty`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcb00000000000000000000000000005', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-005' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-005', '台盼蓝染色液', '50ml/瓶', '瓶', 'RK-20260601-005', '2026-06-03', '2027-06-03', 'CAT-TB-50', 'BN20260525', 'Bio-Rad', 72.00, 360.00, 5.0000, 5.0000, 'zkxw', 5, '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-03 08:40:00', 'd3000000000000000000000000000001', '2026-06-03 08:40:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_stock_batch` WHERE `stock_in_no`='RK-20260601-005' AND `tenant_no`='zkxw' AND `del_flag`=0);
-- ── 入库变动记录 ──────────────────────────────────
INSERT INTO `biz_qc_material_usage` (`id`, `material_id`, `material_code`, `material_name`, `batch_id`, `stock_in_no`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `change_type`, `change_qty`, `stock_before`, `stock_after`, `source_type`, `tenant_no`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcu00000000000000000000000000001', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-001' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-001', 'DMEM培养基', 'qcb00000000000000000000000000001', 'RK-20260601-001', 'CAT-DMEM-500', 'BN20260501', 'Gibco', 128.00, 2560.00, 'in', 20.0000, 0.0000, 20.0000, 'manual_in', 'zkxw', '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-01 08:00:00', 'd3000000000000000000000000000001', '2026-06-01 08:00:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_usage` WHERE `id`='qcu00000000000000000000000000001');
INSERT INTO `biz_qc_material_usage` (`id`, `material_id`, `material_code`, `material_name`, `batch_id`, `stock_in_no`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `change_type`, `change_qty`, `stock_before`, `stock_after`, `source_type`, `tenant_no`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcu00000000000000000000000000002', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-002' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-002', '胎牛血清', 'qcb00000000000000000000000000002', 'RK-20260601-002', 'CAT-FBS-500', 'BN20260415', 'Gibco', 2680.00, 16080.00, 'in', 6.0000, 0.0000, 6.0000, 'manual_in', 'zkxw', '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-01 08:10:00', 'd3000000000000000000000000000001', '2026-06-01 08:10:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_usage` WHERE `id`='qcu00000000000000000000000000002');
INSERT INTO `biz_qc_material_usage` (`id`, `material_id`, `material_code`, `material_name`, `batch_id`, `stock_in_no`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `change_type`, `change_qty`, `stock_before`, `stock_after`, `source_type`, `tenant_no`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcu00000000000000000000000000003', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-003' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-003', '青霉素-链霉素双抗', 'qcb00000000000000000000000000003', 'RK-20260601-003', 'CAT-PS-100', 'BN20260520', 'HyClone', 186.00, 1860.00, 'in', 10.0000, 0.0000, 10.0000, 'manual_in', 'zkxw', '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-02 08:20:00', 'd3000000000000000000000000000001', '2026-06-02 08:20:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_usage` WHERE `id`='qcu00000000000000000000000000003');
INSERT INTO `biz_qc_material_usage` (`id`, `material_id`, `material_code`, `material_name`, `batch_id`, `stock_in_no`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `change_type`, `change_qty`, `stock_before`, `stock_after`, `source_type`, `tenant_no`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcu00000000000000000000000000004', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-004' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-004', '胰酶消化液', 'qcb00000000000000000000000000004', 'RK-20260601-004', 'CAT-TRY-100', 'BN20260518', 'Sigma', 95.00, 760.00, 'in', 8.0000, 0.0000, 8.0000, 'manual_in', 'zkxw', '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-02 08:30:00', 'd3000000000000000000000000000001', '2026-06-02 08:30:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_usage` WHERE `id`='qcu00000000000000000000000000004');
INSERT INTO `biz_qc_material_usage` (`id`, `material_id`, `material_code`, `material_name`, `batch_id`, `stock_in_no`, `catalog_no`, `batch_no`, `manufacturer`, `unit_price`, `amount`, `change_type`, `change_qty`, `stock_before`, `stock_after`, `source_type`, `tenant_no`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`)
SELECT 'qcu00000000000000000000000000005', (SELECT `id` FROM `biz_qc_material` WHERE `material_code`='QC-MAT-005' AND `tenant_no`='zkxw' AND `del_flag`=0 LIMIT 1), 'QC-MAT-005', '台盼蓝染色液', 'qcb00000000000000000000000000005', 'RK-20260601-005', 'CAT-TB-50', 'BN20260525', 'Bio-Rad', 72.00, 360.00, 'in', 5.0000, 0.0000, 5.0000, 'manual_in', 'zkxw', '测试数据初始化', 'd3000000000000000000000000000001', '', '2026-06-03 08:40:00', 'd3000000000000000000000000000001', '2026-06-03 08:40:00', 0 FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM `biz_qc_material_usage` WHERE `id`='qcu00000000000000000000000000005');
+66 -1
View File
@@ -241,6 +241,12 @@ CREATE TABLE `biz_cell_product_spec` (
-- Records of biz_cell_product_spec
-- ----------------------------
BEGIN;
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000001', 'CPS-1.1E6-5ML', '1.1×10⁶/5ml', 'zkxw', 1, '低剂量规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000002', 'CPS-2.2E6-10ML', '2.2×10⁶/10ml', 'zkxw', 2, '低剂量规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000003', 'CPS-5.5E6-20ML', '5.5×10⁶/20ml', 'zkxw', 3, '标准规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000004', 'CPS-1.0E7-50ML', '1.0×10⁷/50ml', 'zkxw', 4, '标准规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000005', 'CPS-2.5E7-50ML', '2.5×10⁷/50ml', 'zkxw', 5, '高剂量规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_cell_product_spec` (`id`, `spec_code`, `spec_name`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cps000000000000000000000000000006', 'CPS-5.5E7-100ML', '5.5×10⁷/100ml', 'zkxw', 6, '高剂量规格', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -277,6 +283,7 @@ CREATE TABLE `biz_cell_sample_type` (
`id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主键ID',
`type_code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '样本类型编码',
`type_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '样本类型名称',
`type_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '样本类型Logo URL',
`storage_years` int(11) DEFAULT NULL COMMENT '样本存储年份',
`storage_price` decimal(18,2) DEFAULT NULL COMMENT '样本存储价格(元)',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
@@ -693,6 +700,7 @@ CREATE TABLE `biz_checkup_institution` (
`institution_address` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '体检机构地址',
`contact_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系人电话',
`institution_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '体检机构Logo URL',
`status` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1' COMMENT '1正常 0停用',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
@@ -711,6 +719,8 @@ CREATE TABLE `biz_checkup_institution` (
-- Records of biz_checkup_institution
-- ----------------------------
BEGIN;
INSERT INTO `biz_checkup_institution` (`id`, `institution_name`, `institution_address`, `contact_name`, `contact_phone`, `institution_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cki000000000000000000000000000001', '安徽省立医院健康管理中心', '合肥市庐阳区六安路9号', '王主任', '0551-6228340', NULL, '1', 'zkxw', 1, '测试数据-省立医院体检中心', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution` (`id`, `institution_name`, `institution_address`, `contact_name`, `contact_phone`, `institution_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('cki000000000000000000000000000002', '合肥美年大健康体检中心', '合肥市蜀山区潜山路188号', '刘经理', '0551-65588000', NULL, '1', 'zkxw', 2, '测试数据-美年大健康', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -743,6 +753,8 @@ CREATE TABLE `biz_checkup_institution_invoice` (
-- Records of biz_checkup_institution_invoice
-- ----------------------------
BEGIN;
INSERT INTO `biz_checkup_institution_invoice` (`id`, `checkup_institution_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckinv000000000000000000000000000001', 'cki000000000000000000000000000001', '安徽省立医院', '12340000000000001X', '合肥市庐阳区六安路9号', '0551-6228340', '中国建设银行合肥庐阳支行', '34000000000000000001', 'zkxw', 1, '测试开票信息-省立医院', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_invoice` (`id`, `checkup_institution_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckinv000000000000000000000000000002', 'cki000000000000000000000000000002', '合肥美年大健康产业控股集团有限公司', '91340100000000002Y', '合肥市蜀山区潜山路188号', '0551-65588000', '招商银行合肥分行营业部', '55100000000000000002', 'zkxw', 1, '测试开票信息-美年大健康', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -833,6 +845,26 @@ CREATE TABLE `biz_checkup_institution_project` (
-- Records of biz_checkup_institution_project
-- ----------------------------
BEGIN;
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000001', 'cki000000000000000000000000000001', '一般健康体检', 580.00, '1', 'zkxw', 1, '含内科、外科、眼科、耳鼻喉科', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000002', 'cki000000000000000000000000000001', '血常规', 45.00, '1', 'zkxw', 2, '全血细胞分析', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000003', 'cki000000000000000000000000000001', '肝功能全套', 120.00, '1', 'zkxw', 3, 'ALT/AST/总胆红素等', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000004', 'cki000000000000000000000000000001', '肾功能全套', 98.00, '1', 'zkxw', 4, '尿素氮/肌酐/尿酸', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000005', 'cki000000000000000000000000000001', '空腹血糖', 25.00, '1', 'zkxw', 5, '需空腹8小时以上', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000006', 'cki000000000000000000000000000001', '血脂四项', 68.00, '1', 'zkxw', 6, '总胆固醇/甘油三酯/HDL/LDL', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000007', 'cki000000000000000000000000000001', '心电图', 35.00, '1', 'zkxw', 7, '十二导联常规心电图', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000008', 'cki000000000000000000000000000001', '胸部DR', 80.00, '1', 'zkxw', 8, '数字化X线摄影', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000009', 'cki000000000000000000000000000001', '腹部B超', 120.00, '1', 'zkxw', 9, '肝、胆、脾、胰、双肾', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000010', 'cki000000000000000000000000000001', '肿瘤标志物筛查', 380.00, '1', 'zkxw', 10, 'CEA/AFP/CA199等组合', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000011', 'cki000000000000000000000000000002', '入职体检套餐A', 298.00, '1', 'zkxw', 1, '适用于一般岗位入职', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000012', 'cki000000000000000000000000000002', '高管健康体检', 1680.00, '1', 'zkxw', 2, '深度体检含专项评估', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000013', 'cki000000000000000000000000000002', '幽门螺旋杆菌检测', 85.00, '1', 'zkxw', 3, 'C13呼气试验', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000014', 'cki000000000000000000000000000002', '甲状腺彩超', 90.00, '1', 'zkxw', 4, '甲状腺形态及血流', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000015', 'cki000000000000000000000000000002', '颈动脉彩超', 160.00, '1', 'zkxw', 5, '评估动脉粥样硬化风险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000016', 'cki000000000000000000000000000002', '骨密度检测', 120.00, '1', 'zkxw', 6, '双能X线骨密度', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000017', 'cki000000000000000000000000000002', '动态血压监测', 200.00, '1', 'zkxw', 7, '24小时动态血压', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000018', 'cki000000000000000000000000000002', '眼底照相', 75.00, '1', 'zkxw', 8, '免散瞳眼底检查', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000019', 'cki000000000000000000000000000002', '肺功能检测', 150.00, '1', 'zkxw', 9, '肺通气功能检查', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_checkup_institution_project` (`id`, `checkup_institution_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ckp000000000000000000000000000020', 'cki000000000000000000000000000002', '细胞储存前专项体检', 880.00, '1', 'zkxw', 10, '细胞存储业务前置体检组合', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -846,6 +878,7 @@ CREATE TABLE `biz_clean_room` (
`room_grade` varchar(8) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '等级 A/B/C/D',
`room_status` varchar(16) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zc' COMMENT 'zc正常 yc异常',
`area_sqm` decimal(12,2) DEFAULT NULL COMMENT '面积m²',
`room_image` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '洁净室图片URL',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
@@ -1479,6 +1512,7 @@ CREATE TABLE `biz_express_company` (
`id` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '主键ID',
`express_code` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '快递公司编码',
`express_name` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '快递公司名称',
`express_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '快递公司Logo URL',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
@@ -1517,6 +1551,7 @@ CREATE TABLE `biz_insurance_company` (
`company_address` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '公司地址',
`contact_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系电话',
`company_logo` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '保险公司Logo URL',
`status` char(1) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '1' COMMENT '1正常 0停用',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
@@ -1535,6 +1570,8 @@ CREATE TABLE `biz_insurance_company` (
-- Records of biz_insurance_company
-- ----------------------------
BEGIN;
INSERT INTO `biz_insurance_company` (`id`, `company_name`, `company_address`, `contact_name`, `contact_phone`, `company_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('inc000000000000000000000000000001', '中国人民财产保险股份有限公司', '北京市西城区西长安街88号', '张经理', '010-95518', NULL, '1', 'zkxw', 1, '测试数据-人保财险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_company` (`id`, `company_name`, `company_address`, `contact_name`, `contact_phone`, `company_logo`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('inc000000000000000000000000000002', '中国平安财产保险股份有限公司', '深圳市福田区益田路5033号平安金融中心', '李经理', '95511', NULL, '1', 'zkxw', 2, '测试数据-平安财险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -1567,6 +1604,8 @@ CREATE TABLE `biz_insurance_company_invoice` (
-- Records of biz_insurance_company_invoice
-- ----------------------------
BEGIN;
INSERT INTO `biz_insurance_company_invoice` (`id`, `insurance_company_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('inv000000000000000000000000000001', 'inc000000000000000000000000000001', '中国人民财产保险股份有限公司', '91110000100000000X', '北京市西城区西长安街88号', '010-95518', '中国工商银行北京分行营业部', '02000000000000000001', 'zkxw', 1, '测试开票信息-人保', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_company_invoice` (`id`, `insurance_company_id`, `company_name`, `tax_no`, `company_address`, `company_phone`, `bank_name`, `bank_account`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('inv000000000000000000000000000002', 'inc000000000000000000000000000002', '中国平安财产保险股份有限公司', '91440300100000000Y', '深圳市福田区益田路5033号平安金融中心', '95511', '招商银行深圳分行营业部', '75500000000000000002', 'zkxw', 1, '测试开票信息-平安', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -1596,6 +1635,26 @@ CREATE TABLE `biz_insurance_project_price` (
-- Records of biz_insurance_project_price
-- ----------------------------
BEGIN;
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000001', 'inc000000000000000000000000000001', '细胞存储责任险', 1280.00, '1', 'zkxw', 1, '年度保费,覆盖样本存储期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000002', 'inc000000000000000000000000000001', '样本运输险', 680.00, '1', 'zkxw', 2, '覆盖样本冷链运输过程', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000003', 'inc000000000000000000000000000001', '实验室财产险', 3500.00, '1', 'zkxw', 3, '覆盖实验室设备与设施', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000004', 'inc000000000000000000000000000001', '公众责任险', 980.00, '1', 'zkxw', 4, '覆盖第三方人身及财产损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000005', 'inc000000000000000000000000000001', '产品责任险', 1680.00, '1', 'zkxw', 5, '覆盖细胞产品相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000006', 'inc000000000000000000000000000001', '雇主责任险', 2200.00, '1', 'zkxw', 6, '覆盖员工工伤及职业病', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000007', 'inc000000000000000000000000000001', '安全生产责任险', 1560.00, '1', 'zkxw', 7, '覆盖生产作业安全事故', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000008', 'inc000000000000000000000000000001', '医疗责任险', 3200.00, '1', 'zkxw', 8, '覆盖医疗服务相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000009', 'inc000000000000000000000000000001', '生物材料污染险', 890.00, '1', 'zkxw', 9, '覆盖生物样本污染损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000010', 'inc000000000000000000000000000001', '冷链中断险', 720.00, '1', 'zkxw', 10, '覆盖冷链设备故障导致损失', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000011', 'inc000000000000000000000000000002', '临床试验责任险', 2560.00, '1', 'zkxw', 1, '年度保费,覆盖临床试验期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000012', 'inc000000000000000000000000000002', '细胞治疗责任险', 3800.00, '1', 'zkxw', 2, '覆盖细胞治疗相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000013', 'inc000000000000000000000000000002', '研究者保险', 1200.00, '1', 'zkxw', 3, '覆盖主要研究者及团队', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000014', 'inc000000000000000000000000000002', '受试者保险', 980.00, '1', 'zkxw', 4, '覆盖临床试验受试者', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000015', 'inc000000000000000000000000000002', '试验器械险', 1450.00, '1', 'zkxw', 5, '覆盖试验用器械损坏', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000016', 'inc000000000000000000000000000002', '伦理审查责任险', 760.00, '1', 'zkxw', 6, '覆盖伦理审查相关责任', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000017', 'inc000000000000000000000000000002', '数据泄露责任险', 1100.00, '1', 'zkxw', 7, '覆盖试验数据泄露风险', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000018', 'inc000000000000000000000000000002', '跨境转运险', 1890.00, '1', 'zkxw', 8, '覆盖跨境样本转运', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000019', 'inc000000000000000000000000000002', '制剂稳定性险', 1350.00, '1', 'zkxw', 9, '覆盖制剂稳定性试验期间', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
INSERT INTO `biz_insurance_project_price` (`id`, `insurance_company_id`, `project_name`, `project_fee`, `status`, `tenant_no`, `order_num`, `remark`, `create_by`, `create_dept_id`, `create_time`, `update_by`, `update_time`, `del_flag`) VALUES ('ipp000000000000000000000000000020', 'inc000000000000000000000000000002', '不良事件保障险', 2100.00, '1', 'zkxw', 10, '覆盖试验不良事件处理', 'd3000000000000000000000000000001', '', '2026-06-14 08:00:00', 'd3000000000000000000000000000001', '2026-06-14 08:00:00', 0);
COMMIT;
-- ----------------------------
@@ -4276,6 +4335,8 @@ DROP TABLE IF EXISTS `biz_qc_material_stock_check_unused_line`;
CREATE TABLE `biz_qc_material_stock_check_unused_line` (
`id` varchar(64) NOT NULL COMMENT '主键ID',
`check_id` varchar(64) NOT NULL COMMENT '盘点单ID',
`usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(biz_qc_material_usage.id)',
`batch_id` varchar(64) DEFAULT NULL COMMENT '关联入库批次ID(手工登记批次检索)',
`material_code` varchar(64) DEFAULT NULL COMMENT '物料编码',
`material_name` varchar(200) NOT NULL COMMENT '物料名称',
`spec_model` varchar(200) DEFAULT NULL COMMENT '规格型号',
@@ -4299,7 +4360,8 @@ CREATE TABLE `biz_qc_material_stock_check_unused_line` (
`update_time` datetime NOT NULL COMMENT '更新时间',
`del_flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '删除标记',
PRIMARY KEY (`id`),
KEY `idx_qc_check_unused_line_check` (`check_id`,`del_flag`)
KEY `idx_qc_check_unused_line_check` (`check_id`,`del_flag`),
KEY `idx_qc_check_unused_line_usage` (`usage_id`,`del_flag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='质检物料盘点-领用未用完登记行';
-- ----------------------------
@@ -4334,6 +4396,7 @@ CREATE TABLE `biz_qc_material_usage` (
`parent_usage_id` varchar(64) DEFAULT NULL COMMENT '关联领用记录ID(task_complete指向manual_out)',
`receiver` varchar(64) DEFAULT NULL COMMENT '领用人(手动出库)',
`purpose` varchar(512) DEFAULT NULL COMMENT '用途/事由(手动出库)',
`requisition_status` varchar(16) NOT NULL DEFAULT 'open' COMMENT '领用状态:open-待登记/有剩余 closed-已使用完',
`source_type` varchar(32) NOT NULL COMMENT '来源:task_complete / manual_in / manual_out / outbound_handover 等',
`tenant_no` varchar(64) NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`remark` varchar(512) DEFAULT NULL COMMENT '备注',
@@ -4502,6 +4565,7 @@ CREATE TABLE `biz_qc_third_party_company` (
`company_name` varchar(200) NOT NULL COMMENT '公司名称',
`contact_name` varchar(100) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) DEFAULT NULL COMMENT '联系电话',
`company_logo` varchar(512) DEFAULT NULL COMMENT '公司Logo URL',
`address` varchar(500) DEFAULT NULL COMMENT '地址',
`invoice_title` varchar(200) DEFAULT NULL COMMENT '发票抬头',
`tax_id` varchar(64) DEFAULT NULL COMMENT '纳税人识别号',
@@ -6419,6 +6483,7 @@ CREATE TABLE `sys_site` (
`contact_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '联系电话',
`business_scope` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '业务范围(字典 zdywfw,多值可逗号分隔)',
`site_image` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '站点图片URL',
`tenant_no` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'zkxw' COMMENT '租户编号',
`order_num` int(11) DEFAULT NULL COMMENT '排序号',
`remark` varchar(512) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01 · 深色侧栏藏青 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #38bdf8;
--primary-dark: #0ea5e9;
--primary-bg: rgba(56, 189, 248, 0.14);
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--sidebar-bg: #0f172a;
--sidebar-border: #1e293b;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1><span class="demo-badge">推荐</span>01 · 深色侧栏藏青</h1>
<p>侧栏 #0f172a · 点缀天蓝 · Logo 绿最跳眼</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#0f172a"></i>侧栏</span><span class="swatch"><i style="background:#38bdf8"></i>点缀</span><span class="swatch"><i style="background:#f8fafc"></i>内容</span><span class="swatch"><i style="background:#e2e8f0"></i>边</span></div>
<div class="theme-jump"><a class="is-current" href="01-dark-sidebar.html">01</a><a class="" href="02-warm-stone.html">02</a><a class="" href="03-medical-blue.html">03</a><a class="" href="04-zinc-minimal.html">04</a><a class="" href="05-soft-violet.html">05</a><a class="" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar sidebar--dark">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">风格差异大:深色导航 + 白内容区,很多 LIS/HIS 系统采用;Logo 绿色会非常醒目。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+299
View File
@@ -0,0 +1,299 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>02 · 暖石米灰 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #57534e;
--primary-dark: #44403c;
--primary-bg: #f5f5f4;
--text: #292524;
--text-muted: #78716c;
--border: #e7e5e4;
--bg-page: #fafaf9;
--surface: #ffffff;
--table-head: #f5f5f4;
--row-alt: #f5f5f4;
--row-hover: #ececea;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body class="layout-warm">
<div class="demo-banner">
<div>
<h1>02 · 暖石米灰</h1>
<p>暖灰主色 #57534e · 米白底 · 不冷不艳</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#57534e"></i>主色</span><span class="swatch"><i style="background:#44403c"></i>深</span><span class="swatch"><i style="background:#fafaf9"></i>浅底</span><span class="swatch"><i style="background:#e7e5e4"></i>边</span></div>
<div class="theme-jump"><a class="" href="01-dark-sidebar.html">01</a><a class="is-current" href="02-warm-stone.html">02</a><a class="" href="03-medical-blue.html">03</a><a class="" href="04-zinc-minimal.html">04</a><a class="" href="05-soft-violet.html">05</a><a class="" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">偏纸质/档案感,长时间看不疲劳;适合财务、合规、大量表格录入。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+299
View File
@@ -0,0 +1,299 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>03 · 经典医院蓝 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #0077b6;
--primary-dark: #023e8a;
--primary-bg: #e8f4fa;
--text: #1e293b;
--text-muted: #64748b;
--border: #bde0fe;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>03 · 经典医院蓝</h1>
<p>主色 #0077b6 · 传统医疗信息系统气质</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#0077b6"></i>主色</span><span class="swatch"><i style="background:#023e8a"></i>深</span><span class="swatch"><i style="background:#e8f4fa"></i>浅底</span><span class="swatch"><i style="background:#bde0fe"></i>边</span></div>
<div class="theme-jump"><a class="" href="01-dark-sidebar.html">01</a><a class="" href="02-warm-stone.html">02</a><a class="is-current" href="03-medical-blue.html">03</a><a class="" href="04-zinc-minimal.html">04</a><a class="" href="05-soft-violet.html">05</a><a class="" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">比 Tailwind 蓝更「医院感」;稳重、熟悉,中老年用户接受度高。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>04 · 锌灰极简 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #52525b;
--primary-dark: #3f3f46;
--primary-bg: #f4f4f5;
--text: #1e293b;
--text-muted: #64748b;
--border: #e4e4e7;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--cta: #18181b;
--cta-dark: #27272a;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>04 · 锌灰极简</h1>
<p>几乎无彩色 · 主按钮 #18181b · Logo 是唯一亮点</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#52525b"></i>导航</span><span class="swatch"><i style="background:#18181b"></i>按钮</span><span class="swatch"><i style="background:#fafafa"></i>浅底</span><span class="swatch"><i style="background:#e4e4e7"></i>边</span></div>
<div class="theme-jump"><a class="" href="01-dark-sidebar.html">01</a><a class="" href="02-warm-stone.html">02</a><a class="" href="03-medical-blue.html">03</a><a class="is-current" href="04-zinc-minimal.html">04</a><a class="" href="05-soft-violet.html">05</a><a class="" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">极简 B 端:界面本身不抢戏,状态 Tag 保留语义色;适合数据密集页面。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+299
View File
@@ -0,0 +1,299 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>05 · 薄雾紫 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #7c6fad;
--primary-dark: #6b5b95;
--primary-bg: #f3f0f8;
--text: #1e293b;
--text-muted: #64748b;
--border: #ddd6fe;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>05 · 薄雾紫</h1>
<p>主色 #7c6fad · 舒缓、偏医疗康养</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#7c6fad"></i>主色</span><span class="swatch"><i style="background:#6b5b95"></i>深</span><span class="swatch"><i style="background:#f3f0f8"></i>浅底</span><span class="swatch"><i style="background:#ddd6fe"></i>边</span></div>
<div class="theme-jump"><a class="" href="01-dark-sidebar.html">01</a><a class="" href="02-warm-stone.html">02</a><a class="" href="03-medical-blue.html">03</a><a class="" href="04-zinc-minimal.html">04</a><a class="is-current" href="05-soft-violet.html">05</a><a class="" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">低饱和紫,比靛蓝更柔;适合客服、客户档案类模块,主列表页需实测。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+299
View File
@@ -0,0 +1,299 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>06 · 墨蓝权威 · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #1e3a5f;
--primary-dark: #152a45;
--primary-bg: #eef2f6;
--text: #1e293b;
--text-muted: #64748b;
--border: #c5d0dc;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>06 · 墨蓝权威</h1>
<p>主色 #1e3a5f · 传统企业门户</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#1e3a5f"></i>主色</span><span class="swatch"><i style="background:#152a45"></i>深</span><span class="swatch"><i style="background:#eef2f6"></i>浅底</span><span class="swatch"><i style="background:#c5d0dc"></i>边</span></div>
<div class="theme-jump"><a class="" href="01-dark-sidebar.html">01</a><a class="" href="02-warm-stone.html">02</a><a class="" href="03-medical-blue.html">03</a><a class="" href="04-zinc-minimal.html">04</a><a class="" href="05-soft-violet.html">05</a><a class="is-current" href="06-navy-authority.html">06</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">深藏青,权威合规感强;与绿色 Logo 对比清晰,适合审批流、协议类页面。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+734
View File
@@ -0,0 +1,734 @@
/* 管理端主题 Demo B(布局/气质与 batch A 不同) */
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: Inter, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--bg-page);
}
.demo-banner {
position: sticky;
top: 0;
z-index: 100;
padding: 10px 20px;
background: #fff;
border-bottom: 1px solid #e2e8f0;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
.demo-banner h1 {
margin: 0;
font-size: 14px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.demo-banner p {
margin: 2px 0 0;
font-size: 12px;
color: #64748b;
}
.demo-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
background: #eff6ff;
color: #1d4ed8;
}
.demo-banner__actions {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.theme-jump {
display: flex;
gap: 4px;
flex-wrap: wrap;
}
.theme-jump a {
padding: 4px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
text-decoration: none;
color: #64748b;
border: 1px solid #e2e8f0;
background: #fff;
}
.theme-jump a:hover {
border-color: var(--primary);
color: var(--primary-dark);
}
.theme-jump a.is-current {
background: var(--primary-bg);
border-color: var(--primary);
color: var(--primary-dark);
}
.swatch-row {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.swatch {
font-size: 10px;
color: #64748b;
display: flex;
align-items: center;
gap: 4px;
}
.swatch i {
width: 12px;
height: 12px;
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
.link-back {
font-size: 12px;
color: var(--primary-dark);
text-decoration: none;
font-weight: 500;
}
.app-layout {
display: flex;
min-height: calc(100vh - 48px);
}
.sidebar {
width: 220px;
flex-shrink: 0;
background: var(--surface);
border-right: 1px solid var(--border);
padding: 18px 12px;
display: flex;
flex-direction: column;
}
.sidebar--dark {
background: var(--sidebar-bg, #0f172a);
border-right-color: var(--sidebar-border, #1e293b);
}
.sidebar--dark .brand {
border-bottom-color: rgba(255, 255, 255, 0.08);
}
.sidebar--dark .brand-text {
color: #f8fafc;
}
.sidebar--dark .brand-text small {
color: #94a3b8;
}
.sidebar--dark .nav-group-title {
color: #64748b;
}
.sidebar--dark .nav a {
color: #94a3b8;
}
.sidebar--dark .nav a::before {
background: rgba(255, 255, 255, 0.08);
}
.sidebar--dark .nav a:hover {
background: rgba(255, 255, 255, 0.06);
color: #e2e8f0;
}
.sidebar--dark .nav a.active {
background: var(--primary-bg);
color: var(--primary);
}
.sidebar--dark .nav a.active::before {
background: var(--primary);
}
.brand {
display: flex;
align-items: center;
gap: 10px;
padding: 4px 10px 16px;
margin-bottom: 6px;
border-bottom: 1px solid var(--border);
}
.brand-logo {
width: 36px;
height: 36px;
object-fit: contain;
flex-shrink: 0;
}
.brand-text {
font-size: 14px;
font-weight: 700;
line-height: 1.3;
}
.brand-text small {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--text-muted);
}
.nav-group {
margin-bottom: 8px;
}
.nav-group-title {
padding: 6px 12px;
font-size: 11px;
font-weight: 700;
color: var(--text-muted);
letter-spacing: 0.03em;
}
.nav a {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
margin: 1px 0;
border-radius: 8px;
color: var(--text-muted);
text-decoration: none;
font-size: 13px;
font-weight: 500;
}
.nav a::before {
content: '';
width: 16px;
height: 16px;
border-radius: 4px;
background: var(--row-alt);
flex-shrink: 0;
}
.nav a:hover {
background: var(--row-alt);
color: var(--text);
}
.nav a.active {
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
.nav a.active::before {
background: var(--primary);
}
.main-col {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
.topbar {
height: 56px;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.crumb {
font-size: 13px;
color: var(--text-muted);
}
.crumb b {
color: var(--text);
font-weight: 600;
}
.topbar-right {
display: flex;
align-items: center;
gap: 12px;
font-size: 13px;
color: var(--text-muted);
}
.avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--primary-bg);
border: 1px solid var(--border);
color: var(--primary-dark);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
}
.work-tabs {
display: flex;
align-items: flex-end;
gap: 4px;
padding: 10px 24px 0;
background: var(--bg-page);
border-bottom: 1px solid var(--border);
}
.work-tab {
padding: 8px 14px;
border: 1px solid var(--border);
border-bottom: none;
border-radius: 8px 8px 0 0;
background: var(--surface);
font-size: 13px;
font-weight: 600;
color: var(--text-muted);
margin-bottom: -1px;
}
.work-tab.is-active {
color: var(--primary-dark);
box-shadow: inset 0 2px 0 var(--cta, var(--primary));
z-index: 1;
}
.content {
flex: 1;
padding: 24px;
overflow: auto;
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.panel-top {
padding: 16px 20px 0;
}
.title-bar-heading {
margin: 0 0 4px;
font-size: 16px;
font-weight: 600;
color: var(--text);
position: relative;
padding-left: 12px;
}
.title-bar-heading::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
border-radius: 2px;
background: var(--cta, var(--primary));
}
.entity-switch {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
padding: 12px 16px 12px;
}
.entity-card {
flex: 0 1 168px;
min-width: 152px;
max-width: 180px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
display: flex;
gap: 8px;
align-items: center;
cursor: default;
}
.entity-card.is-active {
border-color: var(--primary);
background: var(--primary-bg);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);
}
.entity-card__icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: #f1f5f9;
color: #64748b;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
flex-shrink: 0;
}
.entity-card.is-active .entity-card__icon {
background: #fff;
color: var(--primary-dark);
}
.entity-card__title {
font-size: 13px;
font-weight: 600;
color: var(--text);
}
.entity-card.is-active .entity-card__title {
color: var(--primary-dark);
}
.entity-card__desc {
font-size: 11px;
color: var(--text-muted);
line-height: 1.35;
}
.filter-block {
padding: 16px 20px 4px;
border-bottom: 1px solid var(--border);
}
.filter-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px 16px;
}
@media (max-width: 1100px) {
.filter-grid {
grid-template-columns: repeat(2, 1fr);
}
}
.field label {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--text-muted);
margin-bottom: 6px;
}
.input,
.select {
height: 36px;
width: 100%;
padding: 0 12px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
font-size: 14px;
color: var(--text);
font-family: inherit;
}
.input:focus,
.select:focus {
outline: none;
border-color: var(--cta, var(--primary));
box-shadow: 0 0 0 2px color-mix(in srgb, var(--cta, var(--primary)) 20%, transparent);
}
.filter-actions {
display: flex;
gap: 8px;
padding: 12px 0 16px;
}
.list-toolbar {
padding: 12px 20px;
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid var(--border);
background: var(--table-head);
}
.sel-num {
font-size: 13px;
color: var(--text-muted);
margin-right: 4px;
}
.sel-num b {
color: var(--cta-dark, var(--primary-dark));
}
.btn {
height: 36px;
padding: 0 14px;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: default;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-family: inherit;
display: inline-flex;
align-items: center;
gap: 6px;
}
.btn-primary {
background: var(--cta, var(--primary));
border-color: var(--cta, var(--primary));
color: #fff;
}
.btn-primary:hover {
background: var(--cta-dark, var(--primary-dark));
border-color: var(--cta-dark, var(--primary-dark));
}
.btn-op {
height: 28px;
padding: 0 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
margin-right: 4px;
}
.btn-op.primary {
color: var(--cta-dark, var(--primary-dark));
border-color: color-mix(in srgb, var(--cta, var(--primary)) 35%, var(--border));
background: var(--primary-bg);
}
.list-body {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
min-width: 900px;
}
th {
text-align: left;
padding: 10px 14px;
font-size: 12px;
font-weight: 600;
color: var(--text-muted);
background: var(--table-head);
border-bottom: 1px solid var(--border);
white-space: nowrap;
}
td {
padding: 11px 14px;
border-bottom: 1px solid var(--border);
font-size: 13px;
}
tr:hover td {
background: var(--row-hover);
}
tr:nth-child(even) td {
background: var(--row-alt);
}
tr:nth-child(even):hover td {
background: var(--row-hover);
}
.tag {
display: inline-block;
padding: 2px 8px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
}
.tag-info {
background: #f8fafc;
color: #64748b;
}
.tag-success {
background: #d1fae5;
color: #047857;
}
.tag-warning {
background: #fffbeb;
color: #d97706;
}
.tag-danger {
background: #fef2f2;
color: #dc2626;
}
.tag-primary {
background: var(--primary-bg);
color: var(--primary-dark);
}
.pager {
padding: 12px 20px;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
border-top: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
.pager-btn {
min-width: 32px;
height: 32px;
padding: 0 8px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-size: 13px;
font-weight: 500;
}
.pager-btn.is-active {
background: var(--cta, var(--primary));
border-color: var(--cta, var(--primary));
color: #fff;
}
.demo-bottom {
display: grid;
grid-template-columns: 1fr 380px;
gap: 20px;
margin-top: 20px;
}
@media (max-width: 1200px) {
.demo-bottom {
grid-template-columns: 1fr;
}
}
.stats-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.stat-card {
padding: 14px 16px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
}
.stat-card .label {
font-size: 12px;
color: var(--text-muted);
}
.stat-card .value {
margin-top: 4px;
font-size: 22px;
font-weight: 700;
color: var(--cta-dark, var(--primary-dark));
}
.stat-card.warn .value {
color: #d97706;
}
.dialog-preview {
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
overflow: hidden;
}
.dialog-head {
padding: 14px 18px;
border-bottom: 1px solid var(--border);
font-size: 15px;
font-weight: 600;
}
.dialog-body {
padding: 16px 18px;
max-height: 280px;
overflow: auto;
}
.form-grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.dialog-foot {
padding: 12px 18px;
border-top: 1px solid var(--border);
display: flex;
justify-content: flex-end;
gap: 8px;
background: var(--table-head);
}
.theme-note {
margin-top: 16px;
padding: 12px 16px;
border-radius: 8px;
background: var(--primary-bg);
border: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
+433
View File
@@ -0,0 +1,433 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const themes = [
{
id: '01',
file: '01-dark-sidebar.html',
title: '01 · 深色侧栏藏青',
desc: '侧栏 #0f172a · 点缀天蓝 · Logo 绿最跳眼',
note: '风格差异大:深色导航 + 白内容区,很多 LIS/HIS 系统采用;Logo 绿色会非常醒目。',
primary: '#38bdf8',
dark: '#0ea5e9',
bg: 'rgba(56, 189, 248, 0.14)',
border: '#e2e8f0',
swatches: ['#0f172a', '#38bdf8', '#f8fafc', '#e2e8f0'],
darkSidebar: true,
recommended: true
},
{
id: '02',
file: '02-warm-stone.html',
title: '02 · 暖石米灰',
desc: '暖灰主色 #57534e · 米白底 · 不冷不艳',
note: '偏纸质/档案感,长时间看不疲劳;适合财务、合规、大量表格录入。',
primary: '#57534e',
dark: '#44403c',
bg: '#f5f5f4',
border: '#e7e5e4',
pageBg: '#fafaf9',
tableHead: '#f5f5f4',
text: '#292524',
textMuted: '#78716c',
swatches: ['#57534e', '#44403c', '#fafaf9', '#e7e5e4'],
warm: true
},
{
id: '03',
file: '03-medical-blue.html',
title: '03 · 经典医院蓝',
desc: '主色 #0077b6 · 传统医疗信息系统气质',
note: '比 Tailwind 蓝更「医院感」;稳重、熟悉,中老年用户接受度高。',
primary: '#0077b6',
dark: '#023e8a',
bg: '#e8f4fa',
border: '#bde0fe',
swatches: ['#0077b6', '#023e8a', '#e8f4fa', '#bde0fe']
},
{
id: '04',
file: '04-zinc-minimal.html',
title: '04 · 锌灰极简',
desc: '几乎无彩色 · 主按钮 #18181b · Logo 是唯一亮点',
note: '极简 B 端:界面本身不抢戏,状态 Tag 保留语义色;适合数据密集页面。',
primary: '#52525b',
dark: '#3f3f46',
bg: '#f4f4f5',
border: '#e4e4e7',
cta: '#18181b',
ctaDark: '#27272a',
swatches: ['#52525b', '#18181b', '#fafafa', '#e4e4e7']
},
{
id: '05',
file: '05-soft-violet.html',
title: '05 · 薄雾紫',
desc: '主色 #7c6fad · 舒缓、偏医疗康养',
note: '低饱和紫,比靛蓝更柔;适合客服、客户档案类模块,主列表页需实测。',
primary: '#7c6fad',
dark: '#6b5b95',
bg: '#f3f0f8',
border: '#ddd6fe',
swatches: ['#7c6fad', '#6b5b95', '#f3f0f8', '#ddd6fe']
},
{
id: '06',
file: '06-navy-authority.html',
title: '06 · 墨蓝权威',
desc: '主色 #1e3a5f · 传统企业门户',
note: '深藏青,权威合规感强;与绿色 Logo 对比清晰,适合审批流、协议类页面。',
primary: '#1e3a5f',
dark: '#152a45',
bg: '#eef2f6',
border: '#c5d0dc',
swatches: ['#1e3a5f', '#152a45', '#eef2f6', '#c5d0dc']
}
]
function themeJump(currentId) {
return themes
.map((t) => {
const cls = t.id === currentId ? 'is-current' : ''
return `<a class="${cls}" href="${t.file}">${t.id}</a>`
})
.join('')
}
function swatchesHtml(theme) {
const labels = theme.cta
? ['导航', '按钮', '浅底', '边']
: theme.darkSidebar
? ['侧栏', '点缀', '内容', '边']
: ['主色', '深', '浅底', '边']
return theme.swatches
.map((c, i) => `<span class="swatch"><i style="background:${c}"></i>${labels[i]}</span>`)
.join('')
}
function rootVars(theme) {
const lines = [
` --primary: ${theme.primary};`,
` --primary-dark: ${theme.dark};`,
` --primary-bg: ${theme.bg};`,
` --text: ${theme.text || '#1e293b'};`,
` --text-muted: ${theme.textMuted || '#64748b'};`,
` --border: ${theme.border};`,
` --bg-page: ${theme.pageBg || '#fefefe'};`,
` --surface: #ffffff;`,
` --table-head: ${theme.tableHead || '#f8fafc'};`,
` --row-alt: ${theme.warm ? '#f5f5f4' : '#fafafa'};`,
` --row-hover: ${theme.warm ? '#ececea' : '#f1f5f9'};`,
` --shadow: 0 1px 3px rgba(0, 0, 0, 0.05);`,
` --radius: 10px;`
]
if (theme.darkSidebar) {
lines.push(` --sidebar-bg: #0f172a;`, ` --sidebar-border: #1e293b;`)
}
if (theme.cta) {
lines.push(` --cta: ${theme.cta};`, ` --cta-dark: ${theme.ctaDark};`)
}
return lines.join('\n')
}
function renderPage(theme) {
const badge = theme.recommended ? '<span class="demo-badge">推荐</span>' : ''
const bodyClass = theme.warm ? ' class="layout-warm"' : ''
const sidebarClass = theme.darkSidebar ? 'sidebar sidebar--dark' : 'sidebar'
return `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${theme.title} · 管理端界面 Demo B</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
${rootVars(theme)}
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body${bodyClass}>
<div class="demo-banner">
<div>
<h1>${badge}${theme.title}</h1>
<p>${theme.desc}</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row">${swatchesHtml(theme)}</div>
<div class="theme-jump">${themeJump(theme.id)}</div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="${sidebarClass}">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">${theme.note}</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>`
}
for (const theme of themes) {
fs.writeFileSync(path.join(__dirname, theme.file), renderPage(theme))
console.log('written', theme.file)
}
+269
View File
@@ -0,0 +1,269 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Web 管理端 · 主题选型 B(不同风格)</title>
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
rel="stylesheet"
/>
<style>
:root {
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--surface: #fff;
--bg: #f8fafc;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: Inter, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--bg);
padding: 32px 24px 48px;
}
h1 {
margin: 0 0 8px;
font-size: 22px;
}
h2.section-title {
margin: 36px 0 16px;
font-size: 15px;
font-weight: 600;
color: var(--text-muted);
}
.lead {
margin: 0 0 12px;
color: var(--text-muted);
max-width: 760px;
}
.hint {
margin: 0 0 28px;
padding: 12px 16px;
max-width: 760px;
border-radius: 10px;
background: #fff;
border: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 16px;
max-width: 1100px;
}
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
padding: 18px;
text-decoration: none;
color: inherit;
transition:
box-shadow 0.2s,
border-color 0.2s;
}
.card:hover {
border-color: #cbd5e1;
box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08);
}
.card h2 {
margin: 0 0 6px;
font-size: 16px;
}
.card p {
margin: 0 0 14px;
font-size: 13px;
color: var(--text-muted);
}
.colors {
display: flex;
gap: 6px;
margin-bottom: 12px;
align-items: center;
flex-wrap: wrap;
}
.colors span {
width: 36px;
height: 36px;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
.colors .logo-chip {
width: auto;
height: auto;
padding: 4px 8px;
font-size: 11px;
font-weight: 600;
background: #ecfdf5;
color: #047857;
border-color: #a7f3d0;
}
.colors .dark-chip {
background: #0f172a;
}
.meta {
font-size: 12px;
color: var(--text-muted);
font-family: ui-monospace, monospace;
}
.badge {
display: inline-block;
margin-bottom: 10px;
padding: 2px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
background: #f1f5f9;
color: #475569;
}
.badge.recommend {
background: #eff6ff;
color: #1d4ed8;
}
.badge.style {
background: #fef3c7;
color: #92400e;
}
.footer-links {
margin-top: 32px;
max-width: 760px;
font-size: 13px;
color: var(--text-muted);
}
.footer-links a {
color: #2563eb;
text-decoration: none;
font-weight: 500;
}
.footer-links a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1>Web 管理端 · 主题选型 B</h1>
<p class="lead">
上一批(蓝/靛/青绿)若仍不满意,这批换<strong>布局气质</strong>:深色侧栏、暖灰米白、经典医院蓝、极简无色、薄雾紫、墨蓝权威。Logo
仍为真实绿色。
</p>
<p class="hint">
<strong>打开:</strong><code>docs/theme-demos-alt/index.html</code> · 每页顶部可切换 01~06
</p>
<div class="grid">
<a class="card" href="01-dark-sidebar.html">
<span class="badge recommend">推荐</span>
<span class="badge style">深色侧栏</span>
<h2>01 · 深色侧栏藏青</h2>
<p>侧栏藏青 + 白天蓝点缀;Logo 绿在暗底上非常跳。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span class="dark-chip"></span>
<span style="background: #38bdf8"></span>
<span style="background: #f8fafc"></span>
</div>
<div class="meta">侧栏 #0f172a · 点缀 #38bdf8</div>
</a>
<a class="card" href="02-warm-stone.html">
<span class="badge style">暖中性</span>
<h2>02 · 暖石米灰</h2>
<p>米白底 + 暖灰主色,不冷也不艳,像纸质档案系统。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span style="background: #57534e"></span>
<span style="background: #fafaf9"></span>
<span style="background: #e7e5e4"></span>
</div>
<div class="meta">#57534e · #fafaf9 · #e7e5e4</div>
</a>
<a class="card" href="03-medical-blue.html">
<span class="badge style">医院感</span>
<h2>03 · 经典医院蓝</h2>
<p>传统 HIS/LIS 常见蓝,比 Tailwind 蓝更「医疗」。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span style="background: #0077b6"></span>
<span style="background: #023e8a"></span>
<span style="background: #e8f4fa"></span>
</div>
<div class="meta">#0077b6 · #023e8a · #e8f4fa</div>
</a>
<a class="card" href="04-zinc-minimal.html">
<span class="badge style">极简</span>
<h2>04 · 锌灰极简</h2>
<p>界面几乎无色,黑按钮 + 绿 Logo,数据页不抢戏。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span style="background: #52525b"></span>
<span style="background: #18181b"></span>
<span style="background: #fafafa"></span>
</div>
<div class="meta">按钮 #18181b · 底 #fafafa</div>
</a>
<a class="card" href="05-soft-violet.html">
<span class="badge style">康养</span>
<h2>05 · 薄雾紫</h2>
<p>低饱和紫,偏医疗康养、客服档案气质。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span style="background: #7c6fad"></span>
<span style="background: #6b5b95"></span>
<span style="background: #f3f0f8"></span>
</div>
<div class="meta">#7c6fad · #6b5b95 · #f3f0f8</div>
</a>
<a class="card" href="06-navy-authority.html">
<span class="badge style">权威</span>
<h2>06 · 墨蓝权威</h2>
<p>深藏青,审批/协议/合规感强,传统企业门户。</p>
<div class="colors">
<span class="logo-chip">Logo 绿</span>
<span style="background: #1e3a5f"></span>
<span style="background: #152a45"></span>
<span style="background: #eef2f6"></span>
</div>
<div class="meta">#1e3a5f · #152a45 · #eef2f6</div>
</a>
</div>
<p class="footer-links">
上一批方案见 <a href="../theme-demos/index.html">主题选型 A(00~04)</a> · 全绿色系见
<a href="../green-theme-demos/index.html">深绿变体(01~06)</a>
</p>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>00 · 现行薄荷绿(Logo 同色) · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #10b981;
--primary-dark: #059669;
--primary-bg: #ecfdf5;
--text: #1e293b;
--text-muted: #64748b;
--border: #d9e8e2;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--brand-green: #10b981;
--brand-green-dark: #059669;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1><span class="demo-badge demo-badge--warn">现状</span>00 · 现行薄荷绿(Logo 同色)</h1>
<p>主色 #10b981 与 Logo 同为绿色 · 层次易糊</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#10b981"></i>主色</span><span class="swatch"><i style="background:#059669"></i>深</span><span class="swatch"><i style="background:#ecfdf5"></i>浅底</span><span class="swatch"><i style="background:#d9e8e2"></i>边</span></div>
<div class="theme-jump"><a class="is-current" href="00-fresh-mint-clash.html">00</a><a class="" href="01-slate-blue.html">01</a><a class="" href="02-bio-teal.html">02</a><a class="" href="03-graphite-blue.html">03</a><a class="" href="04-indigo-tech.html">04</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">对比基准:Logo 绿 + UI 绿叠在一起,是当前觉得「不好看」的典型情况。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>01 · 深海蓝(推荐) · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #2563eb;
--primary-dark: #1d4ed8;
--primary-bg: #eff6ff;
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--brand-green: #10b981;
--brand-green-dark: #059669;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1><span class="demo-badge">推荐</span>01 · 深海蓝(推荐)</h1>
<p>主色 #2563eb · Logo 绿 + UI 蓝,专业医疗后台</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#2563eb"></i>主色</span><span class="swatch"><i style="background:#1d4ed8"></i>深</span><span class="swatch"><i style="background:#eff6ff"></i>浅底</span><span class="swatch"><i style="background:#e2e8f0"></i>边</span></div>
<div class="theme-jump"><a class="" href="00-fresh-mint-clash.html">00</a><a class="is-current" href="01-slate-blue.html">01</a><a class="" href="02-bio-teal.html">02</a><a class="" href="03-graphite-blue.html">03</a><a class="" href="04-indigo-tech.html">04</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">推荐首选:与绿色 Logo 互补,成功/进行中仍用绿色 Tag,操作引导清晰。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>02 · 生物青绿 · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #0d9488;
--primary-dark: #0f766e;
--primary-bg: #f0fdfa;
--text: #1e293b;
--text-muted: #64748b;
--border: #cce7e4;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--brand-green: #10b981;
--brand-green-dark: #059669;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>02 · 生物青绿</h1>
<p>主色 #0d9488 · 偏蓝的 Teal,保留生命感</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#0d9488"></i>主色</span><span class="swatch"><i style="background:#0f766e"></i>深</span><span class="swatch"><i style="background:#f0fdfa"></i>浅底</span><span class="swatch"><i style="background:#cce7e4"></i>边</span></div>
<div class="theme-jump"><a class="" href="00-fresh-mint-clash.html">00</a><a class="" href="01-slate-blue.html">01</a><a class="is-current" href="02-bio-teal.html">02</a><a class="" href="03-graphite-blue.html">03</a><a class="" href="04-indigo-tech.html">04</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">折中方案:比薄荷绿沉、比纯蓝更有生物气质;注意与成功 Tag 绿色区分。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+303
View File
@@ -0,0 +1,303 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>03 · 石墨灰 + 蓝色按钮 · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #475569;
--primary-dark: #334155;
--primary-bg: #f8fafc;
--text: #1e293b;
--text-muted: #64748b;
--border: #e2e8f0;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--brand-green: #10b981;
--brand-green-dark: #059669;
--cta: #0369a1;
--cta-dark: #0284c7;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>03 · 石墨灰 + 蓝色按钮</h1>
<p>导航 Slate #475569 · 主按钮 #0369a1</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#475569"></i>导航</span><span class="swatch"><i style="background:#0369a1"></i>按钮</span><span class="swatch"><i style="background:#f8fafc"></i>浅底</span><span class="swatch"><i style="background:#e2e8f0"></i>边</span></div>
<div class="theme-jump"><a class="" href="00-fresh-mint-clash.html">00</a><a class="" href="01-slate-blue.html">01</a><a class="" href="02-bio-teal.html">02</a><a class="is-current" href="03-graphite-blue.html">03</a><a class="" href="04-indigo-tech.html">04</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">最克制:界面几乎无彩色,Logo 绿最突出;主按钮单独用蓝色强调。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+301
View File
@@ -0,0 +1,301 @@
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>04 · 靛蓝科技 · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
--primary: #4f46e5;
--primary-dark: #4338ca;
--primary-bg: #eef2ff;
--text: #1e293b;
--text-muted: #64748b;
--border: #c7d2fe;
--bg-page: #fefefe;
--surface: #ffffff;
--table-head: #f8fafc;
--row-alt: #fafafa;
--row-hover: #f1f5f9;
--shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
--radius: 10px;
--brand-green: #10b981;
--brand-green-dark: #059669;
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>04 · 靛蓝科技</h1>
<p>主色 #4f46e5 · 偏生物科技平台气质</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row"><span class="swatch"><i style="background:#4f46e5"></i>主色</span><span class="swatch"><i style="background:#4338ca"></i>深</span><span class="swatch"><i style="background:#eef2ff"></i>浅底</span><span class="swatch"><i style="background:#c7d2fe"></i>边</span></div>
<div class="theme-jump"><a class="" href="00-fresh-mint-clash.html">00</a><a class="" href="01-slate-blue.html">01</a><a class="" href="02-bio-teal.html">02</a><a class="" href="03-graphite-blue.html">03</a><a class="is-current" href="04-indigo-tech.html">04</a></div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">辨识度高、略活泼;适合强调数字化,医疗场景需控制 Tag 饱和度。</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+696
View File
@@ -0,0 +1,696 @@
/* 管理端主题 Demo(Logo 绿固定,:root 覆盖 UI 主色) */
* {
box-sizing: border-box;
}
body {
margin: 0;
min-height: 100vh;
font-family: Inter, -apple-system, sans-serif;
font-size: 14px;
line-height: 1.5;
color: var(--text);
background: var(--bg-page);
}
.demo-banner {
position: sticky;
top: 0;
z-index: 100;
padding: 10px 20px;
background: #fff;
border-bottom: 1px solid #e2e8f0;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04);
}
.demo-banner h1 {
margin: 0;
font-size: 14px;
font-weight: 600;
display: flex;
align-items: center;
gap: 8px;
flex-wrap: wrap;
}
.demo-banner p {
margin: 2px 0 0;
font-size: 12px;
color: #64748b;
}
.demo-badge {
display: inline-block;
padding: 2px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
background: #eff6ff;
color: #1d4ed8;
}
.demo-badge--warn {
background: #ecfdf5;
color: #047857;
}
.demo-banner__actions {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.theme-jump {
display: flex;
gap: 4px;
flex-wrap: wrap;
}
.theme-jump a {
padding: 4px 8px;
border-radius: 6px;
font-size: 11px;
font-weight: 600;
text-decoration: none;
color: #64748b;
border: 1px solid #e2e8f0;
background: #fff;
}
.theme-jump a:hover {
border-color: var(--primary);
color: var(--primary-dark);
}
.theme-jump a.is-current {
background: var(--primary-bg);
border-color: var(--primary);
color: var(--primary-dark);
}
.swatch-row {
display: flex;
gap: 6px;
flex-wrap: wrap;
}
.swatch {
font-size: 10px;
color: #64748b;
display: flex;
align-items: center;
gap: 4px;
}
.swatch i {
width: 12px;
height: 12px;
border-radius: 3px;
border: 1px solid rgba(0, 0, 0, 0.06);
}
.link-back {
font-size: 12px;
color: var(--primary-dark);
text-decoration: none;
font-weight: 500;
}
.app-layout {
display: flex;
min-height: calc(100vh - 48px);
}
.sidebar {
width: 220px;
flex-shrink: 0;
background: var(--surface);
border-right: 1px solid var(--border);
padding: 18px 12px;
display: flex;
flex-direction: column;
}
.brand {
display: flex;
align-items: center;
gap: 10px;
padding: 4px 10px 16px;
margin-bottom: 6px;
border-bottom: 1px solid var(--border);
}
.brand-logo {
width: 36px;
height: 36px;
object-fit: contain;
flex-shrink: 0;
}
.brand-text {
font-size: 14px;
font-weight: 700;
line-height: 1.3;
}
.brand-text small {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--text-muted);
}
.nav-group {
margin-bottom: 8px;
}
.nav-group-title {
padding: 6px 12px;
font-size: 11px;
font-weight: 700;
color: var(--text-muted);
letter-spacing: 0.03em;
}
.nav a {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
margin: 1px 0;
border-radius: 8px;
color: var(--text-muted);
text-decoration: none;
font-size: 13px;
font-weight: 500;
}
.nav a::before {
content: '';
width: 16px;
height: 16px;
border-radius: 4px;
background: var(--row-alt);
flex-shrink: 0;
}
.nav a:hover {
background: var(--row-alt);
color: var(--text);
}
.nav a.active {
background: var(--primary-bg);
color: var(--primary-dark);
font-weight: 600;
}
.nav a.active::before {
background: var(--primary);
}
.main-col {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
}
.topbar {
height: 56px;
padding: 0 24px;
display: flex;
align-items: center;
justify-content: space-between;
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.crumb {
font-size: 13px;
color: var(--text-muted);
}
.crumb b {
color: var(--text);
font-weight: 600;
}
.topbar-right {
display: flex;
align-items: center;
gap: 12px;
font-size: 13px;
color: var(--text-muted);
}
.avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--primary-bg);
border: 1px solid var(--border);
color: var(--primary-dark);
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
}
.work-tabs {
display: flex;
align-items: flex-end;
gap: 4px;
padding: 10px 24px 0;
background: var(--bg-page);
border-bottom: 1px solid var(--border);
}
.work-tab {
padding: 8px 14px;
border: 1px solid var(--border);
border-bottom: none;
border-radius: 8px 8px 0 0;
background: var(--surface);
font-size: 13px;
font-weight: 600;
color: var(--text-muted);
margin-bottom: -1px;
}
.work-tab.is-active {
color: var(--primary-dark);
box-shadow: inset 0 2px 0 var(--primary);
z-index: 1;
}
.content {
flex: 1;
padding: 24px;
overflow: auto;
}
.panel {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius);
box-shadow: var(--shadow);
}
.panel-top {
padding: 16px 20px 0;
}
.title-bar-heading {
margin: 0 0 4px;
font-size: 16px;
font-weight: 600;
color: var(--text);
position: relative;
padding-left: 12px;
}
.title-bar-heading::before {
content: '';
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 16px;
border-radius: 2px;
background: var(--cta, var(--primary));
}
.entity-switch {
display: flex;
justify-content: center;
flex-wrap: wrap;
gap: 10px;
padding: 12px 16px 12px;
}
.entity-card {
flex: 0 1 168px;
min-width: 152px;
max-width: 180px;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
display: flex;
gap: 8px;
align-items: center;
cursor: default;
}
.entity-card.is-active {
border-color: var(--primary);
background: var(--primary-bg);
box-shadow: 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);
}
.entity-card__icon {
width: 32px;
height: 32px;
border-radius: 8px;
background: #f1f5f9;
color: #64748b;
display: flex;
align-items: center;
justify-content: center;
font-size: 15px;
flex-shrink: 0;
}
.entity-card.is-active .entity-card__icon {
background: #fff;
color: var(--primary-dark);
}
.entity-card__title {
font-size: 13px;
font-weight: 600;
color: var(--text);
}
.entity-card.is-active .entity-card__title {
color: var(--primary-dark);
}
.entity-card__desc {
font-size: 11px;
color: var(--text-muted);
line-height: 1.35;
}
.filter-block {
padding: 16px 20px 4px;
border-bottom: 1px solid var(--border);
}
.filter-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px 16px;
}
@media (max-width: 1100px) {
.filter-grid {
grid-template-columns: repeat(2, 1fr);
}
}
.field label {
display: block;
font-size: 11px;
font-weight: 500;
color: var(--text-muted);
margin-bottom: 6px;
}
.input,
.select {
height: 36px;
width: 100%;
padding: 0 12px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
font-size: 14px;
color: var(--text);
font-family: inherit;
}
.input:focus,
.select:focus {
outline: none;
border-color: var(--cta, var(--primary));
box-shadow: 0 0 0 2px color-mix(in srgb, var(--cta, var(--primary)) 20%, transparent);
}
.filter-actions {
display: flex;
gap: 8px;
padding: 12px 0 16px;
}
.list-toolbar {
padding: 12px 20px;
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid var(--border);
background: var(--table-head);
}
.sel-num {
font-size: 13px;
color: var(--text-muted);
margin-right: 4px;
}
.sel-num b {
color: var(--cta-dark, var(--primary-dark));
}
.btn {
height: 36px;
padding: 0 14px;
border-radius: 8px;
font-size: 14px;
font-weight: 600;
cursor: default;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-family: inherit;
display: inline-flex;
align-items: center;
gap: 6px;
}
.btn-primary {
background: var(--cta, var(--primary));
border-color: var(--cta, var(--primary));
color: #fff;
}
.btn-primary:hover {
background: var(--cta-dark, var(--primary-dark));
border-color: var(--cta-dark, var(--primary-dark));
}
.btn-op {
height: 28px;
padding: 0 10px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
margin-right: 4px;
}
.btn-op.primary {
color: var(--cta-dark, var(--primary-dark));
border-color: color-mix(in srgb, var(--cta, var(--primary)) 35%, var(--border));
background: var(--primary-bg);
}
.list-body {
overflow-x: auto;
}
table {
width: 100%;
border-collapse: collapse;
min-width: 900px;
}
th {
text-align: left;
padding: 10px 14px;
font-size: 12px;
font-weight: 600;
color: var(--text-muted);
background: var(--table-head);
border-bottom: 1px solid var(--border);
white-space: nowrap;
}
td {
padding: 11px 14px;
border-bottom: 1px solid var(--border);
font-size: 13px;
}
tr:hover td {
background: var(--row-hover);
}
tr:nth-child(even) td {
background: var(--row-alt);
}
tr:nth-child(even):hover td {
background: var(--row-hover);
}
.tag {
display: inline-block;
padding: 2px 8px;
border-radius: 6px;
font-size: 12px;
font-weight: 600;
}
.tag-info {
background: #f8fafc;
color: #64748b;
}
.tag-success {
background: #d1fae5;
color: #047857;
}
.tag-warning {
background: #fffbeb;
color: #d97706;
}
.tag-danger {
background: #fef2f2;
color: #dc2626;
}
.tag-primary {
background: var(--primary-bg);
color: var(--primary-dark);
}
.pager {
padding: 12px 20px;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 8px;
border-top: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
.pager-btn {
min-width: 32px;
height: 32px;
padding: 0 8px;
border-radius: 8px;
border: 1px solid var(--border);
background: var(--surface);
color: var(--text);
font-size: 13px;
font-weight: 500;
}
.pager-btn.is-active {
background: var(--cta, var(--primary));
border-color: var(--cta, var(--primary));
color: #fff;
}
.demo-bottom {
display: grid;
grid-template-columns: 1fr 380px;
gap: 20px;
margin-top: 20px;
}
@media (max-width: 1200px) {
.demo-bottom {
grid-template-columns: 1fr;
}
}
.stats-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
}
.stat-card {
padding: 14px 16px;
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
}
.stat-card .label {
font-size: 12px;
color: var(--text-muted);
}
.stat-card .value {
margin-top: 4px;
font-size: 22px;
font-weight: 700;
color: var(--cta-dark, var(--primary-dark));
}
.stat-card.warn .value {
color: #d97706;
}
.dialog-preview {
border: 1px solid var(--border);
border-radius: 10px;
background: var(--surface);
box-shadow: 0 8px 24px rgba(15, 23, 42, 0.12);
overflow: hidden;
}
.dialog-head {
padding: 14px 18px;
border-bottom: 1px solid var(--border);
font-size: 15px;
font-weight: 600;
}
.dialog-body {
padding: 16px 18px;
max-height: 280px;
overflow: auto;
}
.form-grid-2 {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
}
.dialog-foot {
padding: 12px 18px;
border-top: 1px solid var(--border);
display: flex;
justify-content: flex-end;
gap: 8px;
background: var(--table-head);
}
.theme-note {
margin-top: 16px;
padding: 12px 16px;
border-radius: 8px;
background: var(--primary-bg);
border: 1px solid var(--border);
font-size: 13px;
color: var(--text-muted);
}
+418
View File
@@ -0,0 +1,418 @@
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const themes = [
{
id: '00',
file: '00-fresh-mint-clash.html',
title: '00 · 现行薄荷绿(Logo 同色)',
desc: '主色 #10b981 与 Logo 同为绿色 · 层次易糊',
note: '对比基准:Logo 绿 + UI 绿叠在一起,是当前觉得「不好看」的典型情况。',
primary: '#10b981',
dark: '#059669',
bg: '#ecfdf5',
border: '#d9e8e2',
swatches: ['#10b981', '#059669', '#ecfdf5', '#d9e8e2'],
recommended: false
},
{
id: '01',
file: '01-slate-blue.html',
title: '01 · 深海蓝(推荐)',
desc: '主色 #2563eb · Logo 绿 + UI 蓝,专业医疗后台',
note: '推荐首选:与绿色 Logo 互补,成功/进行中仍用绿色 Tag,操作引导清晰。',
primary: '#2563eb',
dark: '#1d4ed8',
bg: '#eff6ff',
border: '#e2e8f0',
swatches: ['#2563eb', '#1d4ed8', '#eff6ff', '#e2e8f0'],
recommended: true
},
{
id: '02',
file: '02-bio-teal.html',
title: '02 · 生物青绿',
desc: '主色 #0d9488 · 偏蓝的 Teal,保留生命感',
note: '折中方案:比薄荷绿沉、比纯蓝更有生物气质;注意与成功 Tag 绿色区分。',
primary: '#0d9488',
dark: '#0f766e',
bg: '#f0fdfa',
border: '#cce7e4',
swatches: ['#0d9488', '#0f766e', '#f0fdfa', '#cce7e4'],
recommended: false
},
{
id: '03',
file: '03-graphite-blue.html',
title: '03 · 石墨灰 + 蓝色按钮',
desc: '导航 Slate #475569 · 主按钮 #0369a1',
note: '最克制:界面几乎无彩色,Logo 绿最突出;主按钮单独用蓝色强调。',
primary: '#475569',
dark: '#334155',
bg: '#f8fafc',
border: '#e2e8f0',
cta: '#0369a1',
ctaDark: '#0284c7',
swatches: ['#475569', '#0369a1', '#f8fafc', '#e2e8f0'],
recommended: false
},
{
id: '04',
file: '04-indigo-tech.html',
title: '04 · 靛蓝科技',
desc: '主色 #4f46e5 · 偏生物科技平台气质',
note: '辨识度高、略活泼;适合强调数字化,医疗场景需控制 Tag 饱和度。',
primary: '#4f46e5',
dark: '#4338ca',
bg: '#eef2ff',
border: '#c7d2fe',
swatches: ['#4f46e5', '#4338ca', '#eef2ff', '#c7d2fe'],
recommended: false
}
]
function themeJump(currentId) {
return themes
.map((t) => {
const cls = t.id === currentId ? 'is-current' : ''
return `<a class="${cls}" href="${t.file}">${t.id}</a>`
})
.join('')
}
function swatchesHtml(theme) {
const labels = theme.cta
? ['导航', '按钮', '浅底', '边']
: ['主色', '深', '浅底', '边']
return theme.swatches
.map((c, i) => `<span class="swatch"><i style="background:${c}"></i>${labels[i]}</span>`)
.join('')
}
function rootVars(theme) {
const lines = [
` --primary: ${theme.primary};`,
` --primary-dark: ${theme.dark};`,
` --primary-bg: ${theme.bg};`,
` --text: #1e293b;`,
` --text-muted: #64748b;`,
` --border: ${theme.border};`,
` --bg-page: #fefefe;`,
` --surface: #ffffff;`,
` --table-head: #f8fafc;`,
` --row-alt: #fafafa;`,
` --row-hover: #f1f5f9;`,
` --shadow: 0 1px 3px rgba(0, 0, 0, 0.05);`,
` --radius: 10px;`,
` --brand-green: #10b981;`,
` --brand-green-dark: #059669;`
]
if (theme.cta) {
lines.push(` --cta: ${theme.cta};`, ` --cta-dark: ${theme.ctaDark};`)
}
return lines.join('\n')
}
function renderPage(theme) {
const badge = theme.recommended
? '<span class="demo-badge">推荐</span>'
: theme.id === '00'
? '<span class="demo-badge demo-badge--warn">现状</span>'
: ''
return `<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>${theme.title} · 管理端界面 Demo</title>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />
<style>
:root {
${rootVars(theme)}
}
</style>
<link rel="stylesheet" href="_demo-styles.css" />
</head>
<body>
<div class="demo-banner">
<div>
<h1>${badge}${theme.title}</h1>
<p>${theme.desc}</p>
</div>
<div class="demo-banner__actions">
<div class="swatch-row">${swatchesHtml(theme)}</div>
<div class="theme-jump">${themeJump(theme.id)}</div>
<a class="link-back" href="index.html">选型入口</a>
</div>
</div>
<div class="app-layout">
<aside class="sidebar">
<div class="brand">
<img class="brand-logo" src="../../web-admin/public/logo.png" alt="中科兴皖" width="36" height="36" />
<div class="brand-text">中科兴皖<small>一体化门户</small></div>
</div>
<div class="nav">
<div class="nav-group">
<div class="nav-group-title">市场运营</div>
<a href="#">工作台</a>
<a href="#" class="active">采集协议单</a>
<a href="#">样本接收</a>
<a href="#">缴费确认</a>
</div>
<div class="nav-group">
<div class="nav-group-title">质量管理</div>
<a href="#">质检工单</a>
<a href="#">环境检测</a>
</div>
<div class="nav-group">
<div class="nav-group-title">系统</div>
<a href="#">用户管理</a>
<a href="#">角色权限</a>
</div>
</div>
</aside>
<div class="main-col">
<header class="topbar">
<div class="crumb">市场运营 / <b>采集协议单</b></div>
<div class="topbar-right">
<span>管理员</span>
<div class="avatar">管</div>
</div>
</header>
<div class="work-tabs">
<div class="work-tab">工作台</div>
<div class="work-tab is-active">采集协议单</div>
<div class="work-tab">样本接收</div>
</div>
<div class="content">
<section class="panel">
<div class="panel-top">
<h2 class="title-bar-heading">采集协议单</h2>
</div>
<div class="entity-switch">
<div class="entity-card is-active">
<div class="entity-card__icon">📄</div>
<div>
<div class="entity-card__title">协议单管理</div>
<div class="entity-card__desc">协议审核与状态维护</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">💰</div>
<div>
<div class="entity-card__title">缴费信息</div>
<div class="entity-card__desc">缴费计划与到账</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">🏅</div>
<div>
<div class="entity-card__title">储存证管理</div>
<div class="entity-card__desc">储存证开具管理</div>
</div>
</div>
<div class="entity-card">
<div class="entity-card__icon">📅</div>
<div>
<div class="entity-card__title">满月待办</div>
<div class="entity-card__desc">满月事项跟进</div>
</div>
</div>
</div>
<div class="filter-block">
<div class="filter-grid">
<div class="field">
<label>关键词</label>
<input class="input" type="text" placeholder="协议编号 / 客户姓名 / 手机号" />
</div>
<div class="field">
<label>协议状态</label>
<select class="select"><option>全部</option><option>生效中</option><option>待生效</option></select>
</div>
<div class="field">
<label>预产期起</label>
<input class="input" type="date" />
</div>
<div class="field">
<label>预产期止</label>
<input class="input" type="date" />
</div>
</div>
<div class="filter-actions">
<button type="button" class="btn btn-primary">查询</button>
<button type="button" class="btn">重置</button>
</div>
</div>
<div class="list-toolbar">
<span class="sel-num">已选 <b>2</b> 项</span>
<button type="button" class="btn btn-primary">新增协议</button>
<button type="button" class="btn">批量审核</button>
<button type="button" class="btn">导出</button>
</div>
<div class="list-body">
<table>
<thead>
<tr>
<th><input type="checkbox" checked /></th>
<th>序号</th>
<th>状态</th>
<th>协议编号</th>
<th>客户姓名</th>
<th>手机号</th>
<th>预产期</th>
<th>缴费状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" checked /></td>
<td>1</td>
<td><span class="tag tag-primary">生效中</span></td>
<td>XY-2026-0042</td>
<td>张女士</td>
<td>138****6621</td>
<td>2026-08-12</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-03-01 10:22</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">审核</button>
</td>
</tr>
<tr>
<td><input type="checkbox" checked /></td>
<td>2</td>
<td><span class="tag tag-info">待生效</span></td>
<td>XY-2026-0038</td>
<td>李先生</td>
<td>139****8890</td>
<td>2026-07-20</td>
<td><span class="tag tag-warning">缴费确认中</span></td>
<td>2026-02-28 15:06</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">编辑</button>
<button class="btn-op">生效</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>3</td>
<td><span class="tag tag-warning">已过期</span></td>
<td>XY-2025-1201</td>
<td>王女士</td>
<td>136****3345</td>
<td>2025-12-08</td>
<td><span class="tag tag-success">已缴费</span></td>
<td>2026-02-28 09:18</td>
<td>
<button class="btn-op primary">查看</button>
<button class="btn-op">续签</button>
</td>
</tr>
<tr>
<td><input type="checkbox" /></td>
<td>4</td>
<td><span class="tag tag-danger">已作废</span></td>
<td>XY-2025-0899</td>
<td>赵先生</td>
<td>137****2210</td>
<td>2025-10-15</td>
<td><span class="tag tag-info">待缴费</span></td>
<td>2025-09-20 14:40</td>
<td>
<button class="btn-op primary">查看</button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="pager">
<span>共 128 条</span>
<button class="pager-btn">‹</button>
<button class="pager-btn is-active">1</button>
<button class="pager-btn">2</button>
<button class="pager-btn">3</button>
<button class="pager-btn">›</button>
<span>10 条/页</span>
</div>
</section>
<div class="demo-bottom">
<div>
<div class="stats-row">
<div class="stat-card">
<div class="label">本月新增协议</div>
<div class="value">42</div>
</div>
<div class="stat-card">
<div class="label">生效中</div>
<div class="value">86</div>
</div>
<div class="stat-card warn">
<div class="label">待缴费</div>
<div class="value">12</div>
</div>
</div>
<p class="theme-note">${theme.note}</p>
</div>
<div class="dialog-preview">
<div class="dialog-head">查看协议 · XY-2026-0042</div>
<div class="dialog-body">
<div class="form-grid-2">
<div class="field">
<label>协议状态</label>
<div><span class="tag tag-primary">生效中</span></div>
</div>
<div class="field">
<label>缴费状态</label>
<div><span class="tag tag-success">已缴费</span></div>
</div>
<div class="field">
<label>客户姓名</label>
<input class="input" value="张女士" readonly />
</div>
<div class="field">
<label>手机号</label>
<input class="input" value="138****6621" readonly />
</div>
<div class="field" style="grid-column: 1 / -1">
<label>备注</label>
<input class="input" value="—" readonly />
</div>
</div>
</div>
<div class="dialog-foot">
<button class="btn">关闭</button>
<button class="btn btn-primary">确定</button>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>`
}
for (const theme of themes) {
fs.writeFileSync(path.join(__dirname, theme.file), renderPage(theme))
console.log('written', theme.file)
}
Loaded 100 of 274 files, more files were not shown because too many files have changed in this diff. Show more