feat(i18n): migrate EMR, surgery safety, surgical schedule, surgery manage, operating room, preop manage to vue-i18n (~1000 keys)

This commit is contained in:
2026-06-25 00:22:45 +08:00
parent 24ea1c9e1a
commit 92079e1392
15 changed files with 3571 additions and 1045 deletions

View File

@@ -1364,7 +1364,14 @@
"exportDev": "Export feature in development",
"collectSuccess": "Collected {count} indicators",
"collectFailed": "Collection failed",
"monthLabels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
"monthLabels": [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun"
]
},
"execution": {
"title": "Inpatient Nurse Execution",
@@ -1569,5 +1576,811 @@
"rollFee": "Roll Fee Config",
"medicineReturn": "Medicine Return"
}
},
"surgicalschedule": {
"operCode": "Surgery Order No.",
"placeholderOperCode": "Enter surgery order no.",
"scheduleDate": "Schedule Date",
"rangeSeparator": "to",
"startDate": "Start Date",
"endDate": "End Date",
"orgName": "Organization",
"placeholderOrg": "Select organization",
"applyDept": "Apply Department",
"placeholderDept": "Select department",
"patientNameOrPinyin": "Name/Pinyin",
"placeholderNameOrPinyin": "Enter name or pinyin",
"search": "Search",
"reset": "Reset",
"add": "New Surgery Schedule",
"billing": "Billing",
"medicalAdvice": "Orders",
"export": "Export",
"patientName": "Name",
"identifierNo": "Card No.",
"operName": "Surgery Name",
"surgeryType": "Surgery Type",
"surgeryNature": "Surgery Nature",
"surgeonName": "Surgeon",
"anesMethod": "Anesthesia Method",
"operator": "Operator",
"actions": "Actions",
"view": "View",
"edit": "Edit",
"cancel": "Cancel",
"find": "Find",
"refresh": "Refresh",
"back": "Back",
"save": "Save",
"patientBasicInfo": "Patient Basic Info",
"patientId": "Patient ID",
"gender": "Gender",
"male": "Male",
"female": "Female",
"unknown": "Unknown",
"age": "Age",
"patientWeight": "Weight",
"placeholderWeight": "Enter weight (kg)",
"patientHeight": "Height",
"placeholderHeight": "Enter height (cm)",
"surgeryApplyInfo": "Surgery Application Info",
"feeType": "Fee Type",
"applyTime": "Apply Time",
"applyDoctor": "Apply Doctor",
"placeholderSurgeryType": "Select surgery type",
"surgerySchedule": "Surgery Schedule",
"placeholderScheduleDate": "Select schedule date",
"sequenceNo": "Sequence No.",
"placeholderSequenceNo": "Enter sequence no.",
"roomCode": "Room Code",
"placeholderRoomCode": "Select room code",
"tableNo": "Table No.",
"placeholderTableNo": "Enter table no.",
"isFirstSurgery": "First Surgery",
"yes": "Yes",
"no": "No",
"natureAndSite": "Nature and Site",
"placeholderSurgeryNature": "Select surgery nature",
"surgerySite": "Surgery Site",
"placeholderSurgerySite": "Select surgery site",
"allergyMedication": "Allergy Medication",
"allergyRemark": "Allergy Remark",
"placeholderAllergyRemark": "Enter allergy remark",
"medicalStaff": "Medical Staff",
"assistant1": "Assistant 1",
"placeholderAssistant1": "Select assistant 1",
"assistant2": "Assistant 2",
"placeholderAssistant2": "Select assistant 2",
"assistant3": "Assistant 3",
"placeholderAssistant3": "Select assistant 3",
"scrubNurse": "Scrub Nurse",
"placeholderScrubNurse": "Select scrub nurse",
"instrumentNurse1": "Instrument Nurse 1",
"placeholderInstrumentNurse1": "Select instrument nurse 1",
"instrumentNurse2": "Instrument Nurse 2",
"placeholderInstrumentNurse2": "Select instrument nurse 2",
"circulatingNurse1": "Circulating Nurse 1",
"placeholderCirculatingNurse1": "Select circulating nurse 1",
"placeholderAnesMethod": "Select anesthesia method",
"circulatingNurse2": "Circulating Nurse 2",
"placeholderCirculatingNurse2": "Select circulating nurse 2",
"externalExpert": "External Expert",
"externalExpertName": "External Expert Name",
"placeholderExternalExpertName": "Enter external expert name",
"anesDoctor1": "Anesthesia Doctor 1",
"placeholderAnesDoctor1": "Select anesthesia doctor 1",
"anesDoctor2": "Anesthesia Doctor 2",
"placeholderAnesDoctor2": "Select anesthesia doctor 2",
"anesDoctor3": "Anesthesia Doctor 3",
"placeholderAnesDoctor3": "Select anesthesia doctor 3",
"preDiagnosis": "Preoperative Diagnosis",
"placeholderPreDiagnosis": "Enter preoperative diagnosis",
"postDiagnosis": "Postoperative Diagnosis",
"placeholderPostDiagnosis": "Enter postoperative diagnosis",
"surgeryProcess": "Surgery Process",
"admissionTime": "Admission Time",
"placeholderAdmissionTime": "Select admission time",
"entryTime": "Entry Time",
"placeholderEntryTime": "Select entry time",
"anesStartTime": "Anesthesia Start",
"placeholderAnesStartTime": "Select anesthesia start time",
"startTime": "Incision Time",
"placeholderStartTime": "Select incision time",
"endTime": "Surgery End",
"placeholderEndTime": "Select surgery end time",
"anesEndTime": "Anesthesia End",
"placeholderAnesEndTime": "Select anesthesia end time",
"incisionType": "Incision Type",
"placeholderIncisionType": "Select incision type",
"infectionDiagnosis": "Infection Diagnosis",
"placeholderInfectionDiagnosis": "Enter infection diagnosis",
"isolationType": "Isolation Type",
"placeholderIsolationType": "Enter isolation type",
"implantFlag": "Implant Flag",
"implantSerial": "Implant Serial/Batch",
"placeholderImplantSerial": "Enter implant serial/batch",
"bloodLoss": "Blood Loss",
"placeholderBloodLoss": "Enter blood loss",
"bloodTrans": "Blood Transfusion",
"placeholderBloodTrans": "Enter blood transfusion",
"remarkInfo": "Remark Info",
"communicationInfo": "Communication Info",
"placeholderCommunicationInfo": "Enter communication info",
"remark": "Remark",
"placeholderRemark": "Enter remark",
"applyQuery": "Surgery Application Query",
"applyTimeRange": "Apply Time Range",
"placeholderSurgeon": "Select surgeon",
"confirm": "Confirm",
"patientInfo": "Patient Info:",
"billingAccount": "Billing Account",
"loadingAdvice": "Loading order data, please wait...",
"surgeryLevel": "Surgery Level",
"anesthesiaType": "Anesthesia Type",
"exportFilename": "surgery_schedule.csv",
"addSchedule": "New Surgery Schedule",
"editTitle": "Edit Surgery Schedule",
"viewTitle": "View Surgery Schedule",
"temporaryMedicalTitle": "Outpatient Intraoperative Temporary Orders",
"insurance": "Insurance",
"selfPay": "Self Pay",
"immediate": "Immediate",
"ivInjection": "IV Injection",
"unknownMedicine": "Unknown Medicine",
"msgSelectScheduleDate": "Please select schedule date",
"msgInputSequenceNo": "Please enter sequence no.",
"msgSequenceNoNumber": "Sequence no. must be a number",
"msgSelectRoomCode": "Please select room code",
"msgSelectTableNo": "Please select table no.",
"msgSelectSurgeryNature": "Please select surgery nature",
"msgSelectSurgerySite": "Please select surgery site",
"msgSelectAnesMethod": "Please select anesthesia method",
"msgInputPreDiagnosis": "Please enter preoperative diagnosis",
"msgSelectSurgeon": "Please select surgeon",
"msgGetDetailFailed": "Failed to get surgery schedule detail",
"msgConfirmDelete": "Are you sure to cancel surgery schedule \"{name}\"?",
"msgDeletedSuccess": "Surgery schedule cancelled",
"msgSelectForBilling": "Please select a surgery schedule for billing",
"msgNoVisitForBilling": "This schedule is not linked to an encounter. Please confirm the patient has completed registration.",
"msgGetAccountFailed": "Failed to get account info. Please confirm the encounter has a billing account.",
"msgGetAccountError": "Failed to get account info, please retry.",
"chargeDialogTitle": "Surgery Billing - {name} - {op}",
"msgSelectForAdvice": "Please select a surgery schedule for orders",
"msgNoVisitForAdvice": "This schedule is not linked to an encounter. Please confirm the patient has completed registration.",
"msgRefreshFailed": "Failed to refresh data, please retry",
"msgAdviceGenerated": "Temporary orders generated (signed)",
"msgAdviceDeleted": "Order deleted, moved back to pending list",
"msgPatientInfoIncomplete": "Patient info incomplete, please close and reopen",
"msgTooManyAdvices": "Too many pending orders ({count}), showing first {max}",
"msgQuoteSuccess": "Successfully quoted latest billing medicines!",
"msgGetChargeFailed": "Failed to get billing data, please retry",
"msgAddSuccess": "Added successfully",
"msgAddFailed": "Failed to add surgery schedule, please check form",
"msgEditSuccess": "Updated successfully",
"msgUpdateFailed": "Failed to update surgery schedule, please check form",
"msgValidateFailed": "Please check form, red fields are required",
"msgGetApplyListFailed": "Failed to get surgery application list, please retry",
"msgSelectApplyRecord": "Please select a surgery application record",
"msgExportConfirm": "Export surgery schedule list with current filters?",
"tmp": {
"title": "Outpatient Intraoperative Temporary Orders",
"patientLabel": "Patient: ",
"cardNoLabel": "Card No.: ",
"operCodeLabel": "Surgery Order No.: ",
"deptLabel": "Department: ",
"doctorLabel": "Doctor: ",
"roleLabel": "Role: ",
"refresh": "Refresh",
"quoteBilling": "Quote Billing",
"sectionBillingTitle": "1. Quoted Billing Medicines (Pending Orders)",
"collapse": "Collapse",
"expandAll": "Expand All",
"items": " items",
"colSeq": "No.",
"colMedicineName": "Medicine Name",
"colSpec": "Specification",
"colQuantity": "Quantity",
"colBatchNo": "Batch No.",
"colUnitPrice": "Unit Price",
"colSubtotal": "Subtotal",
"colInsurance": "Insurance",
"insuranceIn": "Insurance Covered",
"selfPay": "Self Pay",
"total": "Total",
"sectionAdviceTitle": "2. Temporary Orders Preview (Generated)",
"colAdviceName": "Order Name",
"colDosage": "Dosage",
"colUnit": "Unit",
"colUsage": "Usage",
"colFrequency": "Frequency",
"immediate": "Immediate",
"colExecuteTime": "Execute Time",
"colAction": "Action",
"edit": "Edit",
"delete": "Delete",
"sectionSignatureTitle": "3. Doctor Electronic Signature",
"signDoctorLabel": "Signing Doctor: ",
"signTimeLabel": "Signing Time: ",
"unsigned": "Unsigned",
"cancel": "Cancel",
"alreadySigned": "Already Signed",
"signAndGenerate": "Sign and Generate Orders",
"signDialogTitle": "Signature Password",
"enterAccountPassword": "Please enter your account password:",
"placeholderPassword": "Enter password",
"confirm": "Confirm",
"editDialogTitle": "Edit Order",
"placeholderDosage": "Enter dosage",
"placeholderUnit": "Enter unit",
"placeholderSelectUsage": "Select usage",
"loading": "Loading...",
"save": "Save",
"tip": "Tip",
"unknownUser": "Unknown User",
"usageIv": "IV Injection",
"usagePo": "Oral",
"usageIm": "Intramuscular",
"usageSc": "Subcutaneous",
"usageIvgtt": "IV Drip",
"usageIh": "Inhalation",
"usageIt": "Sublingual",
"usageIp": "Intraperitoneal",
"usageTop": "Topical",
"usagePr": "Rectal",
"msgFillDosage": "Please enter dosage",
"msgDosageMustBeNumber": "Dosage must be a number",
"msgFillUsage": "Please enter usage",
"msgEditSaved": "Order modification saved to server",
"msgSaveFailedRetry": "Save failed, please retry",
"msgEnterPassword": "Please enter password",
"msgSignSuccess": "Signature successful",
"msgConfirmRollback": "Are you sure to rollback this order?",
"msgRollbackSuccess": "Rollback successful",
"msgRollbackFailedRetry": "Rollback failed, please retry",
"msgSignFirst": "Please sign electronically first",
"msgSubmitting": "Submitting orders, please wait...",
"msgNoAdviceData": "No order data to save",
"msgSaveSuccess": "Temporary orders saved successfully",
"msgSaveFailed": "Failed to save orders: ",
"unknownError": "Unknown error"
},
"msgGetScheduleListFailed": "Failed to get surgery schedule list, please try again later",
"msgTooManyDrafts": "Too many pending advices ({count}), only showing first {max}",
"placeholderSurgeryRemark": "Enter surgery remark",
"scheduleTime": "Schedule Time",
"surgeryNameLabel": "Surgery Name",
"surgeryRemark": "Surgery Remark"
},
"surgerymanage": {
"surgeryNo": "Surgery No.",
"surgeryName": "Surgery Name",
"patientName": "Patient Name",
"surgeryStatus": "Surgery Status",
"surgeryType": "Surgery Type",
"plannedTime": "Planned Time",
"rangeSeparator": "to",
"startDate": "Start Date",
"endDate": "End Date",
"search": "Search",
"reset": "Reset",
"addSurgery": "New Surgery",
"refresh": "Refresh",
"applyDate": "Apply Date",
"surgeryOrderNo": "Surgery Order No.",
"applyDoctor": "Apply Doctor",
"applyDept": "Apply Department",
"surgeryLevel": "Surgery Level",
"emergency": "Emergency",
"yes": "Yes",
"no": "No",
"implantMaterial": "Implant Material",
"mainSurgeon": "Main Surgeon",
"anesthetist": "Anesthetist",
"anesthesiaType": "Anesthesia Type",
"bodySite": "Body Site",
"operatingRoom": "Operating Room",
"operatingRoomDept": "OR Department",
"execDept": "Exec Department",
"status": "Status",
"actions": "Actions",
"view": "View",
"edit": "Edit",
"cancel": "Cancel",
"schedule": "Schedule",
"start": "Start",
"complete": "Complete",
"currentStatus": "Current Status",
"viewModeTip": "View mode: all fields are read-only",
"patient": "Patient",
"placeholderPatient": "Select patient",
"noIdCard": "No ID",
"editModePatientTip": "Patient info cannot be changed in edit mode",
"encounterNo": "Encounter No.",
"placeholderEncounterNo": "Select encounter",
"originalEncounter": "Original encounter",
"none": "None",
"placeholderAutoDoctor": "Auto-detected from current login",
"placeholderAutoDept": "Auto-detected from doctor's department",
"surgeryCode": "Surgery Code",
"placeholderSurgeryCode": "Enter surgery code",
"plannedSurgeryTime": "Planned Surgery Time",
"placeholderDateTime": "Select date and time",
"placeholderBodySite": "Select body site",
"surgeryTeam": "Surgery Team",
"placeholderMainSurgeon": "Select main surgeon",
"placeholderAnesthetist": "Select anesthetist",
"assistant1": "Assistant 1",
"placeholderAssistant1": "Select assistant 1",
"assistant2": "Assistant 2",
"placeholderAssistant2": "Select assistant 2",
"scrubNurse": "Scrub Nurse",
"placeholderScrubNurse": "Select scrub nurse",
"placeholderAnesthesiaType": "Select anesthesia type",
"placeholderOperatingRoom": "Select operating room",
"placeholderExecDept": "Select exec department",
"diagnosisInfo": "Diagnosis Info",
"preoperativeDiagnosis": "Preoperative Diagnosis",
"placeholderPreoperativeDiagnosis": "Enter preoperative diagnosis",
"postoperativeDiagnosis": "Postoperative Diagnosis",
"placeholderPostoperativeDiagnosis": "Enter postoperative diagnosis",
"surgeryDescription": "Surgery Description",
"placeholderSurgeryDescription": "Enter surgery description",
"postoperativeAdvice": "Postoperative Advice",
"placeholderPostoperativeAdvice": "Enter postoperative advice",
"surgeryFee": "Surgery Fee",
"anesthesiaFee": "Anesthesia Fee",
"totalFee": "Total Fee",
"incisionLevel": "Incision Level",
"placeholderIncisionLevel": "Select incision level",
"healingLevel": "Healing Level",
"placeholderHealingLevel": "Select healing level",
"complications": "Complications",
"placeholderComplications": "Enter complications",
"emergencyFlag": "Emergency Flag",
"implantFlag": "Implant Flag",
"operatingRoomConfirmUser": "OR Confirmer",
"placeholderOperatingRoomConfirmUser": "OR confirmer",
"operatingRoomConfirmTime": "OR Confirm Time",
"placeholderOperatingRoomConfirmTime": "Select OR confirm time",
"remark": "Remark",
"placeholderRemark": "Enter remark",
"close": "Close",
"confirm": "Confirm",
"placeholderSurgeryNo": "Enter surgery no.",
"placeholderSurgeryName": "Enter surgery name",
"placeholderPatientName": "Enter patient name",
"placeholderSurgeryStatus": "Select surgery status",
"placeholderSurgeryType": "Select surgery type",
"statusPending": "Pending",
"statusScheduled": "Scheduled",
"statusInProgress": "In Progress",
"statusCompleted": "Completed",
"statusCancelled": "Cancelled",
"statusPaused": "Paused",
"healingGradeA": "Grade A Healing",
"healingGradeB": "Grade B Healing",
"healingGradeC": "Grade C Healing",
"encounterRegistered": "Registered",
"encounterInProgress": "In Progress",
"encounterCompleted": "Completed",
"encounterCancelled": "Cancelled",
"unknown": "Unknown",
"valPatientRequired": "Please select a patient",
"valSurgeryNameRequired": "Please enter surgery name",
"valSurgeryTypeRequired": "Please select surgery type",
"valSurgeryLevelRequired": "Please select surgery level",
"valPlannedTimeRequired": "Please select planned surgery time",
"valMainSurgeonRequired": "Please select main surgeon",
"valAnesthesiaTypeRequired": "Please select anesthesia type",
"valBodySiteRequired": "Please enter body site",
"addSurgeryTitle": "New Surgery",
"editSurgeryTitle": "Edit Surgery",
"viewSurgeryTitle": "View Surgery",
"errorGetSurgeryList": "Failed to get surgery list, please retry",
"errorGetPatientList": "Failed to get patient list",
"warningNoEncounter": "No encounter records, please register first",
"errorGetEncounterList": "Failed to get encounter list",
"errorGetDoctorList": "Failed to get doctor list",
"errorGetOperatingRoomList": "Failed to get operating room list",
"errorGetNurseList": "Failed to get nurse list",
"errorGetOrgList": "Failed to get department list",
"warningEditNotAllowed": "Current status does not allow editing",
"errorGetSurgeryInfo": "Failed to get surgery info",
"infoViewModeNoSubmit": "View mode, cannot submit",
"successAdd": "Added successfully",
"errorAddSurgery": "Failed to add surgery, please check form",
"successUpdate": "Updated successfully",
"errorUpdateSurgery": "Failed to update surgery, please check form",
"errorFormValidation": "Please check form, red fields are required",
"confirmDelete": "Are you sure to delete surgery \"{name}\"?",
"successDelete": "Deleted successfully",
"errorDelete": "Delete failed",
"confirmCancel": "Are you sure to cancel surgery \"{name}\"?",
"successCancelled": "Surgery cancelled",
"errorCancel": "Cancel failed",
"warningCancelNotAllowed": "Current status does not allow cancellation",
"warningSelectOperatingRoom": "Please select operating room first",
"warningSetPlannedTime": "Please set planned surgery time first",
"confirmSchedule": "Are you sure to schedule surgery \"{name}\"?",
"successScheduled": "Surgery scheduled",
"errorSchedule": "Schedule failed",
"confirmStart": "Are you sure to start surgery \"{name}\"?",
"successStarted": "Surgery started",
"errorStart": "Failed to start surgery",
"confirmComplete": "Are you sure to complete surgery \"{name}\"?",
"successCompleted": "Surgery completed",
"errorComplete": "Failed to complete surgery",
"infoSelectEncounter": "Please select an encounter",
"sun": "Sun",
"mon": "Mon",
"tue": "Tue",
"wed": "Wed",
"thu": "Thu",
"fri": "Fri",
"sat": "Sat"
},
"emr": {
"timeliness": {
"stats": { "pending": "Pending", "completed": "Completed", "overdue": "Overdue", "rate": "Completion Rate" },
"department": "Department",
"emrTypeLabel": "EMR Type",
"statusLabel": "Status",
"all": "All",
"search": "Search",
"reset": "Reset",
"doctor": "Doctor",
"requiredHours": "Required Hours(h)",
"deadline": "Deadline",
"actualCompleteTime": "Actual Complete Time",
"emrType": { "admission": "Admission Record", "firstCourse": "First Course", "dailyCourse": "Daily Course", "discharge": "Discharge Record" },
"status": { "pending": "Pending", "completed": "Completed", "overdue": "Overdue" }
},
"sync": {
"title": "EMR Data Sync",
"stats": "Sync Statistics",
"emrCount": "EMR Count",
"revisionCount": "Revision History",
"searchIndexCount": "Search Index",
"operations": "Data Sync Operations",
"alertMessage": "Sync will clear existing revision history and search index, then regenerate from EMR table.",
"syncing": "Syncing...",
"startSync": "Start Sync",
"refreshStats": "Refresh Statistics",
"confirmMessage": "Sync EMR data? This will clear existing revision history and search index, then regenerate.",
"confirmTitle": "Confirm Sync",
"syncComplete": "Sync Complete",
"syncFailed": "Sync Failed",
"unknownError": "Unknown Error"
},
"archive": {
"title": "EMR Print & Archive",
"syncing": "Syncing...",
"syncHistory": "Sync History Data",
"refreshStats": "Refresh Statistics",
"totalRecords": "Total Records",
"archived": "Archived",
"pendingArchive": "Pending Archive",
"archiveRate24h": "24h Archive Rate",
"patientName": "Patient Name",
"status": "Status",
"printed": "Printed",
"lost": "Lost",
"query": "Query",
"patient": "Patient",
"emrType": "EMR Type",
"title_col": "Title",
"operation": "Operation",
"print": "Print",
"archive": "Archive",
"reprint": "Reprint",
"printBy": "Printed By",
"printCount": "Print Count",
"time": "Time",
"archiver": "Archiver",
"confirmArchive": "Confirm Archive",
"archivedSuccess": "Archived",
"reprintAdded": "Reprint record added",
"syncConfirmMessage": "Will sync data from EMR table to revision history and search index. Continue?",
"syncConfirmTitle": "Confirm Sync",
"syncComplete": "Sync Complete",
"syncFailed": "Sync Failed"
},
"completeness": {
"executeCheck": "Execute Completeness Check",
"emrId": "EMR ID",
"emrIdPlaceholder": "Enter EMR ID",
"encounterId": "Encounter ID",
"encounterIdPlaceholder": "Enter Encounter ID",
"totalItems": "Total Items",
"requiredTotal": "Required Total",
"requiredPassed": "Required Passed",
"isComplete": "Is Complete",
"yes": "Yes",
"no": "No",
"failedItemsAlert": "Failed Items Alert",
"resultDetail": "Check Result Details",
"checkItem": "Check Item",
"category": "Category",
"required": "Required",
"requiredYes": "Required",
"requiredNo": "Optional",
"checkResult": "Result",
"pass": "Pass",
"fail": "Fail",
"detail": "Detail",
"checkTime": "Check Time",
"categoryBasic": "Basic Info",
"categoryExamination": "Examination",
"categoryDiagnosis": "Diagnosis",
"categoryTreatment": "Treatment",
"categorySignature": "Signature",
"enterEmrId": "Please enter EMR ID",
"enterEncounterId": "Please enter Encounter ID",
"checkPassed": "EMR completeness check passed",
"checkFailed": "EMR completeness check failed, there are non-conforming items",
"checkError": "Check execution failed",
"getResultError": "Failed to get check results"
},
"warehouse": {
"extractTitle": "Structured Data Extraction",
"emrId": "EMR ID",
"emrIdPlaceholder": "Enter EMR ID",
"extract": "Extract Data",
"viewTitle": "Structured Data View",
"encounterId": "Encounter ID",
"encounterIdPlaceholder": "Enter Encounter ID",
"query": "Query",
"dataType": "Data Type",
"dataKey": "Data Key",
"dataValue": "Data Value",
"dataUnit": "Unit",
"recordTime": "Record Time",
"qualityScore": "Quality Score",
"calculate": "Calculate Score",
"queryHistory": "Query History",
"totalScore": "Total Score",
"completenessScore": "Completeness",
"timelinessScore": "Timeliness",
"accuracyScore": "Accuracy",
"scoreTime": "Score Time",
"emrType": "EMR Type",
"typeVitalSigns": "Vital Signs",
"typeLabResults": "Lab Results",
"typeDiagnosis": "Diagnosis",
"typeMedication": "Medication",
"enterEmrId": "Please enter EMR ID",
"enterEncounterId": "Please enter Encounter ID",
"extractSuccess": "Extraction complete, {count} records",
"extractFailed": "Extraction failed",
"queryFailed": "Query failed",
"calculateSuccess": "Score calculation complete",
"calculateFailed": "Calculation failed"
},
"revision": {
"title": "EMR Revision History",
"patient": "Patient",
"patientName": "Patient Name",
"doctor": "Doctor",
"doctorName": "Doctor Name",
"operator": "Operator",
"operatorName": "Operator Name",
"emrType": "EMR Type",
"all": "All",
"emrTypeAdmission": "Admission Record",
"emrTypeFirstCourse": "First Course",
"emrTypeDailyCourse": "Daily Course",
"emrTypeDischarge": "Discharge Record",
"search": "Search",
"reset": "Reset",
"emrTitle": "EMR Title",
"emrPrefix": "EMR #",
"attendingDoctor": "Attending Doctor",
"department": "Department",
"encounterNo": "Encounter No.",
"operationType": "Operation Type",
"changeContent": "Change Content",
"time": "Time",
"operation": "Operation",
"detail": "Detail",
"revisionDetail": "Revision Detail",
"version": "Version",
"contentSnapshot": "Content Snapshot",
"opCreate": "Create",
"opEdit": "Edit",
"opApprove": "Approve",
"opSign": "Sign",
"loadFailed": "Load failed"
}
},
"surgery": {
"safety": {
"patient": "Patient",
"patientName": "Patient Name",
"checkPhase": "Check Phase",
"all": "All",
"preOp": "Pre-Op",
"intraOp": "Intra-Op",
"postOp": "Post-Op",
"search": "Search",
"reset": "Reset",
"add": "Add",
"surgeryName": "Surgery Name",
"surgeon": "Surgeon",
"anesthesiologist": "Anesthesiologist",
"circulatingNurse": "Circulating Nurse",
"checkTime": "Check Time",
"status": "Status",
"pending": "Pending",
"inProgress": "In Progress",
"completed": "Completed",
"operation": "Operation",
"edit": "Edit",
"delete": "Delete",
"addTitle": "Add Surgery Safety Check",
"editTitle": "Edit Surgery Safety Check",
"operationSuccess": "Operation successful",
"confirmDelete": "Confirm delete?",
"tip": "Tip",
"deleteSuccess": "Deleted successfully",
"checkContent": "Check Content",
"remark": "Remark",
"cancel": "Cancel",
"confirm": "Confirm"
}
},
"operatingroom": {
"name": "Room Name",
"placeholderName": "Enter room name",
"status": "Status",
"placeholderStatus": "Select status",
"search": "Search",
"reset": "Reset",
"addRoom": "Add Room",
"batchEnable": "Batch Enable",
"batchDisable": "Batch Disable",
"seq": "No.",
"roomNo": "Room No.",
"type": "Type",
"department": "Department",
"location": "Location",
"equipment": "Equipment",
"capacity": "Capacity",
"enabled": "Enabled",
"disabled": "Disabled",
"displayOrder": "Display Order",
"actions": "Actions",
"edit": "Edit",
"view": "View",
"enable": "Enable",
"disable": "Disable",
"placeholderRoomNo": "Enter room no.",
"placeholderCapacity": "Enter capacity",
"placeholderType": "Select type",
"placeholderDept": "Select department",
"placeholderDisplayOrder": "Enter display order",
"placeholderLocation": "Enter location",
"placeholderEquipment": "Enter equipment, e.g.: anesthesia machine, monitor, etc.",
"placeholderRemark": "Enter remark",
"remark": "Remark",
"confirm": "Confirm",
"cancel": "Cancel",
"viewTitle": "Room Details",
"roomCode": "Room Code",
"valRoomNoRequired": "Room no. is required",
"valNameRequired": "Room name is required",
"valCapacityRequired": "Capacity is required",
"valCapacityNumber": "Capacity must be a number",
"valDeptRequired": "Please select department",
"addTitle": "Add Room",
"editTitle": "Edit Room",
"errorGetList": "Failed to get room list",
"errorGetListRetry": "Failed to get room list, please retry",
"successModify": "Modified successfully",
"errorModify": "Modify failed",
"errorModifyRetry": "Modify failed, please retry",
"successAdd": "Added successfully",
"errorAdd": "Add failed",
"errorAddRetry": "Add failed, please retry",
"errorForm": "Please complete the form",
"confirmEnable": "Enable selected rooms?",
"successEnable": "Enabled successfully",
"confirmDisable": "Disable selected rooms?",
"successDisable": "Disabled successfully"
},
"preopmanage": {
"totalDiscussions": "Total Discussions",
"draft": "Draft",
"pendingSignature": "Pending Signature",
"pendingReview": "Pending Review",
"completed": "Completed",
"rejected": "Rejected",
"title": "Preop Discussion Management",
"newDiscussion": "New Discussion",
"patient": "Patient",
"patientName": "Patient Name",
"surgeryLevel": "Surgery Level",
"all": "All",
"level1": "Level 1",
"level2": "Level 2",
"level3": "Level 3",
"level4": "Level 4",
"statusLabel": "Status",
"search": "Search",
"reset": "Reset",
"seq": "No.",
"surgeryName": "Surgery Name",
"level": "Level",
"levelSuffix": "",
"host": "Host",
"conclusion": "Conclusion",
"agreeSurgery": "Agree Surgery",
"needSupplement": "Need Supplement",
"noSurgery": "No Surgery",
"createTime": "Create Time",
"actions": "Actions",
"detail": "Detail",
"submit": "Submit",
"pass": "Pass",
"reject": "Reject",
"newDialogTitle": "New Preop Discussion",
"encounterId": "Admission No.",
"placeholderEncounterId": "Admission No.",
"preopDiagnosis": "Preop Diagnosis",
"placeholderPreopDiagnosis": "Preop Diagnosis",
"surgeryIndication": "Surgery Indication",
"placeholderSurgeryIndication": "Surgery Indication",
"mainPlan": "Main Plan",
"placeholderMainPlan": "Main Surgery Plan",
"backupPlan": "Backup Plan",
"placeholderBackupPlan": "Backup Surgery Plan",
"anesthesiaType": "Anesthesia Type",
"placeholderAnesthesiaType": "Anesthesia Type",
"discussionType": "Discussion Type",
"typeDept": "Department",
"typeFull": "Full Department",
"typeHospital": "Hospital-wide",
"risks": "Risks & Countermeasures",
"placeholderRisks": "Possible risks and countermeasures",
"postopNotes": "Postop Notes",
"placeholderPostopNotes": "Postoperative notes",
"hostName": "Host",
"placeholderHostName": "Host name",
"location": "Location",
"placeholderLocation": "Discussion location",
"conclusionLabel": "Conclusion",
"needFurtherCheck": "Need Further Check",
"save": "Save",
"detailTitle": "Discussion Detail",
"detailPatient": "Patient",
"detailSurgeryName": "Surgery Name",
"detailSurgeryLevel": "Surgery Level",
"detailHost": "Host",
"detailConclusion": "Conclusion",
"detailStatus": "Status",
"discussionContent": "Discussion Content",
"participants": "Participants",
"name": "Name",
"titleProf": "Title",
"role": "Role",
"signature": "Signature",
"signed": "Signed",
"unsigned": "Unsigned",
"signTime": "Sign Time",
"valPatientRequired": "Please enter patient name",
"valSurgeryNameRequired": "Please enter surgery name",
"valSurgeryLevelRequired": "Please select surgery level",
"valDiagnosisRequired": "Please enter preop diagnosis",
"valMainPlanRequired": "Please enter main plan",
"valHostRequired": "Please enter host",
"submitSuccess": "Submitted",
"submitFailed": "Submit failed",
"confirmApprove": "Approve this discussion?",
"confirmReject": "Reject this discussion?",
"approveSuccess": "Approved",
"rejectSuccess": "Rejected",
"approveFailed": "Approve failed",
"rejectFailed": "Reject failed",
"createSuccess": "Created successfully",
"createFailed": "Create failed"
}
}
}

View File

@@ -1364,7 +1364,14 @@
"exportDev": "Chức năng xuất đang phát triển",
"collectSuccess": "Đã thu thập {count} chỉ số",
"collectFailed": "Thu thập thất bại",
"monthLabels": ["T1", "T2", "T3", "T4", "T5", "T6"]
"monthLabels": [
"T1",
"T2",
"T3",
"T4",
"T5",
"T6"
]
},
"execution": {
"title": "Thực hiện y tá nội trú",
@@ -1569,5 +1576,811 @@
"rollFee": "Cấu hình phí tự động",
"medicineReturn": "Trả thuốc"
}
},
"surgicalschedule": {
"operCode": "Số phiếu phẫu thuật",
"placeholderOperCode": "Nhập số phiếu phẫu thuật",
"scheduleDate": "Thời gian xếp lịch",
"rangeSeparator": "đến",
"startDate": "Ngày bắt đầu",
"endDate": "Ngày kết thúc",
"orgName": "Cơ sở y tế",
"placeholderOrg": "Chọn cơ sở y tế",
"applyDept": "Khoa đăng ký",
"placeholderDept": "Chọn khoa",
"patientNameOrPinyin": "Tên/Mã pinyin",
"placeholderNameOrPinyin": "Nhập tên hoặc mã pinyin",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"add": "Thêm lịch phẫu thuật",
"billing": "Viện phí",
"medicalAdvice": "Y lệnh",
"export": "Xuất bảng",
"patientName": "Họ tên",
"identifierNo": "Số thẻ",
"operName": "Tên phẫu thuật",
"surgeryType": "Loại phẫu thuật",
"surgeryNature": "Tính chất phẫu thuật",
"surgeonName": "Bác sĩ chính",
"anesMethod": "Phương pháp gây mê",
"operator": "Người thao tác",
"actions": "Thao tác",
"view": "Xem",
"edit": "Sửa",
"cancel": "Hủy",
"find": "Tìm",
"refresh": "Làm mới",
"back": "Quay lại",
"save": "Lưu",
"patientBasicInfo": "Thông tin cơ bản bệnh nhân",
"patientId": "Mã bệnh nhân",
"gender": "Giới tính",
"male": "Nam",
"female": "Nữ",
"unknown": "Không xác định",
"age": "Tuổi",
"patientWeight": "Cân nặng",
"placeholderWeight": "Nhập cân nặng (kg)",
"patientHeight": "Chiều cao",
"placeholderHeight": "Nhập chiều cao (cm)",
"surgeryApplyInfo": "Thông tin đăng ký phẫu thuật",
"feeType": "Loại phí",
"applyTime": "Thời gian đăng ký",
"applyDoctor": "Bác sĩ đăng ký",
"placeholderSurgeryType": "Chọn loại phẫu thuật",
"surgerySchedule": "Xếp lịch phẫu thuật",
"placeholderScheduleDate": "Chọn thời gian xếp lịch",
"sequenceNo": "Thứ tự mổ",
"placeholderSequenceNo": "Nhập thứ tự mổ",
"roomCode": "Số phòng mổ",
"placeholderRoomCode": "Chọn số phòng mổ",
"tableNo": "Bàn mổ",
"placeholderTableNo": "Nhập bàn mổ",
"isFirstSurgery": "Phẫu thuật đầu tiên",
"yes": "Có",
"no": "Không",
"natureAndSite": "Tính chất và vị trí",
"placeholderSurgeryNature": "Chọn tính chất phẫu thuật",
"surgerySite": "Vị trí phẫu thuật",
"placeholderSurgerySite": "Chọn vị trí phẫu thuật",
"allergyMedication": "Thuốc dị ứng",
"allergyRemark": "Ghi chú dị ứng",
"placeholderAllergyRemark": "Nhập ghi chú dị ứng",
"medicalStaff": "Nhân viên y tế",
"assistant1": "Trợ lý 1",
"placeholderAssistant1": "Chọn trợ lý 1",
"assistant2": "Trợ lý 2",
"placeholderAssistant2": "Chọn trợ lý 2",
"assistant3": "Trợ lý 3",
"placeholderAssistant3": "Chọn trợ lý 3",
"scrubNurse": "Điều dưỡng rửa tay",
"placeholderScrubNurse": "Chọn điều dưỡng rửa tay",
"instrumentNurse1": "Điều dưỡng dụng cụ 1",
"placeholderInstrumentNurse1": "Chọn điều dưỡng dụng cụ 1",
"instrumentNurse2": "Điều dưỡng dụng cụ 2",
"placeholderInstrumentNurse2": "Chọn điều dưỡng dụng cụ 2",
"circulatingNurse1": "Điều dưỡng vòng ngoài 1",
"placeholderCirculatingNurse1": "Chọn điều dưỡng vòng ngoài 1",
"placeholderAnesMethod": "Chọn phương pháp gây mê",
"circulatingNurse2": "Điều dưỡng vòng ngoài 2",
"placeholderCirculatingNurse2": "Chọn điều dưỡng vòng ngoài 2",
"externalExpert": "Chuyên gia bên ngoài",
"externalExpertName": "Tên chuyên gia",
"placeholderExternalExpertName": "Nhập tên chuyên gia",
"anesDoctor1": "Bác sĩ gây mê 1",
"placeholderAnesDoctor1": "Chọn bác sĩ gây mê 1",
"anesDoctor2": "Bác sĩ gây mê 2",
"placeholderAnesDoctor2": "Chọn bác sĩ gây mê 2",
"anesDoctor3": "Bác sĩ gây mê 3",
"placeholderAnesDoctor3": "Chọn bác sĩ gây mê 3",
"preDiagnosis": "Chẩn đoán trước mổ",
"placeholderPreDiagnosis": "Nhập chẩn đoán trước mổ",
"postDiagnosis": "Chẩn đoán sau mổ",
"placeholderPostDiagnosis": "Nhập chẩn đoán sau mổ",
"surgeryProcess": "Quy trình phẫu thuật",
"admissionTime": "Thời gian vào phòng",
"placeholderAdmissionTime": "Chọn thời gian vào phòng",
"entryTime": "Thời gian vào bàn mổ",
"placeholderEntryTime": "Chọn thời gian vào bàn mổ",
"anesStartTime": "Bắt đầu gây mê",
"placeholderAnesStartTime": "Chọn thời gian bắt đầu gây mê",
"startTime": "Thời gian rạch",
"placeholderStartTime": "Chọn thời gian rạch",
"endTime": "Kết thúc phẫu thuật",
"placeholderEndTime": "Chọn thời gian kết thúc",
"anesEndTime": "Kết thúc gây mê",
"placeholderAnesEndTime": "Chọn thời gian kết thúc gây mê",
"incisionType": "Loại vết rạch",
"placeholderIncisionType": "Chọn loại vết rạch",
"infectionDiagnosis": "Chẩn đoán nhiễm trùng",
"placeholderInfectionDiagnosis": "Nhập chẩn đoán nhiễm trùng",
"isolationType": "Loại cách ly",
"placeholderIsolationType": "Nhập loại cách ly",
"implantFlag": "Có cấy ghép",
"implantSerial": "Số sêri/Lô cấy ghép",
"placeholderImplantSerial": "Nhập số sêri/lô cấy ghép",
"bloodLoss": "Lượng máu mất",
"placeholderBloodLoss": "Nhập lượng máu mất",
"bloodTrans": "Lượng máu truyền",
"placeholderBloodTrans": "Nhập lượng máu truyền",
"remarkInfo": "Thông tin ghi chú",
"communicationInfo": "Thông tin trao đổi",
"placeholderCommunicationInfo": "Nhập thông tin trao đổi",
"remark": "Ghi chú",
"placeholderRemark": "Nhập ghi chú",
"applyQuery": "Tìm kiếm đăng ký phẫu thuật",
"applyTimeRange": "Khoảng thời gian đăng ký",
"placeholderSurgeon": "Chọn bác sĩ chính",
"confirm": "Xác nhận",
"patientInfo": "Thông tin BN:",
"billingAccount": "Tài khoản viện phí",
"loadingAdvice": "Đang tải dữ liệu y lệnh, vui lòng đợi...",
"surgeryLevel": "Cấp phẫu thuật",
"anesthesiaType": "Phương pháp gây mê",
"exportFilename": "danh_sach_phau_thuat.csv",
"addSchedule": "Thêm lịch phẫu thuật",
"editTitle": "Sửa lịch phẫu thuật",
"viewTitle": "Xem lịch phẫu thuật",
"temporaryMedicalTitle": "Y lệnh tạm thời trong phẫu thuật ngoại trú",
"insurance": "BHYT",
"selfPay": "Tự trả",
"immediate": "Ngay lập tức",
"ivInjection": "Tiêm tĩnh mạch",
"unknownMedicine": "Thuốc chưa xác định",
"msgSelectScheduleDate": "Vui lòng chọn thời gian xếp lịch",
"msgInputSequenceNo": "Vui lòng nhập thứ tự mổ",
"msgSequenceNoNumber": "Thứ tự mổ phải là số",
"msgSelectRoomCode": "Vui lòng chọn số phòng mổ",
"msgSelectTableNo": "Vui lòng chọn bàn mổ",
"msgSelectSurgeryNature": "Vui lòng chọn tính chất phẫu thuật",
"msgSelectSurgerySite": "Vui lòng chọn vị trí phẫu thuật",
"msgSelectAnesMethod": "Vui lòng chọn phương pháp gây mê",
"msgInputPreDiagnosis": "Vui lòng nhập chẩn đoán trước mổ",
"msgSelectSurgeon": "Vui lòng chọn bác sĩ chính",
"msgGetDetailFailed": "Lấy chi tiết lịch phẫu thuật thất bại",
"msgConfirmDelete": "Bạn có chắc muốn hủy lịch phẫu thuật \"{name}\"?",
"msgDeletedSuccess": "Đã hủy lịch phẫu thuật",
"msgSelectForBilling": "Vui lòng chọn lịch phẫu thuật để tính phí",
"msgNoVisitForBilling": "Lịch phẫu thuật chưa liên kết khám bệnh. Vui lòng xác nhận bệnh nhân đã đăng ký.",
"msgGetAccountFailed": "Lấy thông tin tài khoản thất bại. Vui lòng xác nhận khám bệnh đã có tài khoản viện phí.",
"msgGetAccountError": "Lấy thông tin tài khoản thất bại, vui lòng thử lại.",
"chargeDialogTitle": "Viện phí phẫu thuật - {name} - {op}",
"msgSelectForAdvice": "Vui lòng chọn lịch phẫu thuật để tạo y lệnh",
"msgNoVisitForAdvice": "Lịch phẫu thuật chưa liên kết khám bệnh. Vui lòng xác nhận bệnh nhân đã đăng ký.",
"msgRefreshFailed": "Làm mới dữ liệu thất bại, vui lòng thử lại",
"msgAdviceGenerated": "Đã tạo y lệnh tạm thời (đã ký)",
"msgAdviceDeleted": "Đã xóa y lệnh, chuyển về danh sách chờ",
"msgPatientInfoIncomplete": "Thông tin bệnh nhân chưa đầy đủ, vui lòng đóng và mở lại",
"msgTooManyAdvices": "Quá nhiều y lệnh chờ ({count}), chỉ hiển thị {max} đầu tiên",
"msgQuoteSuccess": "Trích dẫn thuốc viện phí thành công!",
"msgGetChargeFailed": "Lấy dữ liệu viện phí thất bại, vui lòng thử lại",
"msgAddSuccess": "Thêm thành công",
"msgAddFailed": "Thêm lịch phẫu thuật thất bại, vui lòng kiểm tra biểu mẫu",
"msgEditSuccess": "Cập nhật thành công",
"msgUpdateFailed": "Cập nhật lịch phẫu thuật thất bại, vui lòng kiểm tra biểu mẫu",
"msgValidateFailed": "Vui lòng kiểm tra biểu mẫu, trường đỏ là bắt buộc",
"msgGetApplyListFailed": "Lấy danh sách đăng ký phẫu thuật thất bại",
"msgSelectApplyRecord": "Vui lòng chọn một bản ghi đăng ký phẫu thuật",
"msgExportConfirm": "Xuất danh sách lịch phẫu thuật với bộ lọc hiện tại?",
"tmp": {
"title": "Y lệnh tạm thời trong phẫu thuật ngoại trú",
"patientLabel": "Bệnh nhân: ",
"cardNoLabel": "Số thẻ: ",
"operCodeLabel": "Số phiếu phẫu thuật: ",
"deptLabel": "Khoa: ",
"doctorLabel": "Bác sĩ: ",
"roleLabel": "Vai trò: ",
"refresh": "Làm mới",
"quoteBilling": "Trích dẫn viện phí",
"sectionBillingTitle": "1. Thuốc viện phí đã trích dẫn (y lệnh chờ tạo)",
"collapse": "Thu gọn",
"expandAll": "Mở rộng tất cả",
"items": " mục",
"colSeq": "STT",
"colMedicineName": "Tên thuốc",
"colSpec": "Quy cách",
"colQuantity": "Số lượng",
"colBatchNo": "Số lô",
"colUnitPrice": "Đơn giá",
"colSubtotal": "Thành tiền",
"colInsurance": "BHYT",
"insuranceIn": "Trong BHYT",
"selfPay": "Tự trả",
"total": "Tổng cộng",
"sectionAdviceTitle": "2. Xem trước y lệnh tạm thời (đã tạo)",
"colAdviceName": "Tên y lệnh",
"colDosage": "Liều lượng",
"colUnit": "Đơn vị",
"colUsage": "Cách dùng",
"colFrequency": "Tần suất",
"immediate": "Ngay lập tức",
"colExecuteTime": "Thời gian thực hiện",
"colAction": "Thao tác",
"edit": "Sửa",
"delete": "Xóa",
"sectionSignatureTitle": "3. Chữ ký điện tử bác sĩ",
"signDoctorLabel": "Bác sĩ ký: ",
"signTimeLabel": "Thời gian ký: ",
"unsigned": "Chưa ký",
"cancel": "Hủy",
"alreadySigned": "Đã ký",
"signAndGenerate": "Ký và tạo y lệnh",
"signDialogTitle": "Mật khẩu chữ ký",
"enterAccountPassword": "Vui lòng nhập mật khẩu tài khoản:",
"placeholderPassword": "Nhập mật khẩu",
"confirm": "Xác nhận",
"editDialogTitle": "Sửa y lệnh",
"placeholderDosage": "Nhập liều lượng",
"placeholderUnit": "Nhập đơn vị",
"placeholderSelectUsage": "Chọn cách dùng",
"loading": "Đang tải...",
"save": "Lưu",
"tip": "Thông báo",
"unknownUser": "Người dùng chưa xác định",
"usageIv": "Tiêm tĩnh mạch",
"usagePo": "Uống",
"usageIm": "Tiêm bắp",
"usageSc": "Tiêm dưới da",
"usageIvgtt": "Truyền tĩnh mạch",
"usageIh": "Hít",
"usageIt": "Ngậm",
"usageIp": "Tiêm phúc mạc",
"usageTop": "Bôi ngoài",
"usagePr": "Đặt hậu môn",
"msgFillDosage": "Vui lòng nhập liều lượng",
"msgDosageMustBeNumber": "Liều lượng phải là số",
"msgFillUsage": "Vui lòng nhập cách dùng",
"msgEditSaved": "Đã lưu chỉnh sửa y lệnh lên máy chủ",
"msgSaveFailedRetry": "Lưu thất bại, vui lòng thử lại",
"msgEnterPassword": "Vui lòng nhập mật khẩu",
"msgSignSuccess": "Ký thành công",
"msgConfirmRollback": "Bạn có chắc muốn hoàn tác y lệnh này?",
"msgRollbackSuccess": "Hoàn tác thành công",
"msgRollbackFailedRetry": "Hoàn tác thất bại, vui lòng thử lại",
"msgSignFirst": "Vui lòng ký điện tử trước",
"msgSubmitting": "Đang gửi y lệnh, vui lòng đợi...",
"msgNoAdviceData": "Không có dữ liệu y lệnh để lưu",
"msgSaveSuccess": "Lưu y lệnh tạm thời thành công",
"msgSaveFailed": "Lưu y lệnh thất bại: ",
"unknownError": "Lỗi không xác định"
},
"msgGetScheduleListFailed": "Lấy danh sách lịch phẫu thuật thất bại, vui lòng thử lại sau",
"msgTooManyDrafts": "Quá nhiều y lệnh chờ ký ({count}条), chỉ hiển thị {max} đầu tiên",
"placeholderSurgeryRemark": "Nhập ghi chú phẫu thuật",
"scheduleTime": "Thời gian xếp lịch",
"surgeryNameLabel": "Tên phẫu thuật",
"surgeryRemark": "Ghi chú phẫu thuật"
},
"surgerymanage": {
"surgeryNo": "Số phẫu thuật",
"surgeryName": "Tên phẫu thuật",
"patientName": "Tên bệnh nhân",
"surgeryStatus": "Trạng thái phẫu thuật",
"surgeryType": "Loại phẫu thuật",
"plannedTime": "Thời gian dự kiến",
"rangeSeparator": "đến",
"startDate": "Ngày bắt đầu",
"endDate": "Ngày kết thúc",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"addSurgery": "Thêm phẫu thuật",
"refresh": "Làm mới",
"applyDate": "Ngày đăng ký",
"surgeryOrderNo": "Số phiếu phẫu thuật",
"applyDoctor": "Bác sĩ đăng ký",
"applyDept": "Khoa đăng ký",
"surgeryLevel": "Cấp phẫu thuật",
"emergency": "Cấp cứu",
"yes": "Có",
"no": "Không",
"implantMaterial": "Vật liệu cấy ghép",
"mainSurgeon": "Bác sĩ chính",
"anesthetist": "Bác sĩ gây mê",
"anesthesiaType": "Phương pháp gây mê",
"bodySite": "Vị trí phẫu thuật",
"operatingRoom": "Phòng mổ",
"operatingRoomDept": "Khoa phòng mổ",
"execDept": "Khoa thực hiện",
"status": "Trạng thái",
"actions": "Thao tác",
"view": "Xem",
"edit": "Sửa",
"cancel": "Hủy",
"schedule": "Lịch hẹn",
"start": "Bắt đầu",
"complete": "Hoàn thành",
"currentStatus": "Trạng thái hiện tại",
"viewModeTip": "Chế độ xem: tất cả trường chỉ đọc",
"patient": "Bệnh nhân",
"placeholderPatient": "Chọn bệnh nhân",
"noIdCard": "Không có CCCD",
"editModePatientTip": "Không thể thay đổi bệnh nhân ở chế độ sửa",
"encounterNo": "Số khám bệnh",
"placeholderEncounterNo": "Chọn khám bệnh",
"originalEncounter": "Khám bệnh gốc",
"none": "Không có",
"placeholderAutoDoctor": "Tự động từ tài khoản đăng nhập",
"placeholderAutoDept": "Tự động từ khoa của bác sĩ",
"surgeryCode": "Mã phẫu thuật",
"placeholderSurgeryCode": "Nhập mã phẫu thuật",
"plannedSurgeryTime": "Thời gian phẫu thuật dự kiến",
"placeholderDateTime": "Chọn ngày giờ",
"placeholderBodySite": "Chọn vị trí phẫu thuật",
"surgeryTeam": "Kíp mổ",
"placeholderMainSurgeon": "Chọn bác sĩ chính",
"placeholderAnesthetist": "Chọn bác sĩ gây mê",
"assistant1": "Trợ lý 1",
"placeholderAssistant1": "Chọn trợ lý 1",
"assistant2": "Trợ lý 2",
"placeholderAssistant2": "Chọn trợ lý 2",
"scrubNurse": "Điều dưỡng vòng ngoài",
"placeholderScrubNurse": "Chọn điều dưỡng vòng ngoài",
"placeholderAnesthesiaType": "Chọn phương pháp gây mê",
"placeholderOperatingRoom": "Chọn phòng mổ",
"placeholderExecDept": "Chọn khoa thực hiện",
"diagnosisInfo": "Thông tin chẩn đoán",
"preoperativeDiagnosis": "Chẩn đoán trước mổ",
"placeholderPreoperativeDiagnosis": "Nhập chẩn đoán trước mổ",
"postoperativeDiagnosis": "Chẩn đoán sau mổ",
"placeholderPostoperativeDiagnosis": "Nhập chẩn đoán sau mổ",
"surgeryDescription": "Mô tả phẫu thuật",
"placeholderSurgeryDescription": "Nhập mô tả phẫu thuật",
"postoperativeAdvice": "Y lệnh sau mổ",
"placeholderPostoperativeAdvice": "Nhập y lệnh sau mổ",
"surgeryFee": "Phí phẫu thuật",
"anesthesiaFee": "Phí gây mê",
"totalFee": "Tổng phí",
"incisionLevel": "Mức độ rạch",
"placeholderIncisionLevel": "Chọn mức độ rạch",
"healingLevel": "Mức độ lành",
"placeholderHealingLevel": "Chọn mức độ lành",
"complications": "Biến chứng",
"placeholderComplications": "Nhập mô tả biến chứng",
"emergencyFlag": "Cấp cứu",
"implantFlag": "Cấy ghép vật liệu",
"operatingRoomConfirmUser": "Người xác nhận phòng mổ",
"placeholderOperatingRoomConfirmUser": "Người xác nhận",
"operatingRoomConfirmTime": "Thời gian xác nhận phòng mổ",
"placeholderOperatingRoomConfirmTime": "Chọn thời gian xác nhận",
"remark": "Ghi chú",
"placeholderRemark": "Nhập ghi chú",
"close": "Đóng",
"confirm": "Xác nhận",
"placeholderSurgeryNo": "Nhập số phẫu thuật",
"placeholderSurgeryName": "Nhập tên phẫu thuật",
"placeholderPatientName": "Nhập tên bệnh nhân",
"placeholderSurgeryStatus": "Chọn trạng thái phẫu thuật",
"placeholderSurgeryType": "Chọn loại phẫu thuật",
"statusPending": "Chờ xếp lịch",
"statusScheduled": "Đã xếp lịch",
"statusInProgress": "Đang phẫu thuật",
"statusCompleted": "Hoàn thành",
"statusCancelled": "Đã hủy",
"statusPaused": "Tạm dừng",
"healingGradeA": "Lành loại A",
"healingGradeB": "Lành loại B",
"healingGradeC": "Lành loại C",
"encounterRegistered": "Đã đăng ký",
"encounterInProgress": "Đang khám",
"encounterCompleted": "Hoàn thành",
"encounterCancelled": "Đã hủy",
"unknown": "Không xác định",
"valPatientRequired": "Vui lòng chọn bệnh nhân",
"valSurgeryNameRequired": "Vui lòng nhập tên phẫu thuật",
"valSurgeryTypeRequired": "Vui lòng chọn loại phẫu thuật",
"valSurgeryLevelRequired": "Vui lòng chọn cấp phẫu thuật",
"valPlannedTimeRequired": "Vui lòng chọn thời gian phẫu thuật",
"valMainSurgeonRequired": "Vui lòng chọn bác sĩ chính",
"valAnesthesiaTypeRequired": "Vui lòng chọn phương pháp gây mê",
"valBodySiteRequired": "Vui lòng nhập vị trí phẫu thuật",
"addSurgeryTitle": "Thêm phẫu thuật mới",
"editSurgeryTitle": "Sửa phẫu thuật",
"viewSurgeryTitle": "Xem phẫu thuật",
"errorGetSurgeryList": "Lấy danh sách phẫu thuật thất bại",
"errorGetPatientList": "Lấy danh sách bệnh nhân thất bại",
"warningNoEncounter": "Bệnh nhân chưa có khám bệnh, vui lòng đăng ký trước",
"errorGetEncounterList": "Lấy danh sách khám bệnh thất bại",
"errorGetDoctorList": "Lấy danh sách bác sĩ thất bại",
"errorGetOperatingRoomList": "Lấy danh sách phòng mổ thất bại",
"errorGetNurseList": "Lấy danh sách điều dưỡng thất bại",
"errorGetOrgList": "Lấy danh sách khoa thất bại",
"warningEditNotAllowed": "Trạng thái hiện tại không cho phép sửa",
"errorGetSurgeryInfo": "Lấy thông tin phẫu thuật thất bại",
"infoViewModeNoSubmit": "Chế độ xem, không thể gửi",
"successAdd": "Thêm thành công",
"errorAddSurgery": "Thêm phẫu thuật thất bại, vui lòng kiểm tra biểu mẫu",
"successUpdate": "Cập nhật thành công",
"errorUpdateSurgery": "Cập nhật phẫu thuật thất bại, vui lòng kiểm tra biểu mẫu",
"errorFormValidation": "Vui lòng kiểm tra biểu mẫu, trường đỏ là bắt buộc",
"confirmDelete": "Bạn có chắc muốn xóa phẫu thuật \"{name}\"?",
"successDelete": "Xóa thành công",
"errorDelete": "Xóa thất bại",
"confirmCancel": "Bạn có chắc muốn hủy phẫu thuật \"{name}\"?",
"successCancelled": "Đã hủy phẫu thuật",
"errorCancel": "Hủy thất bại",
"warningCancelNotAllowed": "Trạng thái hiện tại không cho phép hủy",
"warningSelectOperatingRoom": "Vui lòng chọn phòng mổ trước",
"warningSetPlannedTime": "Vui lòng đặt thời gian phẫu thuật trước",
"confirmSchedule": "Bạn có chắc muốn xếp lịch phẫu thuật \"{name}\"?",
"successScheduled": "Đã xếp lịch phẫu thuật",
"errorSchedule": "Xếp lịch thất bại",
"confirmStart": "Bạn có chắc muốn bắt đầu phẫu thuật \"{name}\"?",
"successStarted": "Đã bắt đầu phẫu thuật",
"errorStart": "Bắt đầu phẫu thuật thất bại",
"confirmComplete": "Bạn có chắc muốn hoàn thành phẫu thuật \"{name}\"?",
"successCompleted": "Đã hoàn thành phẫu thuật",
"errorComplete": "Hoàn thành phẫu thuật thất bại",
"infoSelectEncounter": "Vui lòng chọn khám bệnh",
"sun": "CN",
"mon": "T2",
"tue": "T3",
"wed": "T4",
"thu": "T5",
"fri": "T6",
"sat": "T7"
},
"emr": {
"timeliness": {
"stats": { "pending": "Chờ hoàn thành", "completed": "Đã hoàn thành", "overdue": "Quá hạn", "rate": "Tỷ lệ hoàn thành" },
"department": "Khoa",
"emrTypeLabel": "Loại bệnh án",
"statusLabel": "Trạng thái",
"all": "Tất cả",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"doctor": "Bác sĩ",
"requiredHours": "Thời gian yêu cầu(h)",
"deadline": "Hạn chót",
"actualCompleteTime": "Thời gian hoàn thành thực tế",
"emrType": { "admission": "Bệnh án nhập viện", "firstCourse": "Diễn biến đầu", "dailyCourse": "Diễn biến hàng ngày", "discharge": "Bệnh án ra viện" },
"status": { "pending": "Chờ hoàn thành", "completed": "Đã hoàn thành", "overdue": "Quá hạn" }
},
"sync": {
"title": "Đồng bộ dữ liệu EMR",
"stats": "Thống kê đồng bộ",
"emrCount": "Tổng bệnh án",
"revisionCount": "Lịch sử sửa đổi",
"searchIndexCount": "Chỉ mục tìm kiếm",
"operations": "Thao tác đồng bộ",
"alertMessage": "Đồng bộ sẽ xóa lịch sử sửa đổi và chỉ mục tìm kiếm hiện có, sau đó tạo lại từ bảng bệnh án.",
"syncing": "Đang đồng bộ...",
"startSync": "Bắt đầu đồng bộ",
"refreshStats": "Làm mới thống kê",
"confirmMessage": "Đồng bộ dữ liệu EMR? Thao tác này sẽ xóa lịch sử sửa đổi và chỉ mục tìm kiếm hiện có.",
"confirmTitle": "Xác nhận đồng bộ",
"syncComplete": "Đồng bộ hoàn tất",
"syncFailed": "Đồng bộ thất bại",
"unknownError": "Lỗi không xác định"
},
"archive": {
"title": "In và lưu trữ bệnh án",
"syncing": "Đang đồng bộ...",
"syncHistory": "Đồng bộ dữ liệu lịch sử",
"refreshStats": "Làm mới thống kê",
"totalRecords": "Tổng bản ghi",
"archived": "Đã lưu trữ",
"pendingArchive": "Chờ lưu trữ",
"archiveRate24h": "Tỷ lệ lưu trữ 24h",
"patientName": "Tên bệnh nhân",
"status": "Trạng thái",
"printed": "Đã in",
"lost": "Mất",
"query": "Tìm kiếm",
"patient": "Bệnh nhân",
"emrType": "Loại bệnh án",
"title_col": "Tiêu đề",
"operation": "Thao tác",
"print": "In",
"archive": "Lưu trữ",
"reprint": "In lại",
"printBy": "Người in",
"printCount": "Số lần in",
"time": "Thời gian",
"archiver": "Người lưu trữ",
"confirmArchive": "Xác nhận lưu trữ",
"archivedSuccess": "Đã lưu trữ",
"reprintAdded": "Đã thêm bản ghi in lại",
"syncConfirmMessage": "Sẽ đồng bộ dữ liệu từ bảng bệnh án đến lịch sử sửa đổi và chỉ mục tìm kiếm. Tiếp tục?",
"syncConfirmTitle": "Xác nhận đồng bộ",
"syncComplete": "Đồng bộ hoàn tất",
"syncFailed": "Đồng bộ thất bại"
},
"completeness": {
"executeCheck": "Thực hiện kiểm tra tính đầy đủ",
"emrId": "Mã bệnh án",
"emrIdPlaceholder": "Nhập mã bệnh án",
"encounterId": "Mã khám bệnh",
"encounterIdPlaceholder": "Nhập mã khám bệnh",
"totalItems": "Tổng mục kiểm tra",
"requiredTotal": "Tổng bắt buộc",
"requiredPassed": "Bắt buộc đạt",
"isComplete": "Đầy đủ",
"yes": "Có",
"no": "Không",
"failedItemsAlert": "Cảnh báo mục không đạt",
"resultDetail": "Chi tiết kết quả kiểm tra",
"checkItem": "Mục kiểm tra",
"category": "Phân loại",
"required": "Bắt buộc",
"requiredYes": "Bắt buộc",
"requiredNo": "Tùy chọn",
"checkResult": "Kết quả",
"pass": "Đạt",
"fail": "Không đạt",
"detail": "Chi tiết",
"checkTime": "Thời gian kiểm tra",
"categoryBasic": "Thông tin cơ bản",
"categoryExamination": "Khám",
"categoryDiagnosis": "Chẩn đoán",
"categoryTreatment": "Điều trị",
"categorySignature": "Chữ ký",
"enterEmrId": "Vui lòng nhập mã bệnh án",
"enterEncounterId": "Vui lòng nhập mã khám bệnh",
"checkPassed": "Kiểm tra tính đầy đủ bệnh án đạt",
"checkFailed": "Kiểm tra tính đầy đủ bệnh án không đạt, có mục không hợp lệ",
"checkError": "Thực hiện kiểm tra thất bại",
"getResultError": "Lấy kết quả kiểm tra thất bại"
},
"warehouse": {
"extractTitle": "Trích xuất dữ liệu có cấu trúc",
"emrId": "Mã bệnh án",
"emrIdPlaceholder": "Nhập mã bệnh án",
"extract": "Trích xuất dữ liệu",
"viewTitle": "Xem dữ liệu có cấu trúc",
"encounterId": "Mã khám bệnh",
"encounterIdPlaceholder": "Nhập mã khám bệnh",
"query": "Tìm kiếm",
"dataType": "Loại dữ liệu",
"dataKey": "Khóa dữ liệu",
"dataValue": "Giá trị dữ liệu",
"dataUnit": "Đơn vị",
"recordTime": "Thời gian ghi nhận",
"qualityScore": "Điểm chất lượng",
"calculate": "Tính điểm",
"queryHistory": "Lịch sử tìm kiếm",
"totalScore": "Tổng điểm",
"completenessScore": "Tính đầy đủ",
"timelinessScore": "Tính kịp thời",
"accuracyScore": "Tính chính xác",
"scoreTime": "Thời gian chấm điểm",
"emrType": "Loại bệnh án",
"typeVitalSigns": "Sinh hiệu",
"typeLabResults": "Kết quả xét nghiệm",
"typeDiagnosis": "Chẩn đoán",
"typeMedication": "Thuốc",
"enterEmrId": "Vui lòng nhập mã bệnh án",
"enterEncounterId": "Vui lòng nhập mã khám bệnh",
"extractSuccess": "Trích xuất hoàn tất, {count} bản ghi",
"extractFailed": "Trích xuất thất bại",
"queryFailed": "Tìm kiếm thất bại",
"calculateSuccess": "Tính điểm hoàn tất",
"calculateFailed": "Tính điểm thất bại"
},
"revision": {
"title": "Lịch sử sửa đổi bệnh án",
"patient": "Bệnh nhân",
"patientName": "Tên bệnh nhân",
"doctor": "Bác sĩ",
"doctorName": "Tên bác sĩ",
"operator": "Người thao tác",
"operatorName": "Tên người thao tác",
"emrType": "Loại bệnh án",
"all": "Tất cả",
"emrTypeAdmission": "Bệnh án nhập viện",
"emrTypeFirstCourse": "Diễn biến đầu",
"emrTypeDailyCourse": "Diễn biến hàng ngày",
"emrTypeDischarge": "Bệnh án ra viện",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"emrTitle": "Tiêu đề bệnh án",
"emrPrefix": "Bệnh án #",
"attendingDoctor": "Bác sĩ điều trị",
"department": "Khoa",
"encounterNo": "Số khám bệnh",
"operationType": "Loại thao tác",
"changeContent": "Nội dung thay đổi",
"time": "Thời gian",
"operation": "Thao tác",
"detail": "Chi tiết",
"revisionDetail": "Chi tiết sửa đổi",
"version": "Phiên bản",
"contentSnapshot": "Ảnh chụp nội dung",
"opCreate": "Tạo",
"opEdit": "Sửa",
"opApprove": "Duyệt",
"opSign": "Ký",
"loadFailed": "Tải thất bại"
}
},
"surgery": {
"safety": {
"patient": "Bệnh nhân",
"patientName": "Tên bệnh nhân",
"checkPhase": "Giai đoạn kiểm tra",
"all": "Tất cả",
"preOp": "Trước mổ",
"intraOp": "Trong mổ",
"postOp": "Sau mổ",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"add": "Thêm",
"surgeryName": "Tên phẫu thuật",
"surgeon": "Bác sĩ chính",
"anesthesiologist": "Bác sĩ gây mê",
"circulatingNurse": "Điều dưỡng vòng ngoài",
"checkTime": "Thời gian kiểm tra",
"status": "Trạng thái",
"pending": "Chờ kiểm tra",
"inProgress": "Đang kiểm tra",
"completed": "Hoàn thành",
"operation": "Thao tác",
"edit": "Sửa",
"delete": "Xóa",
"addTitle": "Thêm kiểm tra an toàn phẫu thuật",
"editTitle": "Sửa kiểm tra an toàn phẫu thuật",
"operationSuccess": "Thao tác thành công",
"confirmDelete": "Xác nhận xóa?",
"tip": "Thông báo",
"deleteSuccess": "Xóa thành công",
"checkContent": "Nội dung kiểm tra",
"remark": "Ghi chú",
"cancel": "Hủy",
"confirm": "Xác nhận"
}
},
"operatingroom": {
"name": "Tên phòng mổ",
"placeholderName": "Nhập tên phòng mổ",
"status": "Trạng thái",
"placeholderStatus": "Chọn trạng thái",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"addRoom": "Thêm phòng mổ",
"batchEnable": "Kích hoạt hàng loạt",
"batchDisable": "Vô hiệu hàng loạt",
"seq": "STT",
"roomNo": "Số phòng",
"type": "Loại",
"department": "Khoa",
"location": "Vị trí",
"equipment": "Thiết bị",
"capacity": "Sức chứa",
"enabled": "Kích hoạt",
"disabled": "Vô hiệu",
"displayOrder": "Thứ tự hiển thị",
"actions": "Thao tác",
"edit": "Sửa",
"view": "Xem",
"enable": "Kích hoạt",
"disable": "Vô hiệu",
"placeholderRoomNo": "Nhập số phòng",
"placeholderCapacity": "Nhập sức chứa",
"placeholderType": "Chọn loại",
"placeholderDept": "Chọn khoa",
"placeholderDisplayOrder": "Nhập thứ tự hiển thị",
"placeholderLocation": "Nhập vị trí",
"placeholderEquipment": "Nhập thiết bị, vd: máy gây mê, monitor, bàn mổ...",
"placeholderRemark": "Nhập ghi chú",
"remark": "Ghi chú",
"confirm": "Xác nhận",
"cancel": "Hủy",
"viewTitle": "Chi tiết phòng mổ",
"roomCode": "Mã phòng mổ",
"valRoomNoRequired": "Số phòng không được trống",
"valNameRequired": "Tên phòng không được trống",
"valCapacityRequired": "Sức chứa không được trống",
"valCapacityNumber": "Sức chứa phải là số",
"valDeptRequired": "Vui lòng chọn khoa",
"addTitle": "Thêm phòng mổ",
"editTitle": "Sửa phòng mổ",
"errorGetList": "Lấy danh sách phòng mổ thất bại",
"errorGetListRetry": "Lấy danh sách phòng mổ thất bại, vui lòng thử lại",
"successModify": "Sửa thành công",
"errorModify": "Sửa thất bại",
"errorModifyRetry": "Sửa thất bại, vui lòng thử lại",
"successAdd": "Thêm thành công",
"errorAdd": "Thêm thất bại",
"errorAddRetry": "Thêm thất bại, vui lòng thử lại",
"errorForm": "Vui lòng hoàn thiện biểu mẫu",
"confirmEnable": "Kích hoạt các phòng đã chọn?",
"successEnable": "Kích hoạt thành công",
"confirmDisable": "Vô hiệu các phòng đã chọn?",
"successDisable": "Vô hiệu thành công"
},
"preopmanage": {
"totalDiscussions": "Tổng thảo luận",
"draft": "Bản nháp",
"pendingSignature": "Chờ ký",
"pendingReview": "Chờ duyệt",
"completed": "Hoàn thành",
"rejected": "Từ chối",
"title": "Quản lý thảo luận trước mổ",
"newDiscussion": "Tạo thảo luận",
"patient": "Bệnh nhân",
"patientName": "Tên bệnh nhân",
"surgeryLevel": "Cấp phẫu thuật",
"all": "Tất cả",
"level1": "Cấp 1",
"level2": "Cấp 2",
"level3": "Cấp 3",
"level4": "Cấp 4",
"statusLabel": "Trạng thái",
"search": "Tìm kiếm",
"reset": "Đặt lại",
"seq": "STT",
"surgeryName": "Tên phẫu thuật",
"level": "Cấp",
"levelSuffix": "",
"host": "Chủ trì",
"conclusion": "Kết luận",
"agreeSurgery": "Đồng ý phẫu thuật",
"needSupplement": "Cần bổ sung",
"noSurgery": "Chưa phẫu thuật",
"createTime": "Thời gian tạo",
"actions": "Thao tác",
"detail": "Chi tiết",
"submit": "Gửi",
"pass": "Duyệt",
"reject": "Từ chối",
"newDialogTitle": "Tạo thảo luận trước mổ",
"encounterId": "Số nhập viện",
"placeholderEncounterId": "Số nhập viện",
"preopDiagnosis": "Chẩn đoán trước mổ",
"placeholderPreopDiagnosis": "Chẩn đoán trước mổ",
"surgeryIndication": "Chỉ định phẫu thuật",
"placeholderSurgeryIndication": "Chỉ định phẫu thuật",
"mainPlan": "Kế hoạch chính",
"placeholderMainPlan": "Kế hoạch phẫu thuật chính",
"backupPlan": "Kế hoạch dự phòng",
"placeholderBackupPlan": "Kế hoạch phẫu thuật dự phòng",
"anesthesiaType": "Phương pháp gây mê",
"placeholderAnesthesiaType": "Phương pháp gây mê",
"discussionType": "Loại thảo luận",
"typeDept": "Trong khoa",
"typeFull": "Toàn khoa",
"typeHospital": "Toàn viện",
"risks": "Rủi ro & Đối sách",
"placeholderRisks": "Rủi ro có thể và đối sách",
"postopNotes": "Ghi chú sau mổ",
"placeholderPostopNotes": "Ghi chú sau phẫu thuật",
"hostName": "Chủ trì",
"placeholderHostName": "Tên chủ trì",
"location": "Địa điểm",
"placeholderLocation": "Địa điểm thảo luận",
"conclusionLabel": "Kết luận",
"needFurtherCheck": "Cần kiểm tra thêm",
"save": "Lưu",
"detailTitle": "Chi tiết thảo luận",
"detailPatient": "Bệnh nhân",
"detailSurgeryName": "Tên phẫu thuật",
"detailSurgeryLevel": "Cấp phẫu thuật",
"detailHost": "Chủ trì",
"detailConclusion": "Kết luận",
"detailStatus": "Trạng thái",
"discussionContent": "Nội dung thảo luận",
"participants": "Người tham gia",
"name": "Họ tên",
"titleProf": "Chức danh",
"role": "Vai trò",
"signature": "Chữ ký",
"signed": "Đã ký",
"unsigned": "Chưa ký",
"signTime": "Thời gian ký",
"valPatientRequired": "Vui lòng nhập tên bệnh nhân",
"valSurgeryNameRequired": "Vui lòng nhập tên phẫu thuật",
"valSurgeryLevelRequired": "Vui lòng chọn cấp phẫu thuật",
"valDiagnosisRequired": "Vui lòng nhập chẩn đoán trước mổ",
"valMainPlanRequired": "Vui lòng nhập kế hoạch chính",
"valHostRequired": "Vui lòng nhập chủ trì",
"submitSuccess": "Đã gửi",
"submitFailed": "Gửi thất bại",
"confirmApprove": "Duyệt thảo luận này?",
"confirmReject": "Từ chối thảo luận này?",
"approveSuccess": "Duyệt thành công",
"rejectSuccess": "Từ chối thành công",
"approveFailed": "Duyệt thất bại",
"rejectFailed": "Từ chối thất bại",
"createSuccess": "Tạo thành công",
"createFailed": "Tạo thất bại"
}
}
}

View File

@@ -1363,7 +1363,14 @@
"exportDev": "导出功能开发中",
"collectSuccess": "已采集 {count} 项指标",
"collectFailed": "采集失败",
"monthLabels": ["1月", "2月", "3月", "4月", "5月", "6月"]
"monthLabels": [
"1月",
"2月",
"3月",
"4月",
"5月",
"6月"
]
},
"execution": {
"title": "住院护士执行",
@@ -1568,5 +1575,811 @@
"rollFee": "滚费配置",
"medicineReturn": "退药管理"
}
},
"surgicalschedule": {
"operCode": "手术单号",
"placeholderOperCode": "请输入手术单号",
"scheduleDate": "安排时间",
"rangeSeparator": "至",
"startDate": "开始日期",
"endDate": "结束日期",
"orgName": "卫生机构",
"placeholderOrg": "请选择卫生机构",
"applyDept": "申请科室",
"placeholderDept": "请选择申请科室",
"patientNameOrPinyin": "姓名/拼音码",
"placeholderNameOrPinyin": "请输入姓名/拼音码",
"search": "查询",
"reset": "重置",
"add": "新增手术安排",
"billing": "计费",
"medicalAdvice": "医嘱",
"export": "导出表格",
"patientName": "姓名",
"identifierNo": "就诊卡号",
"operName": "手术名称",
"surgeryType": "手术类型",
"surgeryNature": "手术性质",
"surgeonName": "主刀医生",
"anesMethod": "麻醉方法",
"operator": "操作人",
"actions": "操作",
"view": "查看",
"edit": "编辑",
"cancel": "取消",
"find": "查找",
"refresh": "刷新",
"back": "返回",
"save": "保存",
"patientBasicInfo": "病人基本信息",
"patientId": "患者id",
"gender": "性别",
"male": "男",
"female": "女",
"unknown": "未知",
"age": "年龄",
"patientWeight": "病人体重",
"placeholderWeight": "请输入病人体重kg",
"patientHeight": "病人身高",
"placeholderHeight": "请输入病人身高cm",
"surgeryApplyInfo": "手术申请信息",
"feeType": "费用类别",
"applyTime": "申请时间",
"applyDoctor": "申请医生",
"placeholderSurgeryType": "请选择手术类型",
"surgerySchedule": "手术安排",
"placeholderScheduleDate": "选择安排时间",
"sequenceNo": "手术台次",
"placeholderSequenceNo": "请输入手术台次",
"roomCode": "手术间号",
"placeholderRoomCode": "请选择手术间号",
"tableNo": "手术台",
"placeholderTableNo": "请输入手术台",
"isFirstSurgery": "是否首次手术",
"yes": "是",
"no": "否",
"natureAndSite": "手术性质和部位",
"placeholderSurgeryNature": "请选择手术性质",
"surgerySite": "手术部位",
"placeholderSurgerySite": "请选择手术部位",
"allergyMedication": "过敏药物",
"allergyRemark": "过敏药物备注",
"placeholderAllergyRemark": "请输入过敏药物备注",
"medicalStaff": "医护人员",
"assistant1": "助手1",
"placeholderAssistant1": "请选择助手1",
"assistant2": "助手2",
"placeholderAssistant2": "请选择助手2",
"assistant3": "助手3",
"placeholderAssistant3": "请选择助手3",
"scrubNurse": "洗手护士",
"placeholderScrubNurse": "请选择洗手护士",
"instrumentNurse1": "器械护士1",
"placeholderInstrumentNurse1": "请选择器械护士1",
"instrumentNurse2": "器械护士2",
"placeholderInstrumentNurse2": "请选择器械护士2",
"circulatingNurse1": "巡回护士1",
"placeholderCirculatingNurse1": "请选择巡回护士1",
"placeholderAnesMethod": "请选择麻醉方法",
"circulatingNurse2": "巡回护士2",
"placeholderCirculatingNurse2": "请选择巡回护士2",
"externalExpert": "外请专家",
"externalExpertName": "外请专家姓名",
"placeholderExternalExpertName": "请输入外请专家姓名",
"anesDoctor1": "麻醉医师1",
"placeholderAnesDoctor1": "请选择麻醉医师1",
"anesDoctor2": "麻醉医师2",
"placeholderAnesDoctor2": "请选择麻醉医师2",
"anesDoctor3": "麻醉医师3",
"placeholderAnesDoctor3": "请选择麻醉医师3",
"preDiagnosis": "术前诊断",
"placeholderPreDiagnosis": "请输入术前诊断",
"postDiagnosis": "术后诊断",
"placeholderPostDiagnosis": "请输入术后诊断",
"surgeryProcess": "手术过程",
"admissionTime": "入室时间",
"placeholderAdmissionTime": "选择入室时间",
"entryTime": "进室时间",
"placeholderEntryTime": "选择进室时间",
"anesStartTime": "麻醉开始时间",
"placeholderAnesStartTime": "选择麻醉开始时间",
"startTime": "切开时间",
"placeholderStartTime": "选择切开时间",
"endTime": "手术结束时间",
"placeholderEndTime": "选择手术结束时间",
"anesEndTime": "麻醉结束时间",
"placeholderAnesEndTime": "选择麻醉结束时间",
"incisionType": "切口类型",
"placeholderIncisionType": "请选择切口类型",
"infectionDiagnosis": "感染诊断",
"placeholderInfectionDiagnosis": "请输入感染诊断",
"isolationType": "隔离种类",
"placeholderIsolationType": "请输入隔离种类",
"implantFlag": "是否植入标志",
"implantSerial": "植入物序列号/批号",
"placeholderImplantSerial": "请输入植入物序列号/批号",
"bloodLoss": "出血量",
"placeholderBloodLoss": "请输入出血量",
"bloodTrans": "输血量",
"placeholderBloodTrans": "请输入输血量",
"remarkInfo": "备注信息",
"communicationInfo": "手术相关对话信息",
"placeholderCommunicationInfo": "请输入手术相关对话信息",
"remark": "手术相关备注",
"placeholderRemark": "请输入手术相关备注",
"applyQuery": "手术申请查询",
"applyTimeRange": "申请时间范围",
"placeholderSurgeon": "请选择主刀医生",
"confirm": "确认",
"patientInfo": "患者信息:",
"billingAccount": "计费账号",
"loadingAdvice": "正在加载医嘱数据,请稍候...",
"surgeryLevel": "手术等级",
"anesthesiaType": "麻醉方式",
"exportFilename": "手术安排列表.csv",
"addSchedule": "新增手术安排",
"editTitle": "编辑手术安排",
"viewTitle": "查看手术安排",
"temporaryMedicalTitle": "门诊术中临时医嘱",
"insurance": "医保",
"selfPay": "自费",
"immediate": "立即",
"ivInjection": "静脉注射",
"unknownMedicine": "未知药品",
"msgSelectScheduleDate": "请选择安排时间",
"msgInputSequenceNo": "请输入手术台次",
"msgSequenceNoNumber": "手术台次必须为数字",
"msgSelectRoomCode": "请选择手术间号",
"msgSelectTableNo": "请选择手术台",
"msgSelectSurgeryNature": "请选择手术性质",
"msgSelectSurgerySite": "请选择手术部位",
"msgSelectAnesMethod": "请选择麻醉方法",
"msgInputPreDiagnosis": "请输入术前诊断",
"msgSelectSurgeon": "请选择主刀医生",
"msgGetDetailFailed": "获取手术安排详情失败",
"msgConfirmDelete": "是否确认取消手术安排\"{name}\"?",
"msgDeletedSuccess": "手术安排已取消",
"msgSelectForBilling": "请先选择要计费的手术安排",
"msgNoVisitForBilling": "该手术安排未关联就诊记录,无法计费。请先确认患者已完成就诊登记。",
"msgGetAccountFailed": "获取账户信息失败,请确认该就诊记录是否已建立计费账户。",
"msgGetAccountError": "获取账户信息异常,请稍后重试。",
"chargeDialogTitle": "手术计费 - {name} - {op}",
"msgSelectForAdvice": "请先选择要开具医嘱的手术安排",
"msgNoVisitForAdvice": "该手术安排未关联就诊记录,无法开具医嘱。请先确认患者已完成就诊登记。",
"msgRefreshFailed": "刷新数据失败,请重试",
"msgAdviceGenerated": "临时医嘱已生成(已签发)",
"msgAdviceDeleted": "临时医嘱已删除,已放回待生成列表",
"msgPatientInfoIncomplete": "患者信息不完整,请关闭弹窗重新打开",
"msgTooManyAdvices": "待签发医嘱数量过多({count}条),仅显示前{max}条",
"msgQuoteSuccess": "已成功引用最新计费药品信息!",
"msgGetChargeFailed": "获取计费数据失败,请重试",
"msgAddSuccess": "新增成功",
"msgAddFailed": "新增手术安排失败,请检查表单信息",
"msgEditSuccess": "修改成功",
"msgUpdateFailed": "更新手术安排失败,请检查表单信息",
"msgValidateFailed": "请检查表单信息,标红字段为必填项",
"msgGetApplyListFailed": "获取手术申请列表失败,请稍后重试",
"msgSelectApplyRecord": "请先选择一条手术申请记录",
"msgExportConfirm": "确定要导出当前筛选条件下的手术安排列表吗?",
"tmp": {
"title": "门诊术中临时医嘱",
"patientLabel": "患者:",
"cardNoLabel": "就诊卡号:",
"operCodeLabel": "手术单号:",
"deptLabel": "科室:",
"doctorLabel": "医师:",
"roleLabel": "角色:",
"refresh": "刷新",
"quoteBilling": "引用计费",
"sectionBillingTitle": "一、已引用计费药品(待生成医嘱)",
"collapse": "收起",
"expandAll": "展开全部",
"items": "条",
"colSeq": "序号",
"colMedicineName": "药品名称",
"colSpec": "规格",
"colQuantity": "数量",
"colBatchNo": "批号",
"colUnitPrice": "单价",
"colSubtotal": "小计",
"colInsurance": "医保",
"insuranceIn": "医保内",
"selfPay": "自费",
"total": "总计",
"sectionAdviceTitle": "二、临时医嘱预览(已生成)",
"colAdviceName": "医嘱名称",
"colDosage": "剂量",
"colUnit": "单位",
"colUsage": "用法",
"colFrequency": "频次",
"immediate": "立即",
"colExecuteTime": "执行时间",
"colAction": "操作",
"edit": "编辑",
"delete": "删除",
"sectionSignatureTitle": "三、医师电子签名",
"signDoctorLabel": "签名医师:",
"signTimeLabel": "签名时间:",
"unsigned": "未签名",
"cancel": "取消",
"alreadySigned": "已签发",
"signAndGenerate": "一键签名并生成医嘱",
"signDialogTitle": "弹窗-签名密码",
"enterAccountPassword": "请输入账户密码:",
"placeholderPassword": "请输入密码",
"confirm": "确认",
"editDialogTitle": "编辑医嘱",
"placeholderDosage": "请输入剂量",
"placeholderUnit": "请输入单位",
"placeholderSelectUsage": "请选择用法",
"loading": "加载中...",
"save": "保存",
"tip": "提示",
"unknownUser": "未知用户",
"usageIv": "静脉注射",
"usagePo": "口服",
"usageIm": "肌肉注射",
"usageSc": "皮下注射",
"usageIvgtt": "静脉滴注",
"usageIh": "吸入给药",
"usageIt": "含化",
"usageIp": "腹腔用药",
"usageTop": "局部用药",
"usagePr": "直肠给药",
"msgFillDosage": "请填写剂量",
"msgDosageMustBeNumber": "剂量必须为数字",
"msgFillUsage": "请填写用法",
"msgEditSaved": "医嘱修改已保存到服务器",
"msgSaveFailedRetry": "保存失败,请重试",
"msgEnterPassword": "请输入密码",
"msgSignSuccess": "签名成功",
"msgConfirmRollback": "确定要回退这条医嘱吗?",
"msgRollbackSuccess": "回退成功",
"msgRollbackFailedRetry": "回退失败,请重试",
"msgSignFirst": "请先进行电子签名",
"msgSubmitting": "正在提交医嘱,请稍候...",
"msgNoAdviceData": "没有可保存的医嘱数据",
"msgSaveSuccess": "临时医嘱保存成功",
"msgSaveFailed": "保存医嘱失败:",
"unknownError": "未知错误"
},
"msgGetScheduleListFailed": "获取手术安排列表失败,请稍后重试",
"msgTooManyDrafts": "待签发医嘱数量过多({count}条),仅显示前{max}条",
"placeholderSurgeryRemark": "请输入手术相关备注",
"scheduleTime": "安排时间",
"surgeryNameLabel": "手术名称",
"surgeryRemark": "手术相关备注"
},
"surgerymanage": {
"surgeryNo": "手术编号",
"surgeryName": "手术名称",
"patientName": "患者姓名",
"surgeryStatus": "手术状态",
"surgeryType": "手术类型",
"plannedTime": "计划时间",
"rangeSeparator": "至",
"startDate": "开始日期",
"endDate": "结束日期",
"search": "搜索",
"reset": "重置",
"addSurgery": "新增手术",
"refresh": "刷新",
"applyDate": "申请日期",
"surgeryOrderNo": "手术单号",
"applyDoctor": "申请医生",
"applyDept": "申请科室",
"surgeryLevel": "手术等级",
"emergency": "急诊",
"yes": "是",
"no": "否",
"implantMaterial": "植入耗材",
"mainSurgeon": "主刀医生",
"anesthetist": "麻醉医生",
"anesthesiaType": "麻醉方式",
"bodySite": "手术部位",
"operatingRoom": "手术室",
"operatingRoomDept": "手术室科室",
"execDept": "执行科室",
"status": "状态",
"actions": "操作",
"view": "查看",
"edit": "编辑",
"cancel": "取消",
"schedule": "排期",
"start": "开始",
"complete": "完成",
"currentStatus": "当前状态",
"viewModeTip": "当前为查看模式,所有字段均为只读状态",
"patient": "患者",
"placeholderPatient": "请选择患者",
"noIdCard": "无身份证号",
"editModePatientTip": "编辑模式下患者信息不可更改",
"encounterNo": "就诊流水号",
"placeholderEncounterNo": "请选择就诊流水号",
"originalEncounter": "原就诊记录",
"none": "无",
"placeholderAutoDoctor": "系统自动获取当前登录医生",
"placeholderAutoDept": "系统自动获取当前登录医生所属科室",
"surgeryCode": "手术编码",
"placeholderSurgeryCode": "请输入手术编码",
"plannedSurgeryTime": "计划手术时间",
"placeholderDateTime": "选择日期时间",
"placeholderBodySite": "请选择手术部位",
"surgeryTeam": "手术团队",
"placeholderMainSurgeon": "请选择主刀医生",
"placeholderAnesthetist": "请选择麻醉医生",
"assistant1": "助手1",
"placeholderAssistant1": "请选择助手1",
"assistant2": "助手2",
"placeholderAssistant2": "请选择助手2",
"scrubNurse": "巡回护士",
"placeholderScrubNurse": "请选择巡回护士",
"placeholderAnesthesiaType": "请选择麻醉方式",
"placeholderOperatingRoom": "请选择手术室",
"placeholderExecDept": "请选择执行科室",
"diagnosisInfo": "诊断信息",
"preoperativeDiagnosis": "术前诊断",
"placeholderPreoperativeDiagnosis": "请输入术前诊断",
"postoperativeDiagnosis": "术后诊断",
"placeholderPostoperativeDiagnosis": "请输入术后诊断",
"surgeryDescription": "手术经过描述",
"placeholderSurgeryDescription": "请输入手术经过描述",
"postoperativeAdvice": "术后医嘱",
"placeholderPostoperativeAdvice": "请输入术后医嘱",
"surgeryFee": "手术费用",
"anesthesiaFee": "麻醉费用",
"totalFee": "总费用",
"incisionLevel": "切口等级",
"placeholderIncisionLevel": "请选择切口等级",
"healingLevel": "愈合等级",
"placeholderHealingLevel": "请选择愈合等级",
"complications": "并发症描述",
"placeholderComplications": "请输入并发症描述",
"emergencyFlag": "急诊标志",
"implantFlag": "植入高值耗材标志",
"operatingRoomConfirmUser": "手术室确认人",
"placeholderOperatingRoomConfirmUser": "手术室确认人",
"operatingRoomConfirmTime": "手术室确认时间",
"placeholderOperatingRoomConfirmTime": "选择手术室确认时间",
"remark": "备注",
"placeholderRemark": "请输入备注信息",
"close": "关 闭",
"confirm": "确 定",
"placeholderSurgeryNo": "请输入手术编号",
"placeholderSurgeryName": "请输入手术名称",
"placeholderPatientName": "请输入患者姓名",
"placeholderSurgeryStatus": "请选择手术状态",
"placeholderSurgeryType": "请选择手术类型",
"statusPending": "待排期",
"statusScheduled": "已排期",
"statusInProgress": "手术中",
"statusCompleted": "已完成",
"statusCancelled": "已取消",
"statusPaused": "暂停",
"healingGradeA": "甲级愈合",
"healingGradeB": "乙级愈合",
"healingGradeC": "丙级愈合",
"encounterRegistered": "已挂号",
"encounterInProgress": "进行中",
"encounterCompleted": "已完成",
"encounterCancelled": "已退号",
"unknown": "未知",
"valPatientRequired": "请选择患者",
"valSurgeryNameRequired": "请输入手术名称",
"valSurgeryTypeRequired": "请选择手术类型",
"valSurgeryLevelRequired": "请选择手术等级",
"valPlannedTimeRequired": "请选择计划手术时间",
"valMainSurgeonRequired": "请选择主刀医生",
"valAnesthesiaTypeRequired": "请选择麻醉方式",
"valBodySiteRequired": "请输入手术部位",
"addSurgeryTitle": "新增手术",
"editSurgeryTitle": "编辑手术",
"viewSurgeryTitle": "查看手术",
"errorGetSurgeryList": "获取手术列表失败,请稍后重试",
"errorGetPatientList": "获取患者列表失败",
"warningNoEncounter": "该患者暂无就诊记录,请先挂号或办理住院",
"errorGetEncounterList": "获取就诊列表失败",
"errorGetDoctorList": "获取医生列表失败",
"errorGetOperatingRoomList": "获取手术室列表失败",
"errorGetNurseList": "获取护士列表失败",
"errorGetOrgList": "获取执行科室列表失败",
"warningEditNotAllowed": "当前状态不允许编辑手术,仅新开状态可编辑",
"errorGetSurgeryInfo": "获取手术信息失败",
"infoViewModeNoSubmit": "当前为查看模式,无法提交修改",
"successAdd": "新增成功",
"errorAddSurgery": "新增手术失败,请检查表单信息",
"successUpdate": "修改成功",
"errorUpdateSurgery": "更新手术失败,请检查表单信息",
"errorFormValidation": "请检查表单信息,标红字段为必填项",
"confirmDelete": "是否确认删除手术\"{name}\"?",
"successDelete": "删除成功",
"errorDelete": "删除失败",
"confirmCancel": "是否确认取消手术\"{name}\"?",
"successCancelled": "手术已取消",
"errorCancel": "取消失败",
"warningCancelNotAllowed": "当前状态不允许取消手术",
"warningSelectOperatingRoom": "请先选择手术室后再排期",
"warningSetPlannedTime": "请先设置计划手术时间后再排期",
"confirmSchedule": "是否确认排期手术\"{name}\"?",
"successScheduled": "手术已排期",
"errorSchedule": "排期失败",
"confirmStart": "是否确认开始手术\"{name}\"?",
"successStarted": "手术已开始",
"errorStart": "开始手术失败",
"confirmComplete": "是否确认完成手术\"{name}\"?",
"successCompleted": "手术已完成",
"errorComplete": "完成手术失败",
"infoSelectEncounter": "请选择就诊记录",
"sun": "日",
"mon": "一",
"tue": "二",
"wed": "三",
"thu": "四",
"fri": "五",
"sat": "六"
},
"emr": {
"timeliness": {
"stats": { "pending": "待完成", "completed": "已完成", "overdue": "超时", "rate": "完成率" },
"department": "科室",
"emrTypeLabel": "病历类型",
"statusLabel": "状态",
"all": "全部",
"search": "搜索",
"reset": "重置",
"doctor": "医生",
"requiredHours": "要求时限(h)",
"deadline": "截止时间",
"actualCompleteTime": "实际完成时间",
"emrType": { "admission": "入院记录", "firstCourse": "首次病程", "dailyCourse": "日常病程", "discharge": "出院记录" },
"status": { "pending": "待完成", "completed": "已完成", "overdue": "超时" }
},
"sync": {
"title": "EMR数据同步",
"stats": "同步统计",
"emrCount": "病历总数",
"revisionCount": "修订历史",
"searchIndexCount": "搜索索引",
"operations": "数据同步操作",
"alertMessage": "同步操作将清空现有的修订历史和搜索索引数据,然后从门诊/住院病历表(doc_emr)重新生成。",
"syncing": "同步中...",
"startSync": "开始同步",
"refreshStats": "刷新统计",
"confirmMessage": "确定要同步EMR数据吗这将清空现有的修订历史和搜索索引然后从病历表重新生成。",
"confirmTitle": "确认同步",
"syncComplete": "同步完成",
"syncFailed": "同步失败",
"unknownError": "未知错误"
},
"archive": {
"title": "病历打印归档",
"syncing": "同步中...",
"syncHistory": "同步历史数据",
"refreshStats": "刷新统计",
"totalRecords": "总记录",
"archived": "已归档",
"pendingArchive": "待归档",
"archiveRate24h": "24h归档率",
"patientName": "患者姓名",
"status": "状态",
"printed": "已打印",
"lost": "已遗失",
"query": "查询",
"patient": "患者",
"emrType": "病历类型",
"title_col": "标题",
"operation": "操作",
"print": "打印",
"archive": "归档",
"reprint": "补打",
"printBy": "打印人",
"printCount": "打印次数",
"time": "时间",
"archiver": "归档人",
"confirmArchive": "确认归档",
"archivedSuccess": "已归档",
"reprintAdded": "补打记录已添加",
"syncConfirmMessage": "将从病历表同步数据到修订历史和搜索索引,确定继续?",
"syncConfirmTitle": "确认同步",
"syncComplete": "同步完成",
"syncFailed": "同步失败"
},
"completeness": {
"executeCheck": "执行完整性检查",
"emrId": "病历ID",
"emrIdPlaceholder": "请输入病历ID",
"encounterId": "就诊ID",
"encounterIdPlaceholder": "请输入就诊ID",
"totalItems": "检查项总数",
"requiredTotal": "必填项总数",
"requiredPassed": "必填项通过",
"isComplete": "是否完整",
"yes": "是",
"no": "否",
"failedItemsAlert": "不合格项提醒",
"resultDetail": "检查结果明细",
"checkItem": "检查项",
"category": "分类",
"required": "是否必填",
"requiredYes": "必填",
"requiredNo": "选填",
"checkResult": "检查结果",
"pass": "通过",
"fail": "不合格",
"detail": "详情",
"checkTime": "检查时间",
"categoryBasic": "基本信息",
"categoryExamination": "检查",
"categoryDiagnosis": "诊断",
"categoryTreatment": "治疗",
"categorySignature": "签名",
"enterEmrId": "请输入病历ID",
"enterEncounterId": "请输入就诊ID",
"checkPassed": "病历完整性检查通过",
"checkFailed": "病历完整性检查未通过,存在不合格项",
"checkError": "执行检查失败",
"getResultError": "获取检查结果失败"
},
"warehouse": {
"extractTitle": "结构化数据提取",
"emrId": "病历ID",
"emrIdPlaceholder": "请输入病历ID",
"extract": "提取数据",
"viewTitle": "结构化数据查看",
"encounterId": "就诊ID",
"encounterIdPlaceholder": "请输入就诊ID",
"query": "查询",
"dataType": "数据类型",
"dataKey": "数据键",
"dataValue": "数据值",
"dataUnit": "单位",
"recordTime": "记录时间",
"qualityScore": "质控评分",
"calculate": "计算评分",
"queryHistory": "查询历史",
"totalScore": "总分",
"completenessScore": "完整性",
"timelinessScore": "及时性",
"accuracyScore": "准确性",
"scoreTime": "评分时间",
"emrType": "病历类型",
"typeVitalSigns": "生命体征",
"typeLabResults": "检验结果",
"typeDiagnosis": "诊断",
"typeMedication": "用药",
"enterEmrId": "请输入病历ID",
"enterEncounterId": "请输入就诊ID",
"extractSuccess": "提取完成,共 {count} 条数据",
"extractFailed": "提取失败",
"queryFailed": "查询失败",
"calculateSuccess": "评分计算完成",
"calculateFailed": "计算失败"
},
"revision": {
"title": "病历修改留痕",
"patient": "患者",
"patientName": "患者姓名",
"doctor": "医生",
"doctorName": "医生姓名",
"operator": "操作人",
"operatorName": "操作人",
"emrType": "病历类型",
"all": "全部",
"emrTypeAdmission": "入院记录",
"emrTypeFirstCourse": "首次病程",
"emrTypeDailyCourse": "日常病程",
"emrTypeDischarge": "出院记录",
"search": "搜索",
"reset": "重置",
"emrTitle": "病历标题",
"emrPrefix": "病历 #",
"attendingDoctor": "主治医生",
"department": "科室",
"encounterNo": "就诊号",
"operationType": "操作类型",
"changeContent": "变更内容",
"time": "时间",
"operation": "操作",
"detail": "详情",
"revisionDetail": "修订详情",
"version": "版本",
"contentSnapshot": "内容快照",
"opCreate": "创建",
"opEdit": "编辑",
"opApprove": "审批",
"opSign": "签名",
"loadFailed": "加载失败"
}
},
"surgery": {
"safety": {
"patient": "患者",
"patientName": "患者姓名",
"checkPhase": "核查阶段",
"all": "全部",
"preOp": "术前",
"intraOp": "术中",
"postOp": "术后",
"search": "搜索",
"reset": "重置",
"add": "新增",
"surgeryName": "手术名称",
"surgeon": "主刀医生",
"anesthesiologist": "麻醉医师",
"circulatingNurse": "巡回护士",
"checkTime": "核查时间",
"status": "状态",
"pending": "待核查",
"inProgress": "核查中",
"completed": "已完成",
"operation": "操作",
"edit": "编辑",
"delete": "删除",
"addTitle": "新增手术安全核查",
"editTitle": "编辑手术安全核查",
"operationSuccess": "操作成功",
"confirmDelete": "确认删除?",
"tip": "提示",
"deleteSuccess": "删除成功",
"checkContent": "核查内容",
"remark": "备注",
"cancel": "取消",
"confirm": "确定"
}
},
"operatingroom": {
"name": "手术室名称",
"placeholderName": "请输入手术室名称",
"status": "状态",
"placeholderStatus": "请选择状态",
"search": "搜索",
"reset": "重置",
"addRoom": "新增手术室",
"batchEnable": "批量启用",
"batchDisable": "批量停用",
"seq": "序号",
"roomNo": "房间号",
"type": "类型",
"department": "所属科室",
"location": "位置描述",
"equipment": "设备配置",
"capacity": "容纳人数",
"enabled": "启用",
"disabled": "停用",
"displayOrder": "显示顺序",
"actions": "操作",
"edit": "编辑",
"view": "查看",
"enable": "启用",
"disable": "停用",
"placeholderRoomNo": "请输入房间号",
"placeholderCapacity": "请输入容纳人数",
"placeholderType": "请选择类型",
"placeholderDept": "请选择所属科室",
"placeholderDisplayOrder": "请输入显示顺序",
"placeholderLocation": "请输入位置描述",
"placeholderEquipment": "请输入设备配置,如:麻醉机、监护仪、手术台等",
"placeholderRemark": "请输入备注",
"remark": "备注",
"confirm": "确 定",
"cancel": "取 消",
"viewTitle": "手术室详情",
"roomCode": "手术室编码",
"valRoomNoRequired": "房间号不能为空",
"valNameRequired": "手术室名称不能为空",
"valCapacityRequired": "容纳人数不能为空",
"valCapacityNumber": "容纳人数必须为数字",
"valDeptRequired": "请选择所属科室",
"addTitle": "新增手术室",
"editTitle": "编辑手术室",
"errorGetList": "获取手术室列表失败",
"errorGetListRetry": "获取手术室列表失败,请稍后重试",
"successModify": "修改成功",
"errorModify": "修改失败",
"errorModifyRetry": "修改失败,请稍后重试",
"successAdd": "新增成功",
"errorAdd": "新增失败",
"errorAddRetry": "新增失败,请稍后重试",
"errorForm": "请完善表单信息",
"confirmEnable": "是否确认启用选中的手术室?",
"successEnable": "启用成功",
"confirmDisable": "是否确认停用选中的手术室?",
"successDisable": "停用成功"
},
"preopmanage": {
"totalDiscussions": "总讨论数",
"draft": "草稿",
"pendingSignature": "待签名",
"pendingReview": "待审核",
"completed": "已完成",
"rejected": "已驳回",
"title": "术前讨论管理",
"newDiscussion": "新建讨论",
"patient": "患者",
"patientName": "患者姓名",
"surgeryLevel": "手术级别",
"all": "全部",
"level1": "一级",
"level2": "二级",
"level3": "三级",
"level4": "四级",
"statusLabel": "状态",
"search": "搜索",
"reset": "重置",
"seq": "序号",
"surgeryName": "手术名称",
"level": "级别",
"levelSuffix": "级",
"host": "主持人",
"conclusion": "结论",
"agreeSurgery": "同意手术",
"needSupplement": "需补充检查",
"noSurgery": "暂不手术",
"createTime": "创建时间",
"actions": "操作",
"detail": "详情",
"submit": "提交",
"pass": "通过",
"reject": "驳回",
"newDialogTitle": "新建术前讨论",
"encounterId": "住院号",
"placeholderEncounterId": "住院号",
"preopDiagnosis": "术前诊断",
"placeholderPreopDiagnosis": "术前诊断",
"surgeryIndication": "手术指征",
"placeholderSurgeryIndication": "手术指征",
"mainPlan": "主手术方案",
"placeholderMainPlan": "主手术方案",
"backupPlan": "备选方案",
"placeholderBackupPlan": "备选手术方案",
"anesthesiaType": "麻醉方式",
"placeholderAnesthesiaType": "麻醉方式",
"discussionType": "讨论类型",
"typeDept": "科内讨论",
"typeFull": "全科讨论",
"typeHospital": "全院讨论",
"risks": "风险及对策",
"placeholderRisks": "术中可能风险及对策",
"postopNotes": "术后注意",
"placeholderPostopNotes": "术后注意事项",
"hostName": "主持人",
"placeholderHostName": "主持人姓名",
"location": "讨论地点",
"placeholderLocation": "讨论地点",
"conclusionLabel": "讨论结论",
"needFurtherCheck": "需进一步检查",
"save": "保存",
"detailTitle": "术前讨论详情",
"detailPatient": "患者",
"detailSurgeryName": "手术名称",
"detailSurgeryLevel": "手术级别",
"detailHost": "主持人",
"detailConclusion": "讨论结论",
"detailStatus": "状态",
"discussionContent": "讨论内容",
"participants": "参与者",
"name": "姓名",
"titleProf": "职称",
"role": "角色",
"signature": "签名",
"signed": "已签",
"unsigned": "未签",
"signTime": "签名时间",
"valPatientRequired": "请输入患者姓名",
"valSurgeryNameRequired": "请输入手术名称",
"valSurgeryLevelRequired": "请选择手术级别",
"valDiagnosisRequired": "请输入术前诊断",
"valMainPlanRequired": "请输入主手术方案",
"valHostRequired": "请输入主持人",
"submitSuccess": "已提交",
"submitFailed": "提交失败",
"confirmApprove": "确认通过该讨论?",
"confirmReject": "确认驳回该讨论?",
"approveSuccess": "通过成功",
"rejectSuccess": "驳回成功",
"approveFailed": "通过失败",
"rejectFailed": "驳回失败",
"createSuccess": "创建成功",
"createFailed": "创建失败"
}
}
}

View File

@@ -1,7 +1,7 @@
<template>
<div style="padding:16px">
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
<span style="font-size:18px;font-weight:bold">病历打印归档</span>
<span style="font-size:18px;font-weight:bold">{{ t('emr.archive.title') }}</span>
<div>
<el-button
type="warning"
@@ -9,13 +9,13 @@
@click="handleSync"
style="margin-right:10px"
>
{{ syncing ? '同步中...' : '同步历史数据' }}
{{ syncing ? t('emr.archive.syncing') : t('emr.archive.syncHistory') }}
</el-button>
<el-button
type="primary"
@click="loadStats"
>
刷新统计
{{ t('emr.archive.refreshStats') }}
</el-button>
</div>
</div>
@@ -29,7 +29,7 @@
<div style="font-size:22px;font-weight:bold;color:#409eff">
{{ stats.total||0 }}
</div><div style="font-size:12px;color:#999">
总记录
{{ t('emr.archive.totalRecords') }}
</div>
</div>
</el-card>
@@ -40,7 +40,7 @@
<div style="font-size:22px;font-weight:bold;color:#67c23a">
{{ stats.archived||0 }}
</div><div style="font-size:12px;color:#999">
已归档
{{ t('emr.archive.archived') }}
</div>
</div>
</el-card>
@@ -51,7 +51,7 @@
<div style="font-size:22px;font-weight:bold;color:#e6a23c">
{{ stats.printed||0 }}
</div><div style="font-size:12px;color:#999">
待归档
{{ t('emr.archive.pendingArchive') }}
</div>
</div>
</el-card>
@@ -65,7 +65,7 @@
>
{{ stats.archiveRate24h||0 }}%
</div><div style="font-size:12px;color:#999">
24h归档率
{{ t('emr.archive.archiveRate24h') }}
</div>
</div>
</el-card>
@@ -74,26 +74,26 @@
<div style="margin-bottom:12px;display:flex;gap:8px;flex-wrap:wrap">
<el-input
v-model="q.patientName"
placeholder="患者姓名"
:placeholder="t('emr.archive.patientName')"
clearable
style="width:140px"
/>
<el-select
v-model="q.archiveStatus"
placeholder="状态"
:placeholder="t('emr.archive.status')"
clearable
style="width:120px"
>
<el-option
label="已打印"
:label="t('emr.archive.printed')"
value="PRINTED"
/>
<el-option
label="已归档"
:label="t('emr.archive.archived')"
value="ARCHIVED"
/>
<el-option
label="已遗失"
:label="t('emr.archive.lost')"
value="LOST"
/>
</el-select>
@@ -101,7 +101,7 @@
type="primary"
@click="loadData"
>
查询
{{ t('emr.archive.query') }}
</el-button>
</div>
<el-table
@@ -111,23 +111,23 @@
>
<el-table-column
prop="patientName"
label="患者"
:label="t('emr.archive.patient')"
width="100"
/>
<el-table-column
prop="emrType"
label="病历类型"
:label="t('emr.archive.emrType')"
width="100"
/>
<el-table-column
prop="emrTitle"
label="标题"
:label="t('emr.archive.title')"
width="150"
show-overflow-tooltip
/>
<el-table-column
prop="archiveType"
label="操作"
:label="t('emr.archive.operation')"
width="80"
>
<template #default="{row}">
@@ -136,38 +136,38 @@
type="info"
size="small"
>
打印
{{ t('emr.archive.print') }}
</el-tag>
<el-tag
v-else-if="row.archiveType==='ARCHIVE'"
type="success"
size="small"
>
归档
{{ t('emr.archive.archive') }}
</el-tag>
<el-tag
v-else
type="warning"
size="small"
>
补打
{{ t('emr.archive.reprint') }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="printBy"
label="打印人"
:label="t('emr.archive.printBy')"
width="80"
/>
<el-table-column
prop="printCount"
label="打印次数"
:label="t('emr.archive.printCount')"
width="80"
align="center"
/>
<el-table-column
prop="archiveStatus"
label="状态"
:label="t('emr.archive.status')"
width="90"
>
<template #default="{row}">
@@ -176,14 +176,14 @@
type="success"
size="small"
>
已归档
{{ t('emr.archive.archived') }}
</el-tag>
<el-tag
v-else-if="row.archiveStatus==='PRINTED'"
type="warning"
size="small"
>
待归档
{{ t('emr.archive.pendingArchive') }}
</el-tag>
<el-tag
v-else
@@ -196,11 +196,11 @@
</el-table-column>
<el-table-column
prop="createTime"
label="时间"
:label="t('emr.archive.time')"
width="170"
/>
<el-table-column
label="操作"
:label="t('emr.archive.operation')"
width="160"
>
<template #default="{row}">
@@ -211,7 +211,7 @@
size="small"
@click="doArchive(row)"
>
归档
{{ t('emr.archive.archive') }}
</el-button>
<el-button
type="primary"
@@ -219,7 +219,7 @@
size="small"
@click="doReprint(row)"
>
补打
{{ t('emr.archive.reprint') }}
</el-button>
</template>
</el-table-column>
@@ -235,28 +235,31 @@
</div>
</template>
<script setup>
import {ref,onMounted} from 'vue'
import {ref,onMounted,computed} from 'vue'
import {useRoute} from 'vue-router'
import {ElMessage,ElMessageBox} from 'element-plus'
import {useI18n} from 'vue-i18n'
import {getArchivePage,archive,reprint,getArchiveStats} from './api'
import request from '@/utils/request'
const {t}=useI18n()
const route=useRoute()
const tableData=ref([]);const total=ref(0);const stats=ref({})
const syncing=ref(false)
const q=ref({pageNo:1,pageSize:10,patientName:'',archiveStatus:''})
const loadData=async()=>{const r=await getArchivePage(q.value);tableData.value=r.data?.records||[];total.value=r.data?.total||0}
const loadStats=async()=>{const r=await getArchiveStats();stats.value=r.data||{}}
const doArchive=async(row)=>{const {value}=await ElMessageBox.prompt('归档人','确认归档');if(value){await archive(row.id,value);ElMessage.success('已归档');loadData();loadStats()}}
const doReprint=async(row)=>{await reprint(row.id);ElMessage.success('补打记录已添加');loadData()}
const doArchive=async(row)=>{const {value}=await ElMessageBox.prompt(t('emr.archive.archiver'),t('emr.archive.confirmArchive'));if(value){await archive(row.id,value);ElMessage.success(t('emr.archive.archivedSuccess'));loadData();loadStats()}}
const doReprint=async(row)=>{await reprint(row.id);ElMessage.success(t('emr.archive.reprintAdded'));loadData()}
const handleSync=async()=>{
try{
await ElMessageBox.confirm('将从病历表同步数据到修订历史和搜索索引,确定继续?','确认同步',{type:'warning'})
await ElMessageBox.confirm(t('emr.archive.syncConfirmMessage'),t('emr.archive.syncConfirmTitle'),{type:'warning'})
syncing.value=true
const res=await request({url:'/emr-sync/sync',method:'post'})
ElMessage.success(res.data||'同步完成')
ElMessage.success(res.data||t('emr.archive.syncComplete'))
loadData();loadStats()
}catch(e){
if(e!=='cancel') ElMessage.error('同步失败')
if(e!=='cancel') ElMessage.error(t('emr.archive.syncFailed'))
}finally{
syncing.value=false
}

View File

@@ -2,18 +2,18 @@
<div class="app-container">
<el-card shadow="hover" class="mb8">
<template #header>
<span>执行完整性检查</span>
<span>{{ t('emr.completeness.executeCheck') }}</span>
</template>
<el-form :inline="true" :model="checkForm">
<el-form-item label="病历ID">
<el-input v-model="checkForm.emrId" placeholder="请输入病历ID" clearable />
<el-form-item :label="t('emr.completeness.emrId')">
<el-input v-model="checkForm.emrId" :placeholder="t('emr.completeness.emrIdPlaceholder')" clearable />
</el-form-item>
<el-form-item label="就诊ID">
<el-input v-model="checkForm.encounterId" placeholder="请输入就诊ID" clearable />
<el-form-item :label="t('emr.completeness.encounterId')">
<el-input v-model="checkForm.encounterId" :placeholder="t('emr.completeness.encounterIdPlaceholder')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" :loading="checkLoading" @click="handleCheck">
执行检查
{{ t('emr.completeness.executeCheck') }}
</el-button>
</el-form-item>
</el-form>
@@ -22,29 +22,29 @@
<el-row v-if="checkResult" :gutter="20" class="mb8">
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="检查项总数" :value="checkResult.totalItems" />
<el-statistic :title="t('emr.completeness.totalItems')" :value="checkResult.totalItems" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="必填项总数" :value="checkResult.requiredTotal" />
<el-statistic :title="t('emr.completeness.requiredTotal')" :value="checkResult.requiredTotal" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="必填项通过" :value="checkResult.requiredPassed" />
<el-statistic :title="t('emr.completeness.requiredPassed')" :value="checkResult.requiredPassed" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="是否完整" :value="checkResult.isComplete ? '是' : '否'" />
<el-statistic :title="t('emr.completeness.isComplete')" :value="checkResult.isComplete ? t('emr.completeness.yes') : t('emr.completeness.no')" />
</el-card>
</el-col>
</el-row>
<el-card v-if="checkResult && checkResult.requiredFailed > 0" shadow="hover" class="mb8">
<template #header>
<span style="color: #e6a23c;">不合格项提醒</span>
<span style="color: #e6a23c;">{{ t('emr.completeness.failedItemsAlert') }}</span>
</template>
<el-alert
v-for="item in failedItems"
@@ -59,31 +59,31 @@
<el-card shadow="hover">
<template #header>
<span>检查结果明细</span>
<span>{{ t('emr.completeness.resultDetail') }}</span>
</template>
<el-table v-loading="resultLoading" :data="resultList">
<el-table-column label="检查项" prop="checkItem" width="150" />
<el-table-column label="分类" prop="checkCategory" width="120">
<el-table-column :label="t('emr.completeness.checkItem')" prop="checkItem" width="150" />
<el-table-column :label="t('emr.completeness.category')" prop="checkCategory" width="120">
<template #default="scope">
<el-tag>{{ categoryMap[scope.row.checkCategory] || scope.row.checkCategory }}</el-tag>
</template>
</el-table-column>
<el-table-column label="是否必填" prop="isRequired" width="100">
<el-table-column :label="t('emr.completeness.required')" prop="isRequired" width="100">
<template #default="scope">
<el-tag :type="scope.row.isRequired ? 'danger' : 'info'">
{{ scope.row.isRequired ? '必填' : '选填' }}
{{ scope.row.isRequired ? t('emr.completeness.requiredYes') : t('emr.completeness.requiredNo') }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="检查结果" prop="checkResult" width="120">
<el-table-column :label="t('emr.completeness.checkResult')" prop="checkResult" width="120">
<template #default="scope">
<el-tag :type="scope.row.checkResult === 'PASS' ? 'success' : 'danger'">
{{ scope.row.checkResult === 'PASS' ? '通过' : '不合格' }}
{{ scope.row.checkResult === 'PASS' ? t('emr.completeness.pass') : t('emr.completeness.fail') }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="详情" prop="checkDetail" min-width="200" show-overflow-tooltip />
<el-table-column label="检查时间" prop="checkTime" width="180" />
<el-table-column :label="t('emr.completeness.detail')" prop="checkDetail" min-width="200" show-overflow-tooltip />
<el-table-column :label="t('emr.completeness.checkTime')" prop="checkTime" width="180" />
</el-table>
</el-card>
</div>
@@ -92,9 +92,12 @@
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { checkCompleteness, getCompletenessResults } from '@/api/emr'
import { ElMessage } from 'element-plus'
const { t } = useI18n()
const route = useRoute()
const checkLoading = ref(false)
const resultLoading = ref(false)
@@ -103,13 +106,13 @@ const resultList = ref([])
const checkForm = reactive({ emrId: '', encounterId: '' })
const categoryMap = {
basic: '基本信息',
examination: '检查',
diagnosis: '诊断',
treatment: '治疗',
signature: '签名'
}
const categoryMap = computed(() => ({
basic: t('emr.completeness.categoryBasic'),
examination: t('emr.completeness.categoryExamination'),
diagnosis: t('emr.completeness.categoryDiagnosis'),
treatment: t('emr.completeness.categoryTreatment'),
signature: t('emr.completeness.categorySignature')
}))
const failedItems = computed(() => {
if (!checkResult.value || !checkResult.value.checks) return []
@@ -118,11 +121,11 @@ const failedItems = computed(() => {
const handleCheck = async () => {
if (!checkForm.emrId) {
ElMessage.warning('请输入病历ID')
ElMessage.warning(t('emr.completeness.enterEmrId'))
return
}
if (!checkForm.encounterId) {
ElMessage.warning('请输入就诊ID')
ElMessage.warning(t('emr.completeness.enterEncounterId'))
return
}
checkLoading.value = true
@@ -130,9 +133,9 @@ const handleCheck = async () => {
const res = await checkCompleteness(checkForm.emrId, checkForm.encounterId)
checkResult.value = res.data || res
resultList.value = checkResult.value.checks || []
ElMessage.success(checkResult.value.isComplete ? '病历完整性检查通过' : '病历完整性检查未通过,存在不合格项')
ElMessage.success(checkResult.value.isComplete ? t('emr.completeness.checkPassed') : t('emr.completeness.checkFailed'))
} catch (e) {
ElMessage.error('执行检查失败')
ElMessage.error(t('emr.completeness.checkError'))
} finally {
checkLoading.value = false
}
@@ -145,7 +148,7 @@ const loadResults = async () => {
const res = await getCompletenessResults(checkForm.emrId)
resultList.value = res.data || res || []
} catch (e) {
ElMessage.error('获取检查结果失败')
ElMessage.error(t('emr.completeness.getResultError'))
} finally {
resultLoading.value = false
}

View File

@@ -2,15 +2,15 @@
<div class="app-container">
<el-card shadow="hover" class="mb8">
<template #header>
<span>结构化数据提取</span>
<span>{{ t('emr.warehouse.extractTitle') }}</span>
</template>
<el-form :inline="true" :model="extractForm">
<el-form-item label="病历ID">
<el-input v-model="extractForm.emrId" placeholder="请输入病历ID" clearable />
<el-form-item :label="t('emr.warehouse.emrId')">
<el-input v-model="extractForm.emrId" :placeholder="t('emr.warehouse.emrIdPlaceholder')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" :loading="extractLoading" @click="handleExtract">
提取数据
{{ t('emr.warehouse.extract') }}
</el-button>
</el-form-item>
</el-form>
@@ -18,45 +18,45 @@
<el-card shadow="hover" class="mb8">
<template #header>
<span>结构化数据查看</span>
<span>{{ t('emr.warehouse.viewTitle') }}</span>
</template>
<el-form :inline="true" :model="queryForm">
<el-form-item label="就诊ID">
<el-input v-model="queryForm.encounterId" placeholder="请输入就诊ID" clearable />
<el-form-item :label="t('emr.warehouse.encounterId')">
<el-input v-model="queryForm.encounterId" :placeholder="t('emr.warehouse.encounterIdPlaceholder')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" :loading="queryLoading" @click="handleQuery">
查询
{{ t('emr.warehouse.query') }}
</el-button>
</el-form-item>
</el-form>
<el-table v-loading="queryLoading" :data="structuredDataList" border stripe>
<el-table-column label="数据类型" prop="dataType" width="120">
<el-table-column :label="t('emr.warehouse.dataType')" prop="dataType" width="120">
<template #default="scope">
<el-tag>{{ dataTypeMap[scope.row.dataType] || scope.row.dataType }}</el-tag>
</template>
</el-table-column>
<el-table-column label="数据键" prop="dataKey" width="180" />
<el-table-column label="数据值" prop="dataValue" min-width="150" />
<el-table-column label="单位" prop="dataUnit" width="100" />
<el-table-column label="记录时间" prop="recordTime" width="180" />
<el-table-column :label="t('emr.warehouse.dataKey')" prop="dataKey" width="180" />
<el-table-column :label="t('emr.warehouse.dataValue')" prop="dataValue" min-width="150" />
<el-table-column :label="t('emr.warehouse.dataUnit')" prop="dataUnit" width="100" />
<el-table-column :label="t('emr.warehouse.recordTime')" prop="recordTime" width="180" />
</el-table>
</el-card>
<el-card shadow="hover" class="mb8">
<template #header>
<span>质控评分</span>
<span>{{ t('emr.warehouse.qualityScore') }}</span>
</template>
<el-form :inline="true" :model="qualityForm">
<el-form-item label="就诊ID">
<el-input v-model="qualityForm.encounterId" placeholder="请输入就诊ID" clearable />
<el-form-item :label="t('emr.warehouse.encounterId')">
<el-input v-model="qualityForm.encounterId" :placeholder="t('emr.warehouse.encounterIdPlaceholder')" clearable />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Check" :loading="qualityLoading" @click="handleCalculate">
计算评分
{{ t('emr.warehouse.calculate') }}
</el-button>
<el-button type="success" icon="Search" :loading="scoreLoading" @click="handleLoadScores">
查询历史
{{ t('emr.warehouse.queryHistory') }}
</el-button>
</el-form-item>
</el-form>
@@ -64,43 +64,46 @@
<el-row v-if="currentScore" :gutter="20" class="mb8">
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="总分" :value="currentScore.totalScore" />
<el-statistic :title="t('emr.warehouse.totalScore')" :value="currentScore.totalScore" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="完整性" :value="currentScore.completenessScore" />
<el-statistic :title="t('emr.warehouse.completenessScore')" :value="currentScore.completenessScore" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="及时性" :value="currentScore.timelinessScore" />
<el-statistic :title="t('emr.warehouse.timelinessScore')" :value="currentScore.timelinessScore" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="准确性" :value="currentScore.accuracyScore" />
<el-statistic :title="t('emr.warehouse.accuracyScore')" :value="currentScore.accuracyScore" />
</el-card>
</el-col>
</el-row>
<el-table v-if="scoreList.length > 0" v-loading="scoreLoading" :data="scoreList" border stripe>
<el-table-column label="评分时间" prop="checkTime" width="180" />
<el-table-column label="总分" prop="totalScore" width="100" />
<el-table-column label="完整性" prop="completenessScore" width="100" />
<el-table-column label="及时性" prop="timelinessScore" width="100" />
<el-table-column label="准确性" prop="accuracyScore" width="100" />
<el-table-column label="病历类型" prop="emrType" width="120" />
<el-table-column :label="t('emr.warehouse.scoreTime')" prop="checkTime" width="180" />
<el-table-column :label="t('emr.warehouse.totalScore')" prop="totalScore" width="100" />
<el-table-column :label="t('emr.warehouse.completenessScore')" prop="completenessScore" width="100" />
<el-table-column :label="t('emr.warehouse.timelinessScore')" prop="timelinessScore" width="100" />
<el-table-column :label="t('emr.warehouse.accuracyScore')" prop="accuracyScore" width="100" />
<el-table-column :label="t('emr.warehouse.emrType')" prop="emrType" width="120" />
</el-table>
</el-card>
</div>
</template>
<script setup>
import { ref, reactive } from 'vue'
import { ref, reactive, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { extractStructuredData, getStructuredData, calculateQualityScore, getQualityScores } from '@/api/emr'
import { ElMessage } from 'element-plus'
const { t } = useI18n()
const extractLoading = ref(false)
const queryLoading = ref(false)
const qualityLoading = ref(false)
@@ -114,25 +117,25 @@ const structuredDataList = ref([])
const currentScore = ref(null)
const scoreList = ref([])
const dataTypeMap = {
vital_signs: '生命体征',
lab_results: '检验结果',
diagnosis: '诊断',
medication: '用药'
}
const dataTypeMap = computed(() => ({
vital_signs: t('emr.warehouse.typeVitalSigns'),
lab_results: t('emr.warehouse.typeLabResults'),
diagnosis: t('emr.warehouse.typeDiagnosis'),
medication: t('emr.warehouse.typeMedication')
}))
const handleExtract = async () => {
if (!extractForm.emrId) {
ElMessage.warning('请输入病历ID')
ElMessage.warning(t('emr.warehouse.enterEmrId'))
return
}
extractLoading.value = true
try {
const res = await extractStructuredData(extractForm.emrId)
const data = res.data || res
ElMessage.success('提取完成,共 ' + (Array.isArray(data) ? data.length : 0) + ' 条数据')
ElMessage.success(t('emr.warehouse.extractSuccess', { count: Array.isArray(data) ? data.length : 0 }))
} catch (e) {
ElMessage.error('提取失败')
ElMessage.error(t('emr.warehouse.extractFailed'))
} finally {
extractLoading.value = false
}
@@ -140,7 +143,7 @@ const handleExtract = async () => {
const handleQuery = async () => {
if (!queryForm.encounterId) {
ElMessage.warning('请输入就诊ID')
ElMessage.warning(t('emr.warehouse.enterEncounterId'))
return
}
queryLoading.value = true
@@ -148,7 +151,7 @@ const handleQuery = async () => {
const res = await getStructuredData(queryForm.encounterId)
structuredDataList.value = res.data || res || []
} catch (e) {
ElMessage.error('查询失败')
ElMessage.error(t('emr.warehouse.queryFailed'))
} finally {
queryLoading.value = false
}
@@ -156,16 +159,16 @@ const handleQuery = async () => {
const handleCalculate = async () => {
if (!qualityForm.encounterId) {
ElMessage.warning('请输入就诊ID')
ElMessage.warning(t('emr.warehouse.enterEncounterId'))
return
}
qualityLoading.value = true
try {
const res = await calculateQualityScore(qualityForm.encounterId)
currentScore.value = res.data || res
ElMessage.success('评分计算完成')
ElMessage.success(t('emr.warehouse.calculateSuccess'))
} catch (e) {
ElMessage.error('计算失败')
ElMessage.error(t('emr.warehouse.calculateFailed'))
} finally {
qualityLoading.value = false
}
@@ -173,7 +176,7 @@ const handleCalculate = async () => {
const handleLoadScores = async () => {
if (!qualityForm.encounterId) {
ElMessage.warning('请输入就诊ID')
ElMessage.warning(t('emr.warehouse.enterEncounterId'))
return
}
scoreLoading.value = true
@@ -181,7 +184,7 @@ const handleLoadScores = async () => {
const res = await getQualityScores(qualityForm.encounterId)
scoreList.value = res.data || res || []
} catch (e) {
ElMessage.error('查询失败')
ElMessage.error(t('emr.warehouse.queryFailed'))
} finally {
scoreLoading.value = false
}

View File

@@ -1,30 +1,30 @@
<template>
<div style="padding:16px">
<div style="margin-bottom:16px">
<span style="font-size:18px;font-weight:bold">病历修改留痕</span>
<span style="font-size:18px;font-weight:bold">{{ t('emr.revision.title') }}</span>
</div>
<el-card shadow="never" style="margin-bottom:16px">
<el-form inline>
<el-form-item label="患者">
<el-input v-model="q.patientName" placeholder="患者姓名" clearable style="width:130px" />
<el-form-item :label="t('emr.revision.patient')">
<el-input v-model="q.patientName" :placeholder="t('emr.revision.patientName')" clearable style="width:130px" />
</el-form-item>
<el-form-item label="医生">
<el-input v-model="q.doctorName" placeholder="医生姓名" clearable style="width:130px" />
<el-form-item :label="t('emr.revision.doctor')">
<el-input v-model="q.doctorName" :placeholder="t('emr.revision.doctorName')" clearable style="width:130px" />
</el-form-item>
<el-form-item label="操作人">
<el-input v-model="q.operatorName" placeholder="操作人" clearable style="width:120px" />
<el-form-item :label="t('emr.revision.operator')">
<el-input v-model="q.operatorName" :placeholder="t('emr.revision.operatorName')" clearable style="width:120px" />
</el-form-item>
<el-form-item label="病历类型">
<el-select v-model="q.emrType" placeholder="全部" clearable style="width:130px">
<el-option label="入院记录" value="ADMISSION" />
<el-option label="首次病程" value="FIRST_COURSE" />
<el-option label="日常病程" value="DAILY_COURSE" />
<el-option label="出院记录" value="DISCHARGE" />
<el-form-item :label="t('emr.revision.emrType')">
<el-select v-model="q.emrType" :placeholder="t('emr.revision.all')" clearable style="width:130px">
<el-option :label="t('emr.revision.emrTypeAdmission')" value="ADMISSION" />
<el-option :label="t('emr.revision.emrTypeFirstCourse')" value="FIRST_COURSE" />
<el-option :label="t('emr.revision.emrTypeDailyCourse')" value="DAILY_COURSE" />
<el-option :label="t('emr.revision.emrTypeDischarge')" value="DISCHARGE" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">搜索</el-button>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleQuery">{{ t('emr.revision.search') }}</el-button>
<el-button @click="resetQuery">{{ t('emr.revision.reset') }}</el-button>
</el-form-item>
</el-form>
</el-card>
@@ -36,10 +36,10 @@
default-expand-all
:tree-props="{ children: 'revisions' }"
>
<el-table-column prop="emrTitle" label="病历标题" min-width="200">
<el-table-column prop="emrTitle" :label="t('emr.revision.emrTitle')" min-width="200">
<template #default="{row}">
<template v-if="row.isGroup">
<span style="font-weight:bold">{{ row.emrTitle || '病历 #' + row.emrId }}</span>
<span style="font-weight:bold">{{ row.emrTitle || t('emr.revision.emrPrefix') + row.emrId }}</span>
<el-tag size="small" style="margin-left:8px">{{ row.emrType }}</el-tag>
</template>
<template v-else>
@@ -47,7 +47,7 @@
</template>
</template>
</el-table-column>
<el-table-column prop="patientName" label="患者" width="100">
<el-table-column prop="patientName" :label="t('emr.revision.patient')" width="100">
<template #default="{row}">
<template v-if="row.isGroup">
{{ row.patientName || '-' }}
@@ -55,22 +55,22 @@
</template>
</template>
</el-table-column>
<el-table-column prop="doctorName" label="主治医生" width="100">
<el-table-column prop="doctorName" :label="t('emr.revision.attendingDoctor')" width="100">
<template #default="{row}">
<template v-if="row.isGroup">{{ row.doctorName || '-' }}</template>
</template>
</el-table-column>
<el-table-column prop="departmentName" label="科室" width="100">
<el-table-column prop="departmentName" :label="t('emr.revision.department')" width="100">
<template #default="{row}">
<template v-if="row.isGroup">{{ row.departmentName || '-' }}</template>
</template>
</el-table-column>
<el-table-column prop="encounterNo" label="就诊号" width="120">
<el-table-column prop="encounterNo" :label="t('emr.revision.encounterNo')" width="120">
<template #default="{row}">
<template v-if="row.isGroup">{{ row.encounterNo || '-' }}</template>
</template>
</el-table-column>
<el-table-column prop="operationType" label="操作类型" width="100">
<el-table-column prop="operationType" :label="t('emr.revision.operationType')" width="100">
<template #default="{row}">
<template v-if="!row.isGroup">
<el-tag :type="opTypeMap[row.operationType]?.type || 'info'" size="small">
@@ -79,25 +79,25 @@
</template>
</template>
</el-table-column>
<el-table-column prop="operatorName" label="操作人" width="90">
<el-table-column prop="operatorName" :label="t('emr.revision.operator')" width="90">
<template #default="{row}">
<template v-if="!row.isGroup">{{ row.operatorName }}</template>
</template>
</el-table-column>
<el-table-column prop="diffContent" label="变更内容" min-width="200" show-overflow-tooltip>
<el-table-column prop="diffContent" :label="t('emr.revision.changeContent')" min-width="200" show-overflow-tooltip>
<template #default="{row}">
<template v-if="!row.isGroup">{{ row.diffContent }}</template>
</template>
</el-table-column>
<el-table-column prop="createTime" label="时间" width="170">
<el-table-column prop="createTime" :label="t('emr.revision.time')" width="170">
<template #default="{row}">
<template v-if="!row.isGroup">{{ row.createTime }}</template>
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<el-table-column :label="t('emr.revision.operation')" width="80">
<template #default="{row}">
<template v-if="!row.isGroup">
<el-button type="primary" link size="small" @click="viewDetail(row)">详情</el-button>
<el-button type="primary" link size="small" @click="viewDetail(row)">{{ t('emr.revision.detail') }}</el-button>
</template>
</template>
</el-table-column>
@@ -111,19 +111,19 @@
@size-change="loadData"
@current-change="loadData"
/>
<el-dialog v-model="detailVisible" title="修订详情" width="700px">
<el-dialog v-model="detailVisible" :title="t('emr.revision.revisionDetail')" width="700px">
<el-descriptions :column="2" border>
<el-descriptions-item label="版本">V{{ detail.revisionNumber }}</el-descriptions-item>
<el-descriptions-item label="操作人">{{ detail.operatorName }}</el-descriptions-item>
<el-descriptions-item label="操作类型">{{ detail.operationType }}</el-descriptions-item>
<el-descriptions-item label="时间">{{ detail.createTime }}</el-descriptions-item>
<el-descriptions-item :label="t('emr.revision.version')">V{{ detail.revisionNumber }}</el-descriptions-item>
<el-descriptions-item :label="t('emr.revision.operator')">{{ detail.operatorName }}</el-descriptions-item>
<el-descriptions-item :label="t('emr.revision.operationType')">{{ detail.operationType }}</el-descriptions-item>
<el-descriptions-item :label="t('emr.revision.time')">{{ detail.createTime }}</el-descriptions-item>
</el-descriptions>
<div style="margin-top:12px">
<div style="font-weight:bold;margin-bottom:8px">变更内容:</div>
<div style="font-weight:bold;margin-bottom:8px">{{ t('emr.revision.changeContent') }}:</div>
<pre style="background:#f5f7fa;padding:12px;border-radius:4px;max-height:300px;overflow:auto">{{ detail.diffContent }}</pre>
</div>
<div style="margin-top:12px">
<div style="font-weight:bold;margin-bottom:8px">内容快照:</div>
<div style="font-weight:bold;margin-bottom:8px">{{ t('emr.revision.contentSnapshot') }}:</div>
<pre style="background:#f5f7fa;padding:12px;border-radius:4px;max-height:300px;overflow:auto">{{ detail.snapshotContent }}</pre>
</div>
</el-dialog>
@@ -132,9 +132,12 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { getRevisionPage } from './api'
import { ElMessage } from 'element-plus'
const { t } = useI18n()
const route = useRoute()
const loading = ref(false)
const rawData = ref([])
@@ -143,12 +146,12 @@ const q = ref({ pageNo: 1, pageSize: 10, patientName: '', doctorName: '', operat
const detailVisible = ref(false)
const detail = ref({})
const opTypeMap = {
CREATE: { label: '创建', type: 'success' },
EDIT: { label: '编辑', type: 'warning' },
APPROVE: { label: '审批', type: '' },
SIGN: { label: '签名', type: 'info' }
}
const opTypeMap = computed(() => ({
CREATE: { label: t('emr.revision.opCreate'), type: 'success' },
EDIT: { label: t('emr.revision.opEdit'), type: 'warning' },
APPROVE: { label: t('emr.revision.opApprove'), type: '' },
SIGN: { label: t('emr.revision.opSign'), type: 'info' }
}))
const groupedData = computed(() => {
const map = new Map()
@@ -186,7 +189,7 @@ const loadData = async () => {
rawData.value = r.data?.records || []
total.value = r.data?.total || 0
} catch {
ElMessage.error('加载失败')
ElMessage.error(t('emr.revision.loadFailed'))
} finally {
loading.value = false
}

View File

@@ -1,29 +1,29 @@
<template>
<div style="padding:16px">
<div style="margin-bottom:16px;display:flex;justify-content:space-between;align-items:center">
<span style="font-size:18px;font-weight:bold">EMR数据同步</span>
<span style="font-size:18px;font-weight:bold">{{ t('emr.sync.title') }}</span>
</div>
<el-card shadow="hover" style="margin-bottom:16px">
<template #header>
<span>同步统计</span>
<span>{{ t('emr.sync.stats') }}</span>
</template>
<el-row :gutter="20">
<el-col :span="8">
<el-statistic title="病历总数" :value="stats.emrCount||0" />
<el-statistic :title="t('emr.sync.emrCount')" :value="stats.emrCount||0" />
</el-col>
<el-col :span="8">
<el-statistic title="修订历史" :value="stats.revisionCount||0" />
<el-statistic :title="t('emr.sync.revisionCount')" :value="stats.revisionCount||0" />
</el-col>
<el-col :span="8">
<el-statistic title="搜索索引" :value="stats.searchIndexCount||0" />
<el-statistic :title="t('emr.sync.searchIndexCount')" :value="stats.searchIndexCount||0" />
</el-col>
</el-row>
</el-card>
<el-card shadow="hover">
<template #header>
<span>数据同步操作</span>
<span>{{ t('emr.sync.operations') }}</span>
</template>
<el-alert
type="warning"
@@ -31,7 +31,7 @@
style="margin-bottom:16px"
>
<template #title>
同步操作将清空现有的修订历史和搜索索引数据然后从门诊/住院病历表(doc_emr)重新生成
{{ t('emr.sync.alertMessage') }}
</template>
</el-alert>
<el-button
@@ -39,10 +39,10 @@
:loading="syncing"
@click="handleSync"
>
{{ syncing ? '同步中...' : '开始同步' }}
{{ syncing ? t('emr.sync.syncing') : t('emr.sync.startSync') }}
</el-button>
<el-button @click="loadStats">
刷新统计
{{ t('emr.sync.refreshStats') }}
</el-button>
</el-card>
</div>
@@ -51,8 +51,11 @@
<script setup>
import {ref, onMounted} from 'vue'
import {ElMessage, ElMessageBox} from 'element-plus'
import {useI18n} from 'vue-i18n'
import request from '@/utils/request'
const {t} = useI18n()
const syncing = ref(false)
const stats = ref({})
@@ -64,17 +67,17 @@ const loadStats = async () => {
const handleSync = async () => {
try {
await ElMessageBox.confirm(
'确定要同步EMR数据吗这将清空现有的修订历史和搜索索引然后从病历表重新生成。',
'确认同步',
t('emr.sync.confirmMessage'),
t('emr.sync.confirmTitle'),
{type: 'warning'}
)
syncing.value = true
const res = await request({url: '/emr-sync/sync', method: 'post'})
ElMessage.success(res.data || '同步完成')
ElMessage.success(res.data || t('emr.sync.syncComplete'))
loadStats()
} catch (e) {
if (e !== 'cancel') {
ElMessage.error('同步失败: ' + (e.message || '未知错误'))
ElMessage.error(t('emr.sync.syncFailed') + ': ' + (e.message || t('emr.sync.unknownError')))
}
} finally {
syncing.value = false

View File

@@ -3,61 +3,61 @@
<el-row :gutter="20" class="mb8">
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="待完成" :value="stats.pendingCount" />
<el-statistic :title="t('emr.timeliness.stats.pending')" :value="stats.pendingCount" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="已完成" :value="stats.completedCount" />
<el-statistic :title="t('emr.timeliness.stats.completed')" :value="stats.completedCount" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="超时" :value="stats.overdueCount" />
<el-statistic :title="t('emr.timeliness.stats.overdue')" :value="stats.overdueCount" />
</el-card>
</el-col>
<el-col :span="6">
<el-card shadow="hover">
<el-statistic title="完成率" :value="stats.completionRate" suffix="%" />
<el-statistic :title="t('emr.timeliness.stats.rate')" :value="stats.completionRate" suffix="%" />
</el-card>
</el-col>
</el-row>
<el-form :model="queryParams" :inline="true" class="mt8">
<el-form-item label="科室">
<el-input v-model="queryParams.departmentName" placeholder="科室" clearable />
<el-form-item :label="t('emr.timeliness.department')">
<el-input v-model="queryParams.departmentName" :placeholder="t('emr.timeliness.department')" clearable />
</el-form-item>
<el-form-item label="病历类型">
<el-select v-model="queryParams.emrType" placeholder="全部" clearable>
<el-option label="入院记录" value="ADMISSION" />
<el-option label="首次病程" value="FIRST_COURSE" />
<el-option label="日常病程" value="DAILY_COURSE" />
<el-option label="出院记录" value="DISCHARGE" />
<el-form-item :label="t('emr.timeliness.emrTypeLabel')">
<el-select v-model="queryParams.emrType" :placeholder="t('emr.timeliness.all')" clearable>
<el-option :label="t('emr.timeliness.emrType.admission')" value="ADMISSION" />
<el-option :label="t('emr.timeliness.emrType.firstCourse')" value="FIRST_COURSE" />
<el-option :label="t('emr.timeliness.emrType.dailyCourse')" value="DAILY_COURSE" />
<el-option :label="t('emr.timeliness.emrType.discharge')" value="DISCHARGE" />
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-select v-model="queryParams.status" placeholder="全部" clearable>
<el-option label="待完成" value="PENDING" />
<el-option label="已完成" value="COMPLETED" />
<el-option label="超时" value="OVERDUE" />
<el-form-item :label="t('emr.timeliness.statusLabel')">
<el-select v-model="queryParams.status" :placeholder="t('emr.timeliness.all')" clearable>
<el-option :label="t('emr.timeliness.status.pending')" value="PENDING" />
<el-option :label="t('emr.timeliness.status.completed')" value="COMPLETED" />
<el-option :label="t('emr.timeliness.status.overdue')" value="OVERDUE" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button type="primary" icon="Search" @click="handleQuery">{{ t('emr.timeliness.search') }}</el-button>
<el-button icon="Refresh" @click="resetQuery">{{ t('emr.timeliness.reset') }}</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="dataList">
<el-table-column label="科室" prop="departmentName" width="120" />
<el-table-column label="医生" prop="doctorName" width="100" />
<el-table-column label="病历类型" prop="emrType" width="120">
<el-table-column :label="t('emr.timeliness.department')" prop="departmentName" width="120" />
<el-table-column :label="t('emr.timeliness.doctor')" prop="doctorName" width="100" />
<el-table-column :label="t('emr.timeliness.emrTypeLabel')" prop="emrType" width="120">
<template #default="scope">
<el-tag>{{ emrTypeMap[scope.row.emrType] || scope.row.emrType }}</el-tag>
</template>
</el-table-column>
<el-table-column label="要求时限(h)" prop="requiredHours" width="110" />
<el-table-column label="截止时间" prop="deadlineTime" width="180" />
<el-table-column label="实际完成时间" prop="actualCompleteTime" width="180" />
<el-table-column label="状态" prop="status" width="100">
<el-table-column :label="t('emr.timeliness.requiredHours')" prop="requiredHours" width="110" />
<el-table-column :label="t('emr.timeliness.deadline')" prop="deadlineTime" width="180" />
<el-table-column :label="t('emr.timeliness.actualCompleteTime')" prop="actualCompleteTime" width="180" />
<el-table-column :label="t('emr.timeliness.statusLabel')" prop="status" width="100">
<template #default="scope">
<el-tag :type="statusMap[scope.row.status]?.type">
{{ statusMap[scope.row.status]?.label || scope.row.status }}
@@ -76,10 +76,13 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, computed, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
import { getTimelinessAlerts, getTimelinessStatistics } from '@/api/emr'
const { t } = useI18n()
const route = useRoute()
const loading = ref(false)
const dataList = ref([])
@@ -93,12 +96,17 @@ const queryParams = reactive({
pageSize: 10
})
const emrTypeMap = { ADMISSION: '入院记录', FIRST_COURSE: '首次病程', DAILY_COURSE: '日常病程', DISCHARGE: '出院记录' }
const statusMap = {
PENDING: { label: '待完成', type: 'info' },
COMPLETED: { label: '已完成', type: 'success' },
OVERDUE: { label: '超时', type: 'danger' }
}
const emrTypeMap = computed(() => ({
ADMISSION: t('emr.timeliness.emrType.admission'),
FIRST_COURSE: t('emr.timeliness.emrType.firstCourse'),
DAILY_COURSE: t('emr.timeliness.emrType.dailyCourse'),
DISCHARGE: t('emr.timeliness.emrType.discharge')
}))
const statusMap = computed(() => ({
PENDING: { label: t('emr.timeliness.status.pending'), type: 'info' },
COMPLETED: { label: t('emr.timeliness.status.completed'), type: 'success' },
OVERDUE: { label: t('emr.timeliness.status.overdue'), type: 'danger' }
}))
const getList = async () => {
loading.value = true

View File

@@ -1,4 +1,4 @@
<template>
<template>
<div class="app-container">
<!-- 查询表单 -->
<el-form
@@ -9,24 +9,24 @@
class="query-form"
>
<el-form-item
label="手术室名称"
:label="$t('operatingroom.roomName')"
prop="name"
>
<el-input
v-model="queryParams.name"
placeholder="请输入手术室名称"
:placeholder="$t('operatingroom.placeholderRoomName')"
clearable
style="width: 200px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item
label="状态"
:label="$t('operatingroom.status')"
prop="statusEnum"
>
<el-select
v-model="queryParams.statusEnum"
placeholder="请选择状态"
:placeholder="$t('operatingroom.placeholderStatus')"
clearable
style="width: 150px"
>
@@ -44,13 +44,13 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('operatingroom.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ $t('operatingroom.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -67,7 +67,7 @@
icon="Plus"
@click="handleAdd"
>
新增手术室
{{ $t('operatingroom.addRoom') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -78,7 +78,7 @@
:disabled="multiple"
@click="handleEnable(ids)"
>
批量启用
{{ $t('operatingroom.batchEnable') }}
</el-button>
</el-col>
<el-col :span="1.5">
@@ -89,7 +89,7 @@
:disabled="multiple"
@click="handleDisable(ids)"
>
批量停用
{{ $t('operatingroom.batchDisable') }}
</el-button>
</el-col>
<right-toolbar
@@ -112,78 +112,78 @@
align="center"
/>
<vxe-column
title="序号"
:title="$t('operatingroom.seq')"
type="seq"
align="center"
width="60"
/>
<vxe-column
title="房间号"
:title="$t('operatingroom.roomNo')"
align="center"
field="busNo"
width="120"
show-overflow="title"
/>
<vxe-column
title="手术室名称"
:title="$t('operatingroom.roomName')"
align="center"
field="name"
min-width="150"
show-overflow="title"
/>
<vxe-column
title="类型"
:title="$t('operatingroom.type')"
align="center"
field="roomTypeEnum_dictText"
width="100"
/>
<vxe-column
title="所属科室"
:title="$t('operatingroom.department')"
align="center"
field="organizationName"
width="120"
show-overflow="title"
/>
<vxe-column
title="位置描述"
:title="$t('operatingroom.locationDesc')"
align="center"
field="locationDescription"
min-width="150"
show-overflow="title"
/>
<vxe-column
title="设备配置"
:title="$t('operatingroom.equipmentConfig')"
align="center"
field="equipmentConfig"
min-width="200"
show-overflow="title"
/>
<vxe-column
title="容纳人数"
:title="$t('operatingroom.capacity')"
align="center"
field="capacity"
width="100"
/>
<vxe-column
title="状态"
:title="$t('operatingroom.status')"
align="center"
field="statusEnum"
width="100"
>
<template #default="scope">
<el-tag :type="getStatusType(scope.row.statusEnum)">
{{ scope.row.statusEnum === 1 ? '启用' : '停用' }}
{{ scope.row.statusEnum === 1 ? $t('operatingroom.enabled') : $t('operatingroom.disabled') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
title="显示顺序"
:title="$t('operatingroom.displayOrder')"
align="center"
field="displayOrder"
width="100"
/>
<vxe-column
title="操作"
:title="$t('operatingroom.operations')"
align="center"
width="220"
fixed="right"
@@ -195,7 +195,7 @@
icon="Edit"
@click="handleEdit(scope.row)"
>
编辑
{{ $t('operatingroom.edit') }}
</el-button>
<el-button
link
@@ -203,7 +203,7 @@
icon="View"
@click="handleView(scope.row)"
>
查看
{{ $t('operatingroom.view') }}
</el-button>
<el-button
v-if="scope.row.statusEnum === 1"
@@ -212,7 +212,7 @@
icon="VideoPause"
@click="handleDisable([scope.row.id])"
>
停用
{{ $t('operatingroom.disable') }}
</el-button>
<el-button
v-else
@@ -221,7 +221,7 @@
icon="VideoPlay"
@click="handleEnable([scope.row.id])"
>
启用
{{ $t('operatingroom.enable') }}
</el-button>
</template>
</vxe-column>
@@ -252,23 +252,23 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="房间号"
:label="$t('operatingroom.roomNo')"
prop="busNo"
>
<el-input
v-model="form.busNo"
placeholder="请输入房间号"
:placeholder="$t('operatingroom.placeholderRoomNo')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="手术室名称"
:label="$t('operatingroom.roomName')"
prop="name"
>
<el-input
v-model="form.name"
placeholder="请输入手术室名称"
:placeholder="$t('operatingroom.placeholderRoomName')"
/>
</el-form-item>
</el-col>
@@ -277,7 +277,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="容纳人数"
:label="$t('operatingroom.capacity')"
prop="capacity"
>
<el-input-number
@@ -285,7 +285,7 @@
:min="1"
:max="20"
style="width: 100%"
placeholder="请输入容纳人数"
:placeholder="$t('operatingroom.placeholderCapacity')"
/>
</el-form-item>
</el-col>
@@ -294,12 +294,12 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="类型"
:label="$t('operatingroom.type')"
prop="roomTypeEnum"
>
<el-select
v-model="form.roomTypeEnum"
placeholder="请选择类型"
:placeholder="$t('operatingroom.placeholderType')"
style="width: 100%"
>
<el-option
@@ -313,14 +313,14 @@
</el-col>
<el-col :span="12">
<el-form-item
label="所属科室"
:label="$t('operatingroom.department')"
prop="organizationId"
>
<el-select
v-model="form.organizationId"
filterable
clearable
placeholder="请选择所属科室"
:placeholder="$t('operatingroom.placeholderDepartment')"
:loading="deptLoading"
style="width: 100%"
>
@@ -338,12 +338,12 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="状态"
:label="$t('operatingroom.status')"
prop="statusEnum"
>
<el-select
v-model="form.statusEnum"
placeholder="请选择状态"
:placeholder="$t('operatingroom.placeholderStatus')"
style="width: 100%"
>
<el-option
@@ -360,7 +360,7 @@
<el-row :gutter="20">
<el-col :span="12">
<el-form-item
label="显示顺序"
:label="$t('operatingroom.displayOrder')"
prop="displayOrder"
>
<el-input-number
@@ -368,44 +368,44 @@
:min="0"
:max="999"
style="width: 100%"
placeholder="请输入显示顺序"
:placeholder="$t('operatingroom.placeholderDisplayOrder')"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item
label="位置描述"
:label="$t('operatingroom.locationDesc')"
prop="locationDescription"
>
<el-input
v-model="form.locationDescription"
type="textarea"
placeholder="请输入位置描述"
:placeholder="$t('operatingroom.placeholderLocationDesc')"
:rows="2"
/>
</el-form-item>
<el-form-item
label="设备配置"
:label="$t('operatingroom.equipmentConfig')"
prop="equipmentConfig"
>
<el-input
v-model="form.equipmentConfig"
type="textarea"
placeholder="请输入设备配置,如:麻醉机、监护仪、手术台等"
:placeholder="$t('operatingroom.placeholderEquipmentConfig')"
:rows="3"
/>
</el-form-item>
<el-form-item
label="备注"
:label="$t('operatingroom.remark')"
prop="remark"
>
<el-input
v-model="form.remark"
type="textarea"
placeholder="请输入备注"
:placeholder="$t('operatingroom.placeholderRemark')"
:rows="2"
/>
</el-form-item>
@@ -416,10 +416,10 @@
type="primary"
@click="submitForm"
>
{{ $t('operatingroom.confirm') }}
</el-button>
<el-button @click="cancel">
{{ $t('operatingroom.cancel') }}
</el-button>
</div>
</template>
@@ -428,7 +428,7 @@
<!-- 查看手术室详情对话框 -->
<el-dialog
v-model="viewOpen"
title="手术室详情"
:title="$t('operatingroom.roomDetail')"
width="700px"
teleported
>
@@ -436,40 +436,40 @@
:column="2"
border
>
<el-descriptions-item label="手术室编码">
<el-descriptions-item :label="$t('operatingroom.roomCode')">
{{ viewData.busNo }}
</el-descriptions-item>
<el-descriptions-item label="手术室名称">
<el-descriptions-item :label="$t('operatingroom.roomName')">
{{ viewData.name }}
</el-descriptions-item>
<el-descriptions-item label="类型">
<el-descriptions-item :label="$t('operatingroom.type')">
{{ viewData.roomTypeEnum_dictText }}
</el-descriptions-item>
<el-descriptions-item label="位置描述">
<el-descriptions-item :label="$t('operatingroom.locationDesc')">
{{ viewData.locationDescription }}
</el-descriptions-item>
<el-descriptions-item label="容纳人数">
<el-descriptions-item :label="$t('operatingroom.capacity')">
{{ viewData.capacity }}
</el-descriptions-item>
<el-descriptions-item label="所属科室">
<el-descriptions-item :label="$t('operatingroom.department')">
{{ viewData.organizationName }}
</el-descriptions-item>
<el-descriptions-item label="显示顺序">
<el-descriptions-item :label="$t('operatingroom.displayOrder')">
{{ viewData.displayOrder }}
</el-descriptions-item>
<el-descriptions-item
label="设备配置"
:label="$t('operatingroom.equipmentConfig')"
:span="2"
>
{{ viewData.equipmentConfig }}
</el-descriptions-item>
<el-descriptions-item label="状态">
<el-descriptions-item :label="$t('operatingroom.status')">
<el-tag :type="getStatusType(viewData.statusEnum)">
{{ viewData.statusEnum === 1 ? '启用' : '停用' }}
{{ viewData.statusEnum === 1 ? $t('operatingroom.enabled') : $t('operatingroom.disabled') }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item
label="备注"
:label="$t('operatingroom.remark')"
:span="2"
>
{{ viewData.remark }}
@@ -483,6 +483,9 @@
import { listOperatingRoom, getOperatingRoom, addOperatingRoom, updateOperatingRoom, deleteOperatingRoom, enableOperatingRoom, disableOperatingRoom } from '@/api/operatingroom'
import { deptTreeSelect } from '@/api/system/user'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const { proxy } = getCurrentInstance()
const { operating_room_type } = proxy.useDict('operating_room_type')
@@ -543,20 +546,20 @@ const viewData = ref({})
const roomTypeOptions = operating_room_type
const statusOptions = ref([
{ value: 1, label: '启用' },
{ value: 0, label: '停用' }
const statusOptions = computed(() => [
{ value: 1, label: t('operatingroom.enabled') },
{ value: 0, label: t('operatingroom.disabled') }
])
const rules = ref({
busNo: [{ required: true, message: '房间号不能为空', trigger: 'blur' }],
name: [{ required: true, message: '手术室名称不能为空', trigger: 'blur' }],
const rules = computed(() => ({
busNo: [{ required: true, message: t('operatingroom.ruleRoomNoRequired'), trigger: 'blur' }],
name: [{ required: true, message: t('operatingroom.ruleRoomNameRequired'), trigger: 'blur' }],
capacity: [
{ required: true, message: '容纳人数不能为空', trigger: 'blur' },
{ type: 'number', message: '容纳人数必须为数字', trigger: 'blur' }
{ required: true, message: t('operatingroom.ruleCapacityRequired'), trigger: 'blur' },
{ type: 'number', message: t('operatingroom.ruleCapacityNumber'), trigger: 'blur' }
],
organizationId: [{ required: true, message: '请选择所属科室', trigger: 'change' }]
})
organizationId: [{ required: true, message: t('operatingroom.ruleDepartmentRequired'), trigger: 'change' }]
}))
/** 查询手术室列表 */
function getList() {
@@ -567,11 +570,11 @@ function getList() {
operatingRoomList.value = res.data.records || []
total.value = res.data.total || 0
} else {
proxy.$modal.msgError(res.msg || '获取手术室列表失败')
proxy.$modal.msgError(res.msg || t('operatingroom.getListFailed'))
}
}).catch(error => {
console.error('获取手术室列表失败:', error)
proxy.$modal.msgError('获取手术室列表失败,请稍后重试')
proxy.$modal.msgError(t('operatingroom.getListFailedRetry'))
}).finally(() => {
loading.value = false
})
@@ -657,7 +660,7 @@ function handleSelectionChange(selection) {
function handleAdd() {
reset()
open.value = true
title.value = '新增手术室'
title.value = t('operatingroom.addRoomTitle')
}
/** 修改按钮操作 */
@@ -668,7 +671,7 @@ function handleEdit(row) {
if (res.code === 200) {
form.value = res.data
open.value = true
title.value = '编辑手术室'
title.value = t('operatingroom.editRoomTitle')
}
})
}
@@ -700,32 +703,32 @@ function submitForm() {
if (form.value.id) {
updateOperatingRoom(submitData).then(res => {
if (res.code === 200) {
proxy.$modal.msgSuccess('修改成功')
proxy.$modal.msgSuccess(t('operatingroom.modifySuccess'))
open.value = false
getList()
} else {
proxy.$modal.msgError(res.msg || '修改失败')
proxy.$modal.msgError(res.msg || t('operatingroom.modifyFailed'))
}
}).catch(error => {
console.error('修改手术室失败:', error)
proxy.$modal.msgError('修改失败,请稍后重试')
proxy.$modal.msgError(t('operatingroom.modifyFailedRetry'))
})
} else {
addOperatingRoom(submitData).then(res => {
if (res.code === 200) {
proxy.$modal.msgSuccess('新增成功')
proxy.$modal.msgSuccess(t('operatingroom.addSuccess'))
open.value = false
getList()
} else {
proxy.$modal.msgError(res.msg || '新增失败')
proxy.$modal.msgError(res.msg || t('operatingroom.addFailed'))
}
}).catch(error => {
console.error('新增手术室失败:', error)
proxy.$modal.msgError('新增失败,请稍后重试')
proxy.$modal.msgError(t('operatingroom.addFailedRetry'))
})
}
} else {
proxy.$modal.msgError('请完善表单信息')
proxy.$modal.msgError(t('operatingroom.completeForm'))
}
})
}
@@ -733,13 +736,13 @@ function submitForm() {
/** 启用按钮操作 */
function handleEnable(ids) {
proxy.$modal
.confirm('是否确认启用选中的手术室?')
.confirm(t('operatingroom.confirmEnable'))
.then(function () {
return enableOperatingRoom(ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('启用成功')
proxy.$modal.msgSuccess(t('operatingroom.enableSuccess'))
})
.catch(() => {})
}
@@ -747,13 +750,13 @@ function handleEnable(ids) {
/** 停用按钮操作 */
function handleDisable(ids) {
proxy.$modal
.confirm('是否确认停用选中的手术室?')
.confirm(t('operatingroom.confirmDisable'))
.then(function () {
return disableOperatingRoom(ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('停用成功')
proxy.$modal.msgSuccess(t('operatingroom.disableSuccess'))
})
.catch(() => {})
}

View File

@@ -10,7 +10,7 @@
<div class="stat-value">
{{ stats.total || 0 }}
</div><div class="stat-label">
总讨论数
{{ $t('preopmanage.totalDiscussions') }}
</div>
</div>
</el-col>
@@ -19,7 +19,7 @@
<div class="stat-value draft">
{{ stats.draft || 0 }}
</div><div class="stat-label">
草稿
{{ $t('preopmanage.draft') }}
</div>
</div>
</el-col>
@@ -28,7 +28,7 @@
<div class="stat-value warning">
{{ stats.pending || 0 }}
</div><div class="stat-label">
待签名
{{ $t('preopmanage.pendingSignature') }}
</div>
</div>
</el-col>
@@ -37,7 +37,7 @@
<div class="stat-value info">
{{ stats.reviewing || 0 }}
</div><div class="stat-label">
待审核
{{ $t('preopmanage.pendingReview') }}
</div>
</div>
</el-col>
@@ -46,7 +46,7 @@
<div class="stat-value success">
{{ stats.completed || 0 }}
</div><div class="stat-label">
已完成
{{ $t('preopmanage.completed') }}
</div>
</div>
</el-col>
@@ -55,7 +55,7 @@
<div class="stat-value danger">
{{ stats.rejected || 0 }}
</div><div class="stat-label">
已驳回
{{ $t('preopmanage.rejected') }}
</div>
</div>
</el-col>
@@ -67,13 +67,13 @@
>
<template #header>
<div class="card-header">
<span class="card-title">术前讨论管理</span>
<span class="card-title">{{ $t('preopmanage.discussionManage') }}</span>
<el-button
type="primary"
icon="Plus"
@click="handleAdd"
>
新建讨论
{{ $t('preopmanage.newDiscussion') }}
</el-button>
</div>
</template>
@@ -82,61 +82,61 @@
:model="queryParams"
label-width="80px"
>
<el-form-item label="患者">
<el-form-item :label="$t('preopmanage.patient')">
<el-input
v-model="queryParams.patientName"
placeholder="患者姓名"
:placeholder="$t('preopmanage.patientName')"
clearable
style="width: 140px"
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="手术级别">
<el-form-item :label="$t('preopmanage.surgeryLevel')">
<el-select
v-model="queryParams.surgeryLevel"
placeholder="全部"
:placeholder="$t('preopmanage.all')"
clearable
style="width: 110px"
>
<el-option
label="一级"
:label="$t('preopmanage.level1')"
:value="1"
/><el-option
label="二级"
:label="$t('preopmanage.level2')"
:value="2"
/>
<el-option
label="三级"
:label="$t('preopmanage.level3')"
:value="3"
/><el-option
label="四级"
:label="$t('preopmanage.level4')"
:value="4"
/>
</el-select>
</el-form-item>
<el-form-item label="状态">
<el-form-item :label="$t('preopmanage.status')">
<el-select
v-model="queryParams.status"
placeholder="全部"
:placeholder="$t('preopmanage.all')"
clearable
style="width: 110px"
>
<el-option
label="草稿"
:label="$t('preopmanage.statusDraft')"
:value="0"
/><el-option
label="待签名"
:label="$t('preopmanage.statusPendingSignature')"
:value="1"
/>
<el-option
label="待审核"
:label="$t('preopmanage.statusPendingReview')"
:value="2"
/><el-option
label="已完成"
:label="$t('preopmanage.statusCompleted')"
:value="3"
/>
<el-option
label="已驳回"
:label="$t('preopmanage.statusRejected')"
:value="5"
/>
</el-select>
@@ -147,13 +147,13 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ $t('preopmanage.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ $t('preopmanage.reset') }}
</el-button>
</el-form-item>
</el-form>
@@ -166,23 +166,23 @@
>
<vxe-column
type="seq"
title="序号"
:title="$t('preopmanage.seq')"
width="60"
/>
<vxe-column
field="patientName"
title="患者"
:title="$t('preopmanage.patient')"
width="90"
/>
<vxe-column
field="surgeryName"
title="手术名称"
:title="$t('preopmanage.surgeryName')"
min-width="160"
show-overflow="title"
/>
<vxe-column
field="surgeryLevel"
title="级别"
:title="$t('preopmanage.level')"
width="60"
align="center"
>
@@ -191,18 +191,18 @@
:type="row.surgeryLevel >= 3 ? 'danger' : 'info'"
size="small"
>
{{ row.surgeryLevel }}
{{ row.surgeryLevel }}{{ $t('preopmanage.levelSuffix') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
field="hostUserName"
title="主持人"
:title="$t('preopmanage.host')"
width="90"
/>
<vxe-column
field="discussionConclusion"
title="结论"
:title="$t('preopmanage.conclusion')"
width="90"
align="center"
>
@@ -212,28 +212,28 @@
type="success"
size="small"
>
同意手术
{{ $t('preopmanage.conclusionApprove') }}
</el-tag>
<el-tag
v-else-if="row.discussionConclusion === 2"
type="warning"
size="small"
>
需补充检查
{{ $t('preopmanage.conclusionNeedCheck') }}
</el-tag>
<el-tag
v-else-if="row.discussionConclusion === 3"
type="danger"
size="small"
>
暂不手术
{{ $t('preopmanage.conclusionPostpone') }}
</el-tag>
<span v-else>-</span>
</template>
</vxe-column>
<vxe-column
field="status"
title="状态"
:title="$t('preopmanage.status')"
width="80"
align="center"
>
@@ -248,11 +248,11 @@
</vxe-column>
<vxe-column
field="createTime"
title="创建时间"
:title="$t('preopmanage.createTime')"
width="150"
/>
<vxe-column
title="操作"
:title="$t('preopmanage.operations')"
width="220"
fixed="right"
>
@@ -263,7 +263,7 @@
icon="View"
@click="handleDetail(row)"
>
详情
{{ $t('preopmanage.detail') }}
</el-button>
<el-button
v-if="row.status === 0"
@@ -271,7 +271,7 @@
link
@click="handleSubmit(row)"
>
提交
{{ $t('preopmanage.submit') }}
</el-button>
<el-button
v-if="row.status === 2"
@@ -279,7 +279,7 @@
link
@click="handleReview(row, 1)"
>
通过
{{ $t('preopmanage.approve') }}
</el-button>
<el-button
v-if="row.status === 2"
@@ -287,7 +287,7 @@
link
@click="handleReview(row, 5)"
>
驳回
{{ $t('preopmanage.reject') }}
</el-button>
</template>
</vxe-column>
@@ -304,7 +304,7 @@
<!-- 新建讨论弹窗 -->
<el-dialog
v-model="formVisible"
title="新建术前讨论"
:title="$t('preopmanage.newDiscussionTitle')"
width="800px"
append-to-body
>
@@ -317,20 +317,20 @@
<el-row :gutter="16">
<el-col :span="12">
<el-form-item
label="患者姓名"
:label="$t('preopmanage.patientName')"
prop="patientName"
>
<el-input
v-model="form.patientName"
placeholder="患者姓名"
:placeholder="$t('preopmanage.patientName')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="住院号">
<el-form-item :label="$t('preopmanage.admissionNo')">
<el-input
v-model="form.encounterId"
placeholder="住院号"
:placeholder="$t('preopmanage.admissionNo')"
/>
</el-form-item>
</el-col>
@@ -338,18 +338,18 @@
<el-row :gutter="16">
<el-col :span="12">
<el-form-item
label="手术名称"
:label="$t('preopmanage.surgeryName')"
prop="surgeryName"
>
<el-input
v-model="form.surgeryName"
placeholder="手术名称"
:placeholder="$t('preopmanage.surgeryName')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item
label="手术级别"
:label="$t('preopmanage.surgeryLevel')"
prop="surgeryLevel"
>
<el-select
@@ -357,17 +357,17 @@
style="width:100%"
>
<el-option
label="一级"
:label="$t('preopmanage.level1')"
:value="1"
/><el-option
label="二级"
:label="$t('preopmanage.level2')"
:value="2"
/>
<el-option
label="三级"
:label="$t('preopmanage.level3')"
:value="3"
/><el-option
label="四级"
:label="$t('preopmanage.level4')"
:value="4"
/>
</el-select>
@@ -375,138 +375,138 @@
</el-col>
</el-row>
<el-form-item
label="术前诊断"
:label="$t('preopmanage.preopDiagnosis')"
prop="preopDiagnosis"
>
<el-input
v-model="form.preopDiagnosis"
type="textarea"
:rows="2"
placeholder="术前诊断"
:placeholder="$t('preopmanage.preopDiagnosis')"
/>
</el-form-item>
<el-form-item
label="手术指征"
:label="$t('preopmanage.surgeryIndication')"
prop="surgeryIndication"
>
<el-input
v-model="form.surgeryIndication"
type="textarea"
:rows="2"
placeholder="手术指征"
:placeholder="$t('preopmanage.surgeryIndication')"
/>
</el-form-item>
<el-form-item
label="主手术方案"
:label="$t('preopmanage.mainPlan')"
prop="mainPlan"
>
<el-input
v-model="form.mainPlan"
type="textarea"
:rows="2"
placeholder="主手术方案"
:placeholder="$t('preopmanage.mainPlan')"
/>
</el-form-item>
<el-form-item
label="备选方案"
:label="$t('preopmanage.backupPlan')"
prop="backupPlan"
>
<el-input
v-model="form.backupPlan"
type="textarea"
:rows="2"
placeholder="备选手术方案"
:placeholder="$t('preopmanage.backupPlanPlaceholder')"
/>
</el-form-item>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item label="麻醉方式">
<el-form-item :label="$t('preopmanage.anesthesiaType')">
<el-input
v-model="form.anesthesiaType"
placeholder="麻醉方式"
:placeholder="$t('preopmanage.anesthesiaType')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="讨论类型">
<el-form-item :label="$t('preopmanage.discussionType')">
<el-select
v-model="form.discussionType"
style="width:100%"
>
<el-option
label="科内讨论"
:label="$t('preopmanage.typeDept')"
:value="1"
/><el-option
label="全科讨论"
:label="$t('preopmanage.typeSection')"
:value="2"
/><el-option
label="全院讨论"
:label="$t('preopmanage.typeHospital')"
:value="3"
/>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="风险及对策">
<el-form-item :label="$t('preopmanage.risksAndCountermeasures')">
<el-input
v-model="form.risksAndCountermeasures"
type="textarea"
:rows="2"
placeholder="术中可能风险及对策"
:placeholder="$t('preopmanage.risksPlaceholder')"
/>
</el-form-item>
<el-form-item label="术后注意">
<el-form-item :label="$t('preopmanage.postopNotes')">
<el-input
v-model="form.postopNotes"
type="textarea"
:rows="2"
placeholder="术后注意事项"
:placeholder="$t('preopmanage.postopNotesPlaceholder')"
/>
</el-form-item>
<el-row :gutter="16">
<el-col :span="12">
<el-form-item
label="主持人"
:label="$t('preopmanage.host')"
prop="hostUserName"
>
<el-input
v-model="form.hostUserName"
placeholder="主持人姓名"
:placeholder="$t('preopmanage.hostNamePlaceholder')"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="讨论地点">
<el-form-item :label="$t('preopmanage.discussionLocation')">
<el-input
v-model="form.discussionLocation"
placeholder="讨论地点"
:placeholder="$t('preopmanage.discussionLocation')"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="讨论结论">
<el-form-item :label="$t('preopmanage.discussionConclusion')">
<el-radio-group v-model="form.discussionConclusion">
<el-radio :value="1">
同意手术
{{ $t('preopmanage.conclusionApprove') }}
</el-radio>
<el-radio :value="2">
需进一步检查
{{ $t('preopmanage.conclusionNeedFurtherCheck') }}
</el-radio>
<el-radio :value="3">
暂不手术
{{ $t('preopmanage.conclusionPostpone') }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="formVisible = false">
取消
{{ $t('preopmanage.cancel') }}
</el-button>
<el-button
type="primary"
@click="submitForm"
>
保存
{{ $t('preopmanage.save') }}
</el-button>
</template>
</el-dialog>
@@ -514,7 +514,7 @@
<!-- 详情抽屉 -->
<el-drawer
v-model="detailVisible"
title="术前讨论详情"
:title="$t('preopmanage.discussionDetail')"
size="650px"
>
<div v-if="detailData">
@@ -522,72 +522,72 @@
:column="2"
border
>
<el-descriptions-item label="患者">
<el-descriptions-item :label="$t('preopmanage.patient')">
{{ detailData.discussion?.patientName }}
</el-descriptions-item>
<el-descriptions-item
label="手术名称"
:label="$t('preopmanage.surgeryName')"
:span="2"
>
{{ detailData.discussion?.surgeryName }}
</el-descriptions-item>
<el-descriptions-item label="手术级别">
{{ detailData.discussion?.surgeryLevel }}
<el-descriptions-item :label="$t('preopmanage.surgeryLevel')">
{{ detailData.discussion?.surgeryLevel }}{{ $t('preopmanage.levelSuffix') }}
</el-descriptions-item>
<el-descriptions-item label="主持人">
<el-descriptions-item :label="$t('preopmanage.host')">
{{ detailData.discussion?.hostUserName }}
</el-descriptions-item>
<el-descriptions-item label="讨论结论">
<el-descriptions-item :label="$t('preopmanage.discussionConclusion')">
<el-tag
v-if="detailData.discussion?.discussionConclusion === 1"
type="success"
>
同意手术
{{ $t('preopmanage.conclusionApprove') }}
</el-tag>
<el-tag
v-else-if="detailData.discussion?.discussionConclusion === 2"
type="warning"
>
需补充检查
{{ $t('preopmanage.conclusionNeedCheck') }}
</el-tag>
<el-tag
v-else-if="detailData.discussion?.discussionConclusion === 3"
type="danger"
>
暂不手术
{{ $t('preopmanage.conclusionPostpone') }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="状态">
<el-descriptions-item :label="$t('preopmanage.status')">
<el-tag :type="statusType(detailData.discussion?.status)">
{{ statusText(detailData.discussion?.status) }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
<div class="section-title">
讨论内容
{{ $t('preopmanage.discussionContent') }}
</div>
<el-descriptions
:column="1"
border
>
<el-descriptions-item label="术前诊断">
<el-descriptions-item :label="$t('preopmanage.preopDiagnosis')">
{{ detailData.discussion?.preopDiagnosis }}
</el-descriptions-item>
<el-descriptions-item label="手术指征">
<el-descriptions-item :label="$t('preopmanage.surgeryIndication')">
{{ detailData.discussion?.surgeryIndication }}
</el-descriptions-item>
<el-descriptions-item label="主方案">
<el-descriptions-item :label="$t('preopmanage.mainPlanLabel')">
{{ detailData.discussion?.mainPlan }}
</el-descriptions-item>
<el-descriptions-item label="备选方案">
<el-descriptions-item :label="$t('preopmanage.backupPlan')">
{{ detailData.discussion?.backupPlan }}
</el-descriptions-item>
<el-descriptions-item label="风险及对策">
<el-descriptions-item :label="$t('preopmanage.risksAndCountermeasures')">
{{ detailData.discussion?.risksAndCountermeasures }}
</el-descriptions-item>
</el-descriptions>
<div class="section-title">
参与者
{{ $t('preopmanage.participants') }}
</div>
<vxe-table
:data="detailData.participants || []"
@@ -596,22 +596,22 @@
>
<vxe-column
field="userName"
title="姓名"
:title="$t('preopmanage.name')"
width="100"
/>
<vxe-column
field="title"
title="职称"
:title="$t('preopmanage.title')"
width="100"
/>
<vxe-column
field="role"
title="角色"
:title="$t('preopmanage.role')"
width="80"
/>
<vxe-column
field="signStatus"
title="签名"
:title="$t('preopmanage.signature')"
width="80"
align="center"
>
@@ -620,13 +620,13 @@
:type="row.signStatus === 1 ? 'success' : 'info'"
size="small"
>
{{ row.signStatus === 1 ? '已签' : '未签' }}
{{ row.signStatus === 1 ? $t('preopmanage.signed') : $t('preopmanage.unsigned') }}
</el-tag>
</template>
</vxe-column>
<vxe-column
field="signTime"
title="签名时间"
:title="$t('preopmanage.signTime')"
width="150"
/>
</vxe-table>
@@ -636,10 +636,13 @@
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useI18n } from 'vue-i18n'
import { getDiscussionPage, getDiscussionDetail, addDiscussion, submitDiscussion, reviewDiscussion, getStatistics } from './components/api'
const { t } = useI18n()
const loading = ref(false); const tableData = ref([]); const total = ref(0); const stats = ref(null)
const tableHeight = ref(Math.max(300, window.innerHeight - 320))
function handleResize() { tableHeight.value = Math.max(300, window.innerHeight - 320) }
@@ -648,9 +651,23 @@ const formVisible = ref(false); const formRef = ref()
const detailVisible = ref(false); const detailData = ref(null)
const form = ref({ patientName: '', encounterId: '', surgeryName: '', surgeryLevel: 3, preopDiagnosis: '', surgeryIndication: '', mainPlan: '', backupPlan: '', anesthesiaType: '', discussionType: 1, risksAndCountermeasures: '', postopNotes: '', hostUserName: '', discussionLocation: '', discussionConclusion: 1 })
const rules = { patientName: [{ required: true, message: '请输入患者姓名', trigger: 'blur' }], surgeryName: [{ required: true, message: '请输入手术名称', trigger: 'blur' }], surgeryLevel: [{ required: true, message: '请选择手术级别', trigger: 'change' }], preopDiagnosis: [{ required: true, message: '请输入术前诊断', trigger: 'blur' }], mainPlan: [{ required: true, message: '请输入主手术方案', trigger: 'blur' }], hostUserName: [{ required: true, message: '请输入主持人', trigger: 'blur' }] }
const rules = computed(() => ({
patientName: [{ required: true, message: t('preopmanage.rulePatientNameRequired'), trigger: 'blur' }],
surgeryName: [{ required: true, message: t('preopmanage.ruleSurgeryNameRequired'), trigger: 'blur' }],
surgeryLevel: [{ required: true, message: t('preopmanage.ruleSurgeryLevelRequired'), trigger: 'change' }],
preopDiagnosis: [{ required: true, message: t('preopmanage.rulePreopDiagnosisRequired'), trigger: 'blur' }],
mainPlan: [{ required: true, message: t('preopmanage.ruleMainPlanRequired'), trigger: 'blur' }],
hostUserName: [{ required: true, message: t('preopmanage.ruleHostRequired'), trigger: 'blur' }]
}))
const statusText = (s) => ({ 0: '草稿', 1: '待签名', 2: '待审核', 3: '已完成', 4: '已归档', 5: '已驳回' }[s] || '未知')
const statusText = (s) => ({
0: t('preopmanage.statusDraft'),
1: t('preopmanage.statusPendingSignature'),
2: t('preopmanage.statusPendingReview'),
3: t('preopmanage.statusCompleted'),
4: t('preopmanage.statusArchived'),
5: t('preopmanage.statusRejected')
}[s] || t('preopmanage.statusUnknown'))
const statusType = (s) => ({ 0: 'info', 1: 'warning', 2: '', 3: 'success', 4: 'success', 5: 'danger' }[s] || 'info')
function getList() { loading.value = true; getDiscussionPage(queryParams.value).then(res => { tableData.value = res.data?.records || []; total.value = res.data?.total || 0 }).finally(() => { loading.value = false }) }
@@ -658,17 +675,17 @@ function handleQuery() { queryParams.value.pageNo = 1; getList() }
function resetQuery() { queryParams.value = { patientName: '', surgeryLevel: undefined, status: undefined, pageNo: 1, pageSize: 10 }; getList() }
function handleAdd() { form.value = { patientName: '', encounterId: '', surgeryName: '', surgeryLevel: 3, preopDiagnosis: '', surgeryIndication: '', mainPlan: '', backupPlan: '', anesthesiaType: '', discussionType: 1, risksAndCountermeasures: '', postopNotes: '', hostUserName: '', discussionLocation: '', discussionConclusion: 1 }; formVisible.value = true }
function handleDetail(row) { getDiscussionDetail(row.id).then(res => { detailData.value = res.data; detailVisible.value = true }) }
function handleSubmit(row) { submitDiscussion(row.id).then(res => { if (res.code === 200) { ElMessage.success('已提交'); getList(); loadStats() } else ElMessage.error(res.msg || '提交失败') }) }
function handleSubmit(row) { submitDiscussion(row.id).then(res => { if (res.code === 200) { ElMessage.success(t('preopmanage.submitted')); getList(); loadStats() } else ElMessage.error(res.msg || t('preopmanage.submitFailed')) }) }
function handleReview(row, action) {
const label = action === 1 ? '通过' : '驳回'
ElMessageBox.confirm('确认' + label + '该讨论?', '提示', { type: action === 1 ? 'success' : 'warning' }).then(() => {
reviewDiscussion(row.id, action).then(res => { if (res.code === 200) { ElMessage.success(label + '成功'); getList(); loadStats() } else ElMessage.error(res.msg || label + '失败') })
const label = action === 1 ? t('preopmanage.approve') : t('preopmanage.reject')
ElMessageBox.confirm(t('preopmanage.confirmAction', { action: label }), t('preopmanage.tip'), { type: action === 1 ? 'success' : 'warning' }).then(() => {
reviewDiscussion(row.id, action).then(res => { if (res.code === 200) { ElMessage.success(t('preopmanage.actionSuccess', { action: label })); getList(); loadStats() } else ElMessage.error(res.msg || t('preopmanage.actionFailed', { action: label })) })
}).catch(() => {})
}
function submitForm() {
formRef.value.validate(valid => { if (!valid) return
form.value.patientId = 0; form.value.discussionTime = Date.now()
addDiscussion(form.value).then(res => { if (res.code === 200) { ElMessage.success('创建成功'); formVisible.value = false; getList(); loadStats() } else ElMessage.error(res.msg || '创建失败') })
addDiscussion(form.value).then(res => { if (res.code === 200) { ElMessage.success(t('preopmanage.created')); formVisible.value = false; getList(); loadStats() } else ElMessage.error(res.msg || t('preopmanage.createFailed')) })
})
}
function loadStats() { getStatistics().then(res => { stats.value = res.data }) }

File diff suppressed because it is too large Load Diff

View File

@@ -5,27 +5,27 @@
:model="queryParams"
:inline="true"
>
<el-form-item label="患者">
<el-form-item :label="t('surgery.safety.patient')">
<el-input
v-model="queryParams.patientName"
placeholder="患者姓名"
:placeholder="t('surgery.safety.patientName')"
clearable
/>
</el-form-item>
<el-form-item label="核查阶段">
<el-form-item :label="t('surgery.safety.checkPhase')">
<el-select
v-model="queryParams.checkPhase"
placeholder="全部"
:placeholder="t('surgery.safety.all')"
clearable
>
<el-option
label="术前"
:label="t('surgery.safety.preOp')"
value="PRE_OP"
/><el-option
label="术中"
:label="t('surgery.safety.intraOp')"
value="INTRA_OP"
/><el-option
label="术后"
:label="t('surgery.safety.postOp')"
value="POST_OP"
/>
</el-select>
@@ -36,20 +36,20 @@
icon="Search"
@click="handleQuery"
>
搜索
{{ t('surgery.safety.search') }}
</el-button>
<el-button
icon="Refresh"
@click="resetQuery"
>
重置
{{ t('surgery.safety.reset') }}
</el-button>
<el-button
type="primary"
icon="Plus"
@click="handleAdd"
>
新增
{{ t('surgery.safety.add') }}
</el-button>
</el-form-item>
</el-form>
@@ -58,58 +58,58 @@
:data="dataList"
>
<el-table-column
label="患者"
:label="t('surgery.safety.patient')"
prop="patientName"
width="100"
/>
<el-table-column
label="手术名称"
:label="t('surgery.safety.surgeryName')"
prop="surgeryName"
width="150"
show-overflow-tooltip
/>
<el-table-column
label="核查阶段"
:label="t('surgery.safety.checkPhase')"
prop="checkPhase"
width="90"
>
<template #default="s">
<el-tag>{{ {PRE_OP:'术前',INTRA_OP:'术中',POST_OP:'术后'}[s.row.checkPhase] || s.row.checkPhase }}</el-tag>
<el-tag>{{ checkPhaseMap[s.row.checkPhase] || s.row.checkPhase }}</el-tag>
</template>
</el-table-column>
<el-table-column
label="主刀医生"
:label="t('surgery.safety.surgeon')"
prop="surgeonName"
width="100"
/>
<el-table-column
label="麻醉医师"
:label="t('surgery.safety.anesthesiologist')"
prop="anesthesiologistName"
width="100"
/>
<el-table-column
label="巡回护士"
:label="t('surgery.safety.circulatingNurse')"
prop="circulatingNurseName"
width="100"
/>
<el-table-column
label="核查时间"
:label="t('surgery.safety.checkTime')"
prop="checkTime"
width="170"
/>
<el-table-column
label="状态"
:label="t('surgery.safety.status')"
prop="status"
width="90"
>
<template #default="s">
<el-tag :type="s.row.status==='COMPLETED'?'success':s.row.status==='PENDING'?'danger':'warning'">
{{ {PENDING:'待核查',IN_PROGRESS:'核查中',COMPLETED:'已完成'}[s.row.status] || s.row.status }}
{{ statusMap[s.row.status] || s.row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column
label="操作"
:label="t('surgery.safety.operation')"
width="150"
fixed="right"
>
@@ -119,14 +119,14 @@
type="primary"
@click="handleEdit(s.row)"
>
编辑
{{ t('surgery.safety.edit') }}
</el-button>
<el-button
link
type="danger"
@click="handleDelete(s.row)"
>
删除
{{ t('surgery.safety.delete') }}
</el-button>
</template>
</el-table-column>
@@ -150,64 +150,64 @@
>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="患者">
<el-form-item :label="t('surgery.safety.patient')">
<el-input v-model="formData.patientName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手术名称">
<el-form-item :label="t('surgery.safety.surgeryName')">
<el-input v-model="formData.surgeryName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="核查阶段">
<el-form-item :label="t('surgery.safety.checkPhase')">
<el-select v-model="formData.checkPhase">
<el-option
label="术前"
:label="t('surgery.safety.preOp')"
value="PRE_OP"
/><el-option
label="术中"
:label="t('surgery.safety.intraOp')"
value="INTRA_OP"
/><el-option
label="术后"
:label="t('surgery.safety.postOp')"
value="POST_OP"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="主刀医生">
<el-form-item :label="t('surgery.safety.surgeon')">
<el-input v-model="formData.surgeonName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="麻醉医师">
<el-form-item :label="t('surgery.safety.anesthesiologist')">
<el-input v-model="formData.anesthesiologistName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="巡回护士">
<el-form-item :label="t('surgery.safety.circulatingNurse')">
<el-input v-model="formData.circulatingNurseName" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-form-item :label="t('surgery.safety.status')">
<el-select v-model="formData.status">
<el-option
label="待核查"
:label="t('surgery.safety.pending')"
value="PENDING"
/><el-option
label="核查中"
:label="t('surgery.safety.inProgress')"
value="IN_PROGRESS"
/><el-option
label="已完成"
:label="t('surgery.safety.completed')"
value="COMPLETED"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="核查内容">
<el-form-item :label="t('surgery.safety.checkContent')">
<el-input
v-model="formData.checkContent"
type="textarea"
@@ -216,7 +216,7 @@
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-form-item :label="t('surgery.safety.remark')">
<el-input
v-model="formData.remark"
type="textarea"
@@ -228,13 +228,13 @@
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">
取消
{{ t('surgery.safety.cancel') }}
</el-button>
<el-button
type="primary"
@click="submitForm"
>
确定
{{ t('surgery.safety.confirm') }}
</el-button>
</template>
</el-dialog>
@@ -242,27 +242,41 @@
</template>
<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, computed, onMounted } from 'vue'
import { useI18n } from 'vue-i18n'
import { getPage, addCheck, updateCheck, deleteCheck } from './api'
import { ElMessage, ElMessageBox } from 'element-plus'
const { t } = useI18n()
const loading = ref(false); const dataList = ref([]); const total = ref(0); const showSearch = ref(true)
const dialogVisible = ref(false); const dialogTitle = ref('新增')
const dialogVisible = ref(false); const dialogTitle = ref(t('surgery.safety.addTitle'))
const queryParams = reactive({ patientName: '', checkPhase: '', pageNo: 1, pageSize: 10 })
const formData = ref({})
const checkPhaseMap = computed(() => ({
PRE_OP: t('surgery.safety.preOp'),
INTRA_OP: t('surgery.safety.intraOp'),
POST_OP: t('surgery.safety.postOp')
}))
const statusMap = computed(() => ({
PENDING: t('surgery.safety.pending'),
IN_PROGRESS: t('surgery.safety.inProgress'),
COMPLETED: t('surgery.safety.completed')
}))
const getList = async () => { loading.value = true; const res = await getPage(queryParams); dataList.value = res.data?.records || []; total.value = res.data?.total || 0; loading.value = false }
const handleQuery = () => { queryParams.pageNo = 1; getList() }
const resetQuery = () => { queryParams.patientName = ''; queryParams.checkPhase = ''; handleQuery() }
const handleAdd = () => { formData.value = { status: 'PENDING' }; dialogTitle.value = '新增手术安全核查'; dialogVisible.value = true }
const handleEdit = (row) => { formData.value = { ...row }; dialogTitle.value = '编辑手术安全核查'; dialogVisible.value = true }
const handleAdd = () => { formData.value = { status: 'PENDING' }; dialogTitle.value = t('surgery.safety.addTitle'); dialogVisible.value = true }
const handleEdit = (row) => { formData.value = { ...row }; dialogTitle.value = t('surgery.safety.editTitle'); dialogVisible.value = true }
const submitForm = async () => {
if (formData.value.id) { await updateCheck(formData.value) } else { await addCheck(formData.value) }
ElMessage.success('操作成功'); dialogVisible.value = false; getList()
ElMessage.success(t('surgery.safety.operationSuccess')); dialogVisible.value = false; getList()
}
const handleDelete = async (row) => {
await ElMessageBox.confirm('确认删除?', '提示', { type: 'warning' })
await deleteCheck(row.id); ElMessage.success('删除成功'); getList()
await ElMessageBox.confirm(t('surgery.safety.confirmDelete'), t('surgery.safety.tip'), { type: 'warning' })
await deleteCheck(row.id); ElMessage.success(t('surgery.safety.deleteSuccess')); getList()
}
onMounted(() => getList())
</script>

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,37 @@
<template>
<template>
<div class="temporary-medical-container">
<!-- 顶部区域标题 + 患者信息 + 操作按钮 -->
<div class="top-container">
<!-- 标题栏 -->
<div class="title-bar">
<h1 class="title-text">
门诊术中临时医嘱
{{ t('surgicalschedule.tmp.title') }}
</h1>
</div>
<!-- 患者信息卡 -->
<div class="patient-info-card">
<div class="info-item">
<span class="info-label">患者</span>
<span class="info-label">{{ t('surgicalschedule.tmp.patientLabel') }}</span>
<span class="info-value">{{ patientInfo.patientName || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">就诊卡号</span>
<span class="info-label">{{ t('surgicalschedule.tmp.cardNoLabel') }}</span>
<span class="info-value">{{ patientInfo.identifierNo || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">手术单号</span>
<span class="info-label">{{ t('surgicalschedule.tmp.operCodeLabel') }}</span>
<span class="info-value">{{ patientInfo.operCode || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">科室</span>
<span class="info-label">{{ t('surgicalschedule.tmp.deptLabel') }}</span>
<span class="info-value">{{ patientInfo.roomCode || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">医师</span>
<span class="info-label">{{ t('surgicalschedule.tmp.doctorLabel') }}</span>
<span class="info-value">{{ patientInfo.doctorName || '-' }}</span>
</div>
<div class="info-item">
<span class="info-label">角色</span>
<span class="info-label">{{ t('surgicalschedule.tmp.roleLabel') }}</span>
<span class="info-value">{{ patientInfo.role || '-' }}</span>
</div>
</div>
@@ -41,13 +41,13 @@
class="refresh-btn"
@click="handleRefresh"
>
<span></span> 刷新
<span></span> {{ t('surgicalschedule.tmp.refresh') }}
</el-button>
<el-button
class="quote-btn"
@click="handleQuoteBilling"
>
引用计费
{{ t('surgicalschedule.tmp.quoteBilling') }}
</el-button>
</div>
</div>
@@ -55,13 +55,13 @@
<!-- 已引用计费药品区域 -->
<div class="medicine-section">
<div class="section-title">
已引用计费药品待生成医嘱
{{ t('surgicalschedule.tmp.sectionBillingTitle') }}
<span
v-if="(billingMedicines || []).length >= PAGE_SIZE"
style="margin-left:auto;font-size:14px;color:#4a8bc9;cursor:pointer;white-space:nowrap;"
@click="billingExpanded = !billingExpanded"
>
{{ billingExpanded ? '收起' : `展开全部(${(billingMedicines || []).length})` }}
{{ billingExpanded ? t('surgicalschedule.tmp.collapse') : `${t('surgicalschedule.tmp.expandAll')}(${(billingMedicines || []).length}${t('surgicalschedule.tmp.items')})` }}
</span>
</div>
<vxe-table
@@ -73,25 +73,25 @@
fit
>
<vxe-column
title="序号"
:title="t('surgicalschedule.tmp.colSeq')"
type="seq"
width="60"
align="center"
/>
<vxe-column
title="药品名称"
:title="t('surgicalschedule.tmp.colMedicineName')"
field="medicineName"
min-width="150"
show-overflow="title"
/>
<vxe-column
title="规格"
:title="t('surgicalschedule.tmp.colSpec')"
field="specification"
min-width="100"
align="center"
/>
<vxe-column
title="数量"
:title="t('surgicalschedule.tmp.colQuantity')"
field="quantity"
width="80"
align="center"
@@ -101,13 +101,13 @@
</template>
</vxe-column>
<vxe-column
title="批号"
:title="t('surgicalschedule.tmp.colBatchNo')"
field="batchNumber"
min-width="120"
align="center"
/>
<vxe-column
title="单价"
:title="t('surgicalschedule.tmp.colUnitPrice')"
field="unitPrice"
min-width="80"
align="center"
@@ -117,7 +117,7 @@
</template>
</vxe-column>
<vxe-column
title="小计"
:title="t('surgicalschedule.tmp.colSubtotal')"
field="subtotal"
min-width="100"
align="center"
@@ -127,7 +127,7 @@
</template>
</vxe-column>
<vxe-column
title="医保"
:title="t('surgicalschedule.tmp.colInsurance')"
field="insuranceType"
width="80"
align="center"
@@ -145,13 +145,13 @@
<div class="medicine-summary">
<div class="summary-item insurance">
医保内{{ insuranceAmount.toFixed(2) }}
{{ t('surgicalschedule.tmp.insuranceIn') }}{{ insuranceAmount.toFixed(2) }}
</div>
<div class="summary-item self-pay">
自费{{ selfPayAmount.toFixed(2) }}
{{ t('surgicalschedule.tmp.selfPay') }}{{ selfPayAmount.toFixed(2) }}
</div>
<div class="summary-item total">
总计{{ totalAmount.toFixed(2) }}
{{ t('surgicalschedule.tmp.total') }}{{ totalAmount.toFixed(2) }}
</div>
</div>
</div>
@@ -159,13 +159,13 @@
<!-- 临时医嘱预览区域 -->
<div class="advice-section">
<div class="section-title">
临时医嘱预览已生成
{{ t('surgicalschedule.tmp.sectionAdviceTitle') }}
<span
v-if="(displayAdvices || []).length >= PAGE_SIZE"
style="margin-left:auto;font-size:14px;color:#4a8bc9;cursor:pointer;white-space:nowrap;"
@click="advicesExpanded = !advicesExpanded"
>
{{ advicesExpanded ? '收起' : `展开全部(${(displayAdvices || []).length})` }}
{{ advicesExpanded ? t('surgicalschedule.tmp.collapse') : `${t('surgicalschedule.tmp.expandAll')}(${(displayAdvices || []).length}${t('surgicalschedule.tmp.items')})` }}
</span>
</div>
<vxe-table
@@ -177,25 +177,25 @@
@cell-click="handleAdviceRowClick"
>
<vxe-column
title="序号"
:title="t('surgicalschedule.tmp.colSeq')"
type="seq"
width="60"
align="center"
/>
<vxe-column
title="医嘱名称"
:title="t('surgicalschedule.tmp.colAdviceName')"
field="adviceName"
min-width="150"
show-overflow="title"
/>
<vxe-column
title="剂量"
:title="t('surgicalschedule.tmp.colDosage')"
field="dosage"
min-width="80"
align="center"
/>
<vxe-column
title="单位"
:title="t('surgicalschedule.tmp.colUnit')"
field="unit"
min-width="80"
align="center"
@@ -205,7 +205,7 @@
</template>
</vxe-column>
<vxe-column
title="用法"
:title="t('surgicalschedule.tmp.colUsage')"
field="usage"
min-width="100"
show-overflow="title"
@@ -215,17 +215,17 @@
</template>
</vxe-column>
<vxe-column
title="频次"
:title="t('surgicalschedule.tmp.colFrequency')"
field="frequency"
min-width="80"
align="center"
>
<template #default>
立即
{{ t('surgicalschedule.tmp.immediate') }}
</template>
</vxe-column>
<vxe-column
title="执行时间"
:title="t('surgicalschedule.tmp.colExecuteTime')"
field="executeTime"
min-width="160"
align="center"
@@ -235,7 +235,7 @@
</template>
</vxe-column>
<vxe-column
title="操作"
:title="t('surgicalschedule.tmp.colAction')"
min-width="140"
align="center"
>
@@ -245,14 +245,14 @@
type="primary"
@click="handleEditAdvice(rowIndex)"
>
编辑
{{ t('surgicalschedule.tmp.edit') }}
</el-button>
<el-button
link
type="danger"
@click="handleDeleteAdvice(rowIndex)"
>
删除
{{ t('surgicalschedule.tmp.delete') }}
</el-button>
</template>
</vxe-column>
@@ -262,19 +262,19 @@
<!-- 医师电子签名区域 -->
<div class="signature-section">
<div class="section-title">
医师电子签名
{{ t('surgicalschedule.tmp.sectionSignatureTitle') }}
</div>
<!-- 签名信息卡 -->
<div class="signature-card">
<div class="signature-info">
<span class="info-label">签名医师</span>
<span class="info-label">{{ t('surgicalschedule.tmp.signDoctorLabel') }}</span>
<span
class="info-value"
:class="{ 'unsigned': !isSigned }"
>{{ isSigned ? signatureDoctor : '未签名' }}</span>
>{{ isSigned ? signatureDoctor : t('surgicalschedule.tmp.unsigned') }}</span>
</div>
<div class="signature-info">
<span class="info-label">签名时间</span>
<span class="info-label">{{ t('surgicalschedule.tmp.signTimeLabel') }}</span>
<span class="info-value">{{ signatureTime || '-' }}</span>
</div>
</div>
@@ -284,14 +284,14 @@
class="cancel-btn"
@click="handleCancel"
>
取消
{{ t('surgicalschedule.tmp.cancel') }}
</el-button>
<el-button
class="sign-btn"
:disabled="allItemsSubmitted"
@click="handleSignAndSubmit"
>
{{ allItemsSubmitted ? '已签发' : '一键签名并生成医嘱' }}
{{ allItemsSubmitted ? t('surgicalschedule.tmp.alreadySigned') : t('surgicalschedule.tmp.signAndGenerate') }}
</el-button>
</div>
</div>
@@ -299,28 +299,28 @@
<!-- 签名密码弹窗 -->
<el-dialog
v-model="showSignDialog"
title="弹窗-签名密码"
:title="t('surgicalschedule.tmp.signDialogTitle')"
width="400px"
teleported
>
<div class="sign-dialog-content">
<p>请输入账户密码</p>
<p>{{ t('surgicalschedule.tmp.enterAccountPassword') }}</p>
<el-input
v-model="signPassword"
type="password"
placeholder="请输入密码"
:placeholder="t('surgicalschedule.tmp.placeholderPassword')"
style="margin-bottom: 16px"
@keyup.enter="confirmSign"
/>
<div class="dialog-actions">
<el-button @click="showSignDialog = false">
取消
{{ t('surgicalschedule.tmp.cancel') }}
</el-button>
<el-button
type="primary"
@click="confirmSign"
>
确认
{{ t('surgicalschedule.tmp.confirm') }}
</el-button>
</div>
</div>
@@ -329,7 +329,7 @@
<!-- 编辑医嘱弹窗 -->
<el-dialog
v-model="showEditDialog"
title="编辑医嘱"
:title="t('surgicalschedule.tmp.editDialogTitle')"
width="500px"
teleported
>
@@ -338,35 +338,35 @@
:model="editForm"
label-width="80px"
>
<el-form-item label="药品名称">
<el-form-item :label="t('surgicalschedule.tmp.colMedicineName')">
<el-input
v-model="editForm.adviceName"
disabled
/>
</el-form-item>
<el-form-item
label="剂量"
:label="t('surgicalschedule.tmp.colDosage')"
required
>
<el-input
v-model.number="editForm.dosage"
placeholder="请输入剂量"
:placeholder="t('surgicalschedule.tmp.placeholderDosage')"
/>
</el-form-item>
<el-form-item label="单位">
<el-form-item :label="t('surgicalschedule.tmp.colUnit')">
<el-input
v-model="editForm.unit"
placeholder="请输入单位"
:placeholder="t('surgicalschedule.tmp.placeholderUnit')"
/>
</el-form-item>
<el-form-item
label="用法"
:label="t('surgicalschedule.tmp.colUsage')"
required
>
<el-select
v-if="getMethodCodeDict.length > 0"
v-model="editForm.usage"
placeholder="请选择用法"
:placeholder="t('surgicalschedule.tmp.placeholderSelectUsage')"
style="width: 100%"
filterable
>
@@ -380,10 +380,10 @@
<el-input
v-else
disabled
placeholder="加载中..."
:placeholder="t('surgicalschedule.tmp.loading')"
/>
</el-form-item>
<el-form-item label="频次">
<el-form-item :label="t('surgicalschedule.tmp.colFrequency')">
<el-input
v-model="editForm.frequency"
disabled
@@ -392,13 +392,13 @@
</el-form>
<div class="dialog-actions">
<el-button @click="handleCancelEdit">
取消
{{ t('surgicalschedule.tmp.cancel') }}
</el-button>
<el-button
type="primary"
@click="handleSaveEdit"
>
保存
{{ t('surgicalschedule.tmp.save') }}
</el-button>
</div>
</div>
@@ -409,11 +409,16 @@
<script setup>
import { ref, computed, getCurrentInstance, onMounted, watch, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useI18n } from 'vue-i18n'
import useUserStore from '@/store/modules/user'
import { checkPassword } from '@/api/surgicalschedule'
import { savePrescription } from '@/views/clinicmanagement/bargain/component/api.js'
import { parseTime } from '@/utils/his'
const { t } = useI18n()
const immediateFrequency = computed(() => t('surgicalschedule.tmp.immediate'))
// 定义props
const props = defineProps({
// 患者和医生信息
@@ -483,22 +488,22 @@ const mapUsageCode = (advice) => {
}
// 🔧 新增:本地备用用法字典,确保字典未加载时也能显示中文
const localMethodCode = [
{ value: '404', label: '静脉注射' },
{ value: '1', label: '口服' },
{ value: '403', label: '肌肉注射' },
{ value: '401', label: '皮下注射' },
{ value: '405', label: '静脉滴注' },
{ value: '5', label: '吸入给药' },
{ value: '610', label: '含化' },
{ value: '604', label: '腹腔用药' },
{ value: '6', label: '局部用药' },
{ value: '2', label: '直肠给药' }
]
const localMethodCode = computed(() => [
{ value: '404', label: t('surgicalschedule.tmp.usageIv') },
{ value: '1', label: t('surgicalschedule.tmp.usagePo') },
{ value: '403', label: t('surgicalschedule.tmp.usageIm') },
{ value: '401', label: t('surgicalschedule.tmp.usageSc') },
{ value: '405', label: t('surgicalschedule.tmp.usageIvgtt') },
{ value: '5', label: t('surgicalschedule.tmp.usageIh') },
{ value: '610', label: t('surgicalschedule.tmp.usageIt') },
{ value: '604', label: t('surgicalschedule.tmp.usageIp') },
{ value: '6', label: t('surgicalschedule.tmp.usageTop') },
{ value: '2', label: t('surgicalschedule.tmp.usagePr') }
])
// 🔧 新增:获取用法字典(优先使用从后端加载的,否则使用本地备用)
const getMethodCodeDict = computed(() => {
let dict = method_code.value && method_code.value.length > 0 ? method_code.value : localMethodCode
let dict = method_code.value && method_code.value.length > 0 ? method_code.value : localMethodCode.value
return dict
})
@@ -542,12 +547,12 @@ const editForm = ref({
dosage: '',
unit: '',
usage: '',
frequency: '立即'
frequency: ''
})
// 计算属性
const currentUser = computed(() => ({
name: userStore.nickName || userStore.name || '未知用户',
name: userStore.nickName || userStore.name || t('surgicalschedule.tmp.unknownUser'),
id: userStore.id
}))
@@ -588,16 +593,16 @@ const convertedAdvices = computed(() => {
// 🔧 修复:根据药品名称判断用法,使用后端字典的正确编码
let usageCode = '404' // 默认静脉注射编码
let usageLabel = '静脉注射' // 默认显示名称
let usageLabel = t('surgicalschedule.tmp.usageIv') // 默认显示名称
if (medicine.medicineName && medicine.medicineName.includes('注射液')) {
usageCode = '404'
usageLabel = '静脉注射'
usageLabel = t('surgicalschedule.tmp.usageIv')
} else if (medicine.medicineName && medicine.medicineName.includes('片')) {
usageCode = '1'
usageLabel = '口服'
usageLabel = t('surgicalschedule.tmp.usagePo')
} else if (medicine.medicineName && medicine.medicineName.includes('胶囊')) {
usageCode = '1'
usageLabel = '口服'
usageLabel = t('surgicalschedule.tmp.usagePo')
}
return {
@@ -607,7 +612,7 @@ const convertedAdvices = computed(() => {
unit: specUnit,
usage: usageCode, // 🔧 修复:使用后端字典的正确编码
usageLabel: usageLabel, // 🔧 新增:保存显示名称
frequency: '立即',
frequency: immediateFrequency.value,
executeTime: '',
originalMedicine: medicine
}
@@ -629,7 +634,7 @@ const initDisplayAdvices = () => {
mapped.usage = usageCodeMapping[advice.usage]
}
mapped.unit = cleanUnitLabel(mapped.unit)
mapped.frequency = '立即'
mapped.frequency = immediateFrequency.value
return mapped
})
} else {
@@ -662,7 +667,7 @@ watch(() => props.temporaryAdvices, (newVal, oldVal) => {
// 🔧 BugFix: 清洗单位(去除 ×、:、/ 等多余字符)
mapped.unit = cleanUnitLabel(mapped.unit)
// 🔧 BugFix: 频次强制修正为"立即"(临床应用要求)
mapped.frequency = '立即'
mapped.frequency = immediateFrequency.value
// 🔧 BugFix: 执行时间不应为空时回退为空串(由父组件从 contentJson 中取持久化值)
return mapped
})
@@ -727,7 +732,7 @@ const handleEditAdvice = (index) => {
dosage: advice.dosage,
unit: cleanUnitLabel(advice.unit),
usage: usageCode, // 使用映射后的正确编码
frequency: '立即'
frequency: immediateFrequency.value
}
showEditDialog.value = true
}
@@ -735,16 +740,16 @@ const handleEditAdvice = (index) => {
// 保存编辑
const handleSaveEdit = async () => {
if (!editForm.value.dosage && editForm.value.dosage !== 0) {
ElMessage.warning('请填写剂量')
ElMessage.warning(t('surgicalschedule.tmp.msgFillDosage'))
return
}
// 🔧 新增:验证剂量必须为数字
if (isNaN(editForm.value.dosage) || editForm.value.dosage === '') {
ElMessage.warning('剂量必须为数字')
ElMessage.warning(t('surgicalschedule.tmp.msgDosageMustBeNumber'))
return
}
if (!editForm.value.usage) {
ElMessage.warning('请填写用法')
ElMessage.warning(t('surgicalschedule.tmp.msgFillUsage'))
return
}
@@ -859,9 +864,9 @@ const handleSaveEdit = async () => {
}
try {
await savePrescription({ organizationId: props.patientInfo.orgId || 1, adviceSaveList: [saveItem] }, '2')
ElMessage.success('医嘱修改已保存到服务器')
ElMessage.success(t('surgicalschedule.tmp.msgEditSaved'))
} catch (e) {
ElMessage.error('保存失败,请重试')
ElMessage.error(t('surgicalschedule.tmp.msgSaveFailedRetry'))
}
}
}
@@ -875,13 +880,13 @@ const handleCancelEdit = () => {
dosage: '',
unit: '',
usage: '',
frequency: '立即'
frequency: ''
}
}
const confirmSign = async () => {
if (!signPassword.value) {
ElMessage.warning('请输入密码')
ElMessage.warning(t('surgicalschedule.tmp.msgEnterPassword'))
return
}
@@ -896,7 +901,7 @@ const confirmSign = async () => {
signatureTime.value = parseTime(new Date())
showSignDialog.value = false
signPassword.value = ''
ElMessage.success('签名成功')
ElMessage.success(t('surgicalschedule.tmp.msgSignSuccess'))
// 签名成功后自动提交,用 setTimeout 确保响应式状态更新完成
setTimeout(() => {
@@ -925,9 +930,9 @@ const handleSignAndSubmit = () => {
* - 回退后刷新,该医嘱将从"已生成"移到"待生成"列表
*/
const handleDeleteAdvice = async (index) => {
ElMessageBox.confirm('确定要回退这条医嘱吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
ElMessageBox.confirm(t('surgicalschedule.tmp.msgConfirmRollback'), t('surgicalschedule.tmp.tip'), {
confirmButtonText: t('surgicalschedule.tmp.confirm'),
cancelButtonText: t('surgicalschedule.tmp.cancel'),
type: 'warning'
}).then(async () => {
const rollbackAdvice = displayAdvices.value[index]
@@ -989,14 +994,14 @@ const handleDeleteAdvice = async (index) => {
}
emit('update:billing-medicines', [...props.billingMedicines, restoredItem])
}
ElMessage.success('回退成功')
ElMessage.success(t('surgicalschedule.tmp.msgRollbackSuccess'))
} else {
emit('update:temporary-advices', originalList)
ElMessage.error(res.msg || '回退失败,请重试')
ElMessage.error(res.msg || t('surgicalschedule.tmp.msgRollbackFailedRetry'))
}
} catch (e) {
emit('update:temporary-advices', originalList)
ElMessage.error('回退失败,请重试')
ElMessage.error(t('surgicalschedule.tmp.msgRollbackFailedRetry'))
}
} else {
// 未持久化到数据库的医嘱(无 requestId本地移除即可
@@ -1022,7 +1027,7 @@ const handleDeleteAdvice = async (index) => {
}
emit('update:billing-medicines', [...props.billingMedicines, restoredItem])
}
ElMessage.success('回退成功')
ElMessage.success(t('surgicalschedule.tmp.msgRollbackSuccess'))
}
}).catch(() => {
// 用户取消
@@ -1034,13 +1039,13 @@ const isSubmitting = ref(false)
const handleSubmit = async () => {
if (!isSigned.value) {
ElMessage.warning('请先进行电子签名')
ElMessage.warning(t('surgicalschedule.tmp.msgSignFirst'))
return
}
// 🔧 防重复提交:如果正在提交,直接返回
if (isSubmitting.value) {
ElMessage.warning('正在提交医嘱,请稍候...')
ElMessage.warning(t('surgicalschedule.tmp.msgSubmitting'))
return
}
@@ -1048,7 +1053,7 @@ const handleSubmit = async () => {
// 🔧 修复签发应该处理区域一中所有待签发的药品billingMedicines而非区域二中已有数据displayAdvices
const itemsToSign = convertedAdvices.value
if (itemsToSign.length === 0) {
ElMessage.warning('没有可保存的医嘱数据')
ElMessage.warning(t('surgicalschedule.tmp.msgNoAdviceData'))
return
}
@@ -1191,7 +1196,7 @@ const handleSubmit = async () => {
const response = await savePrescription(saveData, '2')
if (response.code === 200) {
ElMessage.success('临时医嘱保存成功')
ElMessage.success(t('surgicalschedule.tmp.msgSaveSuccess'))
// 🔧 签名成功,后端已更新已有记录的 statusEnum 为 2
// 不需要手动更新 requestId签名操作是 UPDATE不是 INSERT后端不返回新 ID
@@ -1210,10 +1215,10 @@ const handleSubmit = async () => {
// 通知父组件
emit('submit', submitData)
} else {
ElMessage.error('保存医嘱失败:' + (response.msg || response.message || '未知错误'))
ElMessage.error(t('surgicalschedule.tmp.msgSaveFailed') + (response.msg || response.message || t('surgicalschedule.tmp.unknownError')))
}
} catch (error) {
ElMessage.error('保存医嘱失败,请重试')
ElMessage.error(t('surgicalschedule.tmp.msgSaveFailedRetry'))
} finally {
// 🔧 重置防重复提交标志位
isSubmitting.value = false
@@ -1561,4 +1566,4 @@ const editFormUsageLabel = computed(() => {
:deep(.el-descriptions__label) {
font-weight: bold;
}
</style>
</style>